def register(cls):
     cls.min_max_time_steps_per_frame = NewMinMaxIntProperty(
         name_min="Min Substeps",
         description_min="Minimum number of substeps per frame calculation",
         min_min=1,
         max_min=100,
         default_min=1,
         name_max="Max Substeps",
         description_max="Maximum number of substeps per frame calculation",
         min_max=1,
         max_max=100,
         default_max=8,
     )
     cls.enable_adaptive_obstacle_time_stepping = BoolProperty(
         name="Enable Adaptive Time Stepping for Obstacles",
         description="Include obstacle velocities when calculating number"
         " of frame substeps. Enabling may improve the accuracy of"
         " fluid-solid interaction for fast moving obstacles.",
         default=False,
     )
     cls.particle_jitter_factor = FloatProperty(
         name="Particle Jitter",
         description="Amount of random jitter that is added to newly spawned"
         " fluid particles. Higher values may improve simulation accuracy,"
         " but may cause 'bumpy' artifacts in the initial mesh shape.",
         min=0.0,
         max=1.0,
         default=1.0,
         precision=2,
         subtype='FACTOR',
     )
     cls.PICFLIP_ratio = FloatProperty(
         name="PIC/FLIP Ratio",
         description="Ratio of PIC velocity to FLIP velocity update mixture."
         " PIC velocity method is not very accurate, but stable. FLIP"
         " velocity method is very accurate, but less stable. Using a"
         " value of 0.0 results in a completely FLIP simulator, while"
         " using a value of 1.0 results in a completely PIC simulator.",
         min=0.0,
         max=1.0,
         default=0.05,
         precision=2,
         subtype='FACTOR',
     )
     cls.CFL_condition_number = IntProperty(
         name="Safety Factor (CFL Number)",
         description="Maximum number of grid cells a particle can travel"
         " in a single substep. A larger number may speed up simulation"
         " baking by reducing the number of required substeps at the"
         " cost of accuracy.",
         min=1,
         max=50,
         default=5,
     )
     cls.enable_extreme_velocity_removal = BoolProperty(
         name="Remove particles with extreme velocities",
         description="Attempt to remove extreme particle velocities that"
         " cause the simulator to exceed the maximum number of allowed"
         " frame substeps. Enabling this option may prevent simulation"
         " blow-up in extreme cases. Disable this option if fast moving"
         " fluid is disappearing from the simulation domain.",
         default=True,
     )
     cls.enable_gpu_features = BoolProperty(
         name="Enable GPU Features",
         description="Enable simulator to accelerate some computations"
         " with your GPU device. TIP: Compare simulation performance"
         " with this setting on/off to test what is faster on your"
         " hardware setup. Note: you may only notice a difference on"
         " higher resolution simulations.",
         default=True)
     cls.num_threads_auto_detect = IntProperty(
         name="Threads",
         description=
         "Number of threads to use simultaneously while simulating",
         min=1,
         max=1024,
         default=1,
     )
     cls.num_threads_fixed = IntProperty(
         name="Threads",
         description=
         "Number of threads to use simultaneously while simulating",
         min=1,
         max=1024,
         default=1,
     )
     cls.threading_mode = EnumProperty(
         name="Threading Mode",
         description="Determing the amount of simulation threads used",
         items=types.threading_modes,
         default='THREADING_MODE_AUTO_DETECT',
         options={'HIDDEN'},
     )
     cls.enable_asynchronous_meshing = BoolProperty(
         name="Enable Async Meshing",
         description="Run mesh generation process in a separate thread while"
         " the simulation is running. May increase simulation performance"
         " but will use more RAM if enabled.",
         default=True,
     )
     cls.precompute_static_obstacles = BoolProperty(
         name="Precompute Static Obstacles",
         description="Precompute data for static obstacles. If enabled,"
         " the simulator will avoid recomputing data for non-animated"
         " obstacles. Increases simulation performance but will use"
         " more RAM if enabled.",
         default=True,
     )
     cls.reserve_temporary_grids = BoolProperty(
         name="Reserve Temporary Grid Memory",
         description="Reserve space in memory for temporary grids. Increases"
         " simulation performance for scenes with animated or keyframed"
         " obstacles but will use more RAM if enabled.",
         default=True,
     )
     cls.experimental_optimization_features = BoolProperty(
         name="Enable Experimental Optimization Features",
         description="Enable features that may boost performance. Compare"
         " simulation performance with this setting on/off to test"
         " what is faster on your hardware setup. Note: you may only"
         " notice a difference on higher resolution simulations.",
         default=True,
     )
Example #2
0
class SvBevelNode(bpy.types.Node, SverchCustomTreeNode):
    """
    Triggers: Bevel, Round, Smooth
    Tooltip: Bevel vertices, edges and faces. Create rounded corners.
    """
    bl_idname = 'SvBevelNode'
    bl_label = 'Bevel'
    bl_icon = 'MOD_BEVEL'

    @throttled
    def mode_change(self, context):
        self.inputs[5].name = 'BevelEdges' if not self.vertexOnly else 'VerticesMask'
        if 'Spread' in self.inputs:
            self.inputs['Spread'].hide_safe = self.miter_inner == 'SHARP' and self.miter_outer == 'SHARP'

    offset_: FloatProperty(
        name='Amount', description='Amount to offset beveled edge',
        default=0.0, min=0.0, update=updateNode)

    offset_modes = [
        ("OFFSET", "Offset", "Amount is offset of new edges from original", 1),
        ("WIDTH", "Width", "Amount is width of new face", 2),
        ("DEPTH", "Depth", "Amount is perpendicular distance from original edge to bevel face", 3),
        ("PERCENT", "Percent", "Amount is percent of adjacent edge length", 4)
    ]

    offsetType: EnumProperty(
        name='Amount Type', description="What distance Amount measures",
        items=offset_modes, default='OFFSET', update=updateNode)

    segments_: IntProperty(
        name="Segments", description="Number of segments in bevel",
        default=1, min=1, update=updateNode)

    profile_: FloatProperty(
        name="Profile", description="Profile shape; 0.5 - round",
        default=0.5, min=0.0, max=1.0, update=updateNode)

    vertexOnly: BoolProperty(
        name="Vertex mode", description="Only bevel edges, not edges",
        default=False, update=mode_change)

    clamp_overlap : BoolProperty(
        name = "Clamp Overlap",
        description = "do not allow beveled edges/vertices to overlap each other",
        default = False,
        update = updateNode)

    loop_slide : BoolProperty(
        name = "Loop Slide",
        description = "prefer to slide along edges to having even widths",
        default = True,
        update = updateNode)

    miter_types = [
        ('SHARP', "Sharp", "Sharp", 0),
        ('PATCH', "Patch", "Patch", 1),
        ('ARC', "Arc", "Arc", 2)
    ]

    miter_outer : EnumProperty(
        name = "Outer",
        description = "Outer mitter type",
        items = miter_types,
        default = 'SHARP',
        update = mode_change)

    miter_inner : EnumProperty(
        name = "Inner",
        description = "Inner mitter type",
        items = miter_types,
        default = 'SHARP',
        update = mode_change)
    
    spread : FloatProperty(
        name = "Spread",
        description = "Amount to offset beveled edge",
        default = 0.0, min = 0.0,
        update = updateNode)

    def sv_init(self, context):
        si, so = self.inputs.new, self.outputs.new
        si('SvVerticesSocket', "Vertices")
        si('SvStringsSocket', 'Edges')
        si('SvStringsSocket', 'Polygons')
        si('SvStringsSocket', 'FaceData')
        si('SvStringsSocket', 'BevelFaceData')
        si('SvStringsSocket', 'BevelEdges')

        si('SvStringsSocket', "Offset").prop_name = "offset_"
        si('SvStringsSocket', "Segments").prop_name = "segments_"
        si('SvStringsSocket', "Profile").prop_name = "profile_"
        si('SvStringsSocket', "Spread").prop_name = "spread"

        so('SvVerticesSocket', 'Vertices')
        so('SvStringsSocket', 'Edges')
        so('SvStringsSocket', 'Polygons')
        so('SvStringsSocket', 'FaceData')
        so('SvStringsSocket', 'NewPolys')

        self.mode_change(context)

    def draw_buttons(self, context, layout):
        layout.prop(self, "vertexOnly")
        layout.prop(self, "clamp_overlap")
        layout.label(text="Amount type:")
        layout.prop(self, "offsetType", expand=True)

    def draw_buttons_ext(self, context, layout):
        self.draw_buttons(context, layout)
        layout.prop(self, "loop_slide")
        layout.label(text="Miter type:")
        layout.prop(self, 'miter_inner')
        layout.prop(self, 'miter_outer')

    def get_socket_data(self):
        vertices = self.inputs['Vertices'].sv_get(default=[[]])
        edges = self.inputs['Edges'].sv_get(default=[[]])
        faces = self.inputs['Polygons'].sv_get(default=[[]])
        if 'FaceData' in self.inputs:
            face_data = self.inputs['FaceData'].sv_get(default=[[]])
        else:
            face_data = [[]]
        if 'BevelFaceData' in self.inputs:
            bevel_face_data = self.inputs['BevelFaceData'].sv_get(default=[[]])
        else:
            bevel_face_data = [[]]
        if self.vertexOnly:
            mask = self.inputs['VerticesMask'].sv_get(default=[[]])
        else:
            mask = self.inputs['BevelEdges'].sv_get(default=[[]])
        offsets = self.inputs['Offset'].sv_get()[0]
        segments = self.inputs['Segments'].sv_get()[0]
        profiles = self.inputs['Profile'].sv_get()[0]
        if 'Spread' in self.inputs:
            spreads = self.inputs['Spread'].sv_get()[0]
        else:
            spreads = [0.0]
        return vertices, edges, faces, face_data, mask, offsets, segments, profiles, bevel_face_data, spreads

    def create_geom(self, bm, mask):
        if not self.vertexOnly:
            b_edges = get_bevel_edges(bm, mask)
            geom = list(bm.verts) + list(b_edges) + list(bm.faces)
        else:
            b_verts = get_bevel_verts(bm, mask)
            geom = b_verts + list(bm.edges) + list(bm.faces)
        return geom

    def process(self):

        if not (self.inputs[0].is_linked and (self.inputs[2].is_linked or self.inputs[1].is_linked)):
            return
        if not any(self.outputs[name].is_linked for name in ['Vertices', 'Edges', 'Polygons', 'NewPolys']):
            return

        verts_out = []
        edges_out = []
        faces_out = []
        face_data_out = []
        result_bevel_faces = []

        meshes = match_long_repeat(self.get_socket_data())

        for vertices, edges, faces, face_data, mask, offset, segments, profile, bevel_face_data, spread in zip(*meshes):
            if face_data:
                fullList(face_data, len(faces))
            if bevel_face_data and isinstance(bevel_face_data, (list, tuple)):
                bevel_face_data = bevel_face_data[0]
            bm = bmesh_from_pydata(vertices, edges, faces, markup_face_data=True, normal_update=True)
            geom = self.create_geom(bm, mask)

            try:
                bevel_faces = bmesh.ops.bevel(bm,
                    geom=geom,
                    offset=offset,
                    offset_type=self.offsetType,
                    segments=segments,
                    profile=profile,
                    vertex_only=self.vertexOnly,
                    clamp_overlap = self.clamp_overlap,
                    loop_slide = self.loop_slide,
                    spread = spread,
                    miter_inner = self.miter_inner,
                    miter_outer = self.miter_outer,
                    # strength= (float)
                    # hnmode= (enum in ['NONE', 'FACE', 'ADJACENT', 'FIXED_NORMAL_SHADING'], default 'NONE')
                    material=-1)['faces']
            except Exception as e:
                self.exception(e)

            new_bevel_faces = [[v.index for v in face.verts] for face in bevel_faces]
            if not face_data:
                verts, edges, faces = pydata_from_bmesh(bm)
                verts_out.append(verts)
                edges_out.append(edges)
                faces_out.append(faces)
                if bevel_face_data != []:
                    new_face_data = []
                    for face in faces:
                        if set(face) in map(set, new_bevel_faces):
                            new_face_data.append(bevel_face_data)
                        else:
                            new_face_data.append(None)
                    face_data_out.append(new_face_data)
                else:
                    face_data_out.append([])
            else:
                verts, edges, faces, new_face_data = pydata_from_bmesh(bm, face_data)
                verts_out.append(verts)
                edges_out.append(edges)
                faces_out.append(faces)
                if bevel_face_data != []:
                    new_face_data_m = []
                    for data, face in zip(new_face_data, faces):
                        if set(face) in map(set, new_bevel_faces):
                            new_face_data_m.append(bevel_face_data)
                        else:
                            new_face_data_m.append(data)
                    face_data_out.append(new_face_data_m)
                else:
                    face_data_out.append(new_face_data)
            bm.free()
            result_bevel_faces.append(new_bevel_faces)

        self.outputs['Vertices'].sv_set(verts_out)
        self.outputs['Edges'].sv_set(edges_out)
        self.outputs['Polygons'].sv_set(faces_out)
        if 'FaceData' in self.outputs:
            self.outputs['FaceData'].sv_set(face_data_out)
        self.outputs['NewPolys'].sv_set(result_bevel_faces)
Example #3
0
def register():
    bpy.utils.register_class(SampleGeneratorPanel)

    # bpy.types.Scene.sg_label_mode = EnumProperty(
    #   items = [('sgSegment', 'Segmented','Segment'), ('sgBBox', 'Bounding Box','Bounding Box')],
    #   name = "Label Mode",
    #   description = "Controls which kind of labels are generated." )

    # bpy.types.Scene.sg_render_mode = EnumProperty(
    #   items = [('sgBackground', 'Background','Background'), ('sgCropped', 'Cropped','Cropped')],
    #   name = "Render Mode",
    #   description = "The rendering Mode.")

    bpy.types.Scene.sg_objectGroup = PointerProperty(
        type=bpy.types.Group,
        name="Object Group",
        description="An Object group with all objects that are to be rendered."
    )
    bpy.types.Scene.sg_backgroundPath = StringProperty(
        subtype="FILE_PATH",
        name="Background Path",
        description="Path to background images.")

    bpy.types.Scene.sg_nSamples = IntProperty(
        name="Number Samples",
        min=0,
        max=999999999,
        description="Number of generated Samples.")

    bpy.types.Scene.sg_cam = PointerProperty(
        name="Camera",
        type=bpy.types.Object,
        description="The scenes camera Object. (needed for perspective changes)"
    )
    bpy.types.Scene.sg_sun = PointerProperty(
        name="Sun",
        type=bpy.types.Object,
        description=
        "The scenes Lightsource. (needed for light rotation and intensity adjustments)"
    )
    bpy.types.Scene.sg_ground = PointerProperty(
        name="Ground",
        type=bpy.types.Object,
        description=
        "The scenes Ground Object. (will be set to shadow catcher and disabled for shadowless rendering)"
    )
    bpy.types.Scene.sg_cam_target = PointerProperty(
        name="Camera Target",
        type=bpy.types.Object,
        description="The camera Target. (Camera is always pointed at this)")
    bpy.types.Scene.sg_cam_dist = FloatProperty(
        name="Camera distance",
        default=2.2,
        subtype='DISTANCE',
        unit='LENGTH',
        description="Cameras distance to Objects.")
    bpy.types.Scene.sg_img_size = IntVectorProperty(
        name="Image Size",
        size=2,
        default=(300, 300),
        description=
        "Size of the rendered image (In Background rendering this is set to size of background image)."
    )

    bpy.utils.register_class(GenerateSamplesOperator)
    bpy.types.INFO_MT_render.append(menu_func)
class SFR_Settings(PropertyGroup):

    #### SETTINGS OPTIMIZER ####

    detection_method: EnumProperty(
        name="Optimization Method",
        items=(
            ('MANUAL', 'Manual', 'Manual Scene Optimizer'),
            ('AUTOMATIC', 'Automatic', 'Automatic Scene Optimizer'),
        ),
        default='AUTOMATIC',
        description=
        "Optimization method, manual for basic setups, automatic for more precise settings",
        options=set(),  # Not animatable!
    )
    threshold: FloatProperty(
        name="Threshold",
        default=0.1,
        max=1,
        min=0.01,
        description=
        "Threshold on which the next benchmark method should set in",
        options=set(),  # Not animatable!
    )
    resolution: IntProperty(
        name="Benchmark Res",
        default=5,
        max=20,
        min=1,
        description=
        "Resolution the benchmark should run, higher = more precision but slower",
        options=set(),  # Not animatable!
    )
    frame_skipped: IntProperty(
        name="Frame Offset",
        default=10,
        max=20,
        min=1,
        description="Frames between automatic benchmarks",
        options=set(),  # Not animatable!
    )
    inputdir: StringProperty(
        name="Benchmark Folder",
        default="C:/temp/",
        description="Benchmarking Frames will be saved here",
        subtype='DIR_PATH',
        maxlen=1024,
        options=set(),  # Not animatable!
    )
    use_diffuse: BoolProperty(name="Diffuse",
                              default=True,
                              description="Benchmark diffuse")
    use_glossy: BoolProperty(name="Glossy",
                             default=True,
                             description="Benchmark glossy")
    use_transparent: BoolProperty(name="Transparency",
                                  default=True,
                                  description="Benchmark transparency")
    use_transmission: BoolProperty(name="Transmission",
                                   default=True,
                                   description="Benchmark transmission")
    use_volume: BoolProperty(name="Volume",
                             default=True,
                             description="Benchmark volume")
    use_indirect: BoolProperty(name="Indirect Brightness",
                               default=True,
                               description="Benchmark indirect brightness")
    use_caustics: BoolProperty(name="Caustics",
                               default=False,
                               description="Benchmark caustic blur")

    #### TEXTURE OPTIMIZER ####

    diffuse_resize: IntProperty(
        name="Diffuse / Albedo",
        default=0,
        max=7,
        min=0,
        description=
        "the factor by which the diffuse or albedo textures will be scaled down, 0 = unaffected \nrecommended: 0",
        options=set(),  # Not animatable!
    )
    ao_resize: IntProperty(
        name="Ambient Occlusion",
        default=2,
        max=7,
        min=0,
        description=
        "the factor by which the ambient occlusion textures will be scaled down, 0 = unaffected \nrecommended: 2",
        options=set(),  # Not animatable!
    )
    specular_resize: IntProperty(
        name="Specular / Metallic",
        default=2,
        max=7,
        min=0,
        description=
        "the factor by which the specular or metallic textures will be scaled down, 0 = unaffected \nrecommended: 2",
        options=set(),  # Not animatable!
    )
    roughness_resize: IntProperty(
        name="Roughness / Glossiness",
        default=2,
        max=7,
        min=0,
        description=
        "the factor by which the roughness or glossiness textures will be scaled down, 0 = unaffected \nrecommended: 2",
        options=set(),  # Not animatable!
    )
    normal_resize: IntProperty(
        name="Normal / Bump",
        default=1,
        max=7,
        min=0,
        description=
        "the factor by which the normal or bump textures will be scaled down, 0 = unaffected \nrecommended: 1",
        options=set(),  # Not animatable!
    )
    opacity_resize: IntProperty(
        name="Opacity / Transparency",
        default=1,
        max=7,
        min=0,
        description=
        "the factor by which the opacity or transparency textures will be scaled down, 0 = unaffected \nrecommended: 1",
        options=set(),  # Not animatable!
    )
    translucency_resize: IntProperty(
        name="Translucency",
        default=1,
        max=7,
        min=0,
        description=
        "the factor by which the translucency textures will be scaled down, 0 = unaffected \nrecommended: 1",
        options=set(),  # Not animatable!
    )
    create_backup: BoolProperty(
        name="Create Backup",
        default=True,
        description=
        'Creates a backup of all the image files in the folder "textures backup"\nwe heavily recommend to keep this enabled'
    )
Example #5
0
class SHIPGENERATOR_OT_hull(Operator):
    bl_label = "Shipgenerator hull"
    bl_idname = "shipgenerator.hull"
    bl_description = "Create a hull surface"
    bl_space_type = "VIEW_3D"
    bl_region_type = "UI"
    bl_options = {'REGISTER', 'UNDO'}

    width: IntProperty(name="Hull Width",
                       default=4,
                       min=0,
                       max=15,
                       description="Used as a width property")

    seed: IntProperty(
        name="Generational Seed",
        default=1,
        min=-99999999,
        max=99999999,
        description="Used for randomizing the seed of generation")

    def invoke(self, context, event):
        return context.window_manager.invoke_props_dialog(self)

    def create_surface(self,
                       context,
                       p_name: str,
                       p_location: [float, float, float],
                       p_collection=None,
                       p_parent: Object = None):
        bpy.ops.surface.primitive_nurbs_surface_surface_add()
        new_surface = context.object
        new_surface.name = p_name
        new_surface.location = p_location
        new_surface.parent = p_parent

        new_surface.data.splines[0].use_endpoint_u = True
        new_surface.data.splines[0].use_endpoint_v = True
        new_surface.data.splines[0].use_smooth = False

        self.set_random_positions(new_surface, 0, 0, 0)

        if p_collection is not None:
            context.collection.objects.unlink(new_surface)
            p_collection.objects.link(new_surface)

        return new_surface

    def get_point_y_z(self, p_surface, p_z_row: int, p_y_column: int,
                      p_width: int):
        index = p_y_column * p_width + p_z_row
        return p_surface.data.splines[0].points[index]

    def get_point_index(p_surface, p_index: int):
        return p_surface.data.splines[0].points[p_index]

    def set_random_positions(self,
                             p_surface: bpy.types.SurfaceCurve,
                             p_min_x: int,
                             p_max_x: int,
                             p_seed: int,
                             p_y_offset=2,
                             p_z_offset=2):
        y_start = 0

        row_x = [p_min_x, p_min_x, p_min_x, p_min_x]
        if p_min_x != p_max_x:
            logging.info("Will Randomize X position")

            random.seed(p_seed)

            row_x = [
                0,
                random.randrange(p_min_x, p_max_x),
                random.randrange(p_min_x, p_max_x),
                random.randrange(p_min_x, p_max_x)
            ]

        row_index = 0
        for point in p_surface.data.splines[0].points:
            position = point.co

            position[0] = row_x[row_index]
            position[1] = y_start
            position[2] = p_z_offset * row_index

            if row_index < 3:
                row_index += 1
            else:
                row_index = 0
                y_start += p_y_offset

    def set_column_points_to_position(self, p_surface, p_y: int, p_width: int,
                                      p_position: []):
        for z_index in range(0, p_width):
            point = self.get_point_y_z(p_surface, z_index, p_y, p_width)
            point.co = p_position[z_index]

    def get_column_points_positions(self, p_surface, p_y: int, p_width: int):
        points_position = []
        for row_index in range(0, p_width):
            point = self.get_point_y_z(p_surface, row_index, p_y, p_width)
            points_position.append(point.co)

        return points_position

    def execute(self, context):
        hull_collection = bpy.data.collections.new('Hull')
        context.scene.collection.children.link(hull_collection)

        surface = self.create_surface(context, "Hull_Main_Stern",
                                      [0.0, 0.0, 0.0], hull_collection)

        self.set_random_positions(surface, 3, 6, self.seed, 3, 2)

        surface_two = self.create_surface(context, "Hull_Main_Bow",
                                          [0.0, 9.0, 0.0], hull_collection,
                                          surface)

        for column_index in range(0, 4):
            surface_positions = self.get_column_points_positions(
                surface, column_index, 4)

            self.set_column_points_to_position(surface_two, column_index, 4,
                                               surface_positions)

        surface_bow = self.create_surface(context, "Hull_Bow", [0, 18, 0],
                                          hull_collection, surface)

        self.set_random_positions(surface_bow, 3, 6, self.seed,
                                  random.randrange(2, 7), 2)

        surface_positions = self.get_column_points_positions(surface, 0, 4)

        self.set_column_points_to_position(surface_bow, 0, 4,
                                           surface_positions)

        self.set_column_points_to_position(surface_bow, 3, 4, [(0, 16, 1, 1),
                                                               (0, 17, 3, 1),
                                                               (0, 18, 4, 1),
                                                               (0, 18, 6, 1)])

        return {'FINISHED'}
Example #6
0
class GenerateCollisionMesh(RDOperator):
    """
    :ref:`operator` for creating a collision mesh using the builtin
    subdivide and shrinkwrap operators.

    **Preconditions:**

    **Postconditions:**
    """
    bl_idname = config.OPERATOR_PREFIX + "generatecollisionmesh"
    bl_label = "Generate Collision Mesh for selected"

    shrinkWrapOffset = FloatProperty(name="Shrinkwrap Offset",
                                     default=0.001,
                                     unit='LENGTH',
                                     min=0,
                                     max=0.5)
    subdivisionLevels = IntProperty(name="Subdivision Levels", default=2)

    @classmethod
    def run(cls, shrinkWrapOffset, subdivisionLevels):
        return super().run(**cls.pass_keywords())

    @RDOperator.OperatorLogger
    def execute(self, context):
        from . import segments, model

        target_name = [
            i.name for i in bpy.context.selected_objects if i.type == 'MESH'
        ][0]
        self.logger.debug("Creating Collision mesh for: %s", target_name)
        armature = context.active_object.name

        bpy.ops.object.select_all(action='DESELECT')
        bpy.context.scene.objects.active = bpy.data.objects[target_name]

        d = bpy.data.objects[target_name].dimensions
        bpy.ops.mesh.primitive_cube_add(
            location=bpy.data.objects[target_name].location,
            rotation=bpy.data.objects[target_name].rotation_euler)
        bpy.context.object.dimensions = d * 1000000
        bpy.ops.object.transform_apply(scale=True)
        mod = bpy.context.object.modifiers.new(name='subsurf', type='SUBSURF')
        mod.subdivision_type = 'SIMPLE'
        mod.levels = self.subdivisionLevels
        bpy.ops.object.modifier_apply(modifier='subsurf')
        mod = bpy.context.object.modifiers.new(name='shrink_wrap',
                                               type='SHRINKWRAP')
        mod.wrap_method = "NEAREST_SURFACEPOINT"
        mod.offset = self.shrinkWrapOffset * 1000
        self.logger.debug("%f, %f", mod.offset, self.shrinkWrapOffset)
        mod.target = bpy.data.objects[target_name]
        bpy.ops.object.modifier_apply(modifier='shrink_wrap')

        if not bpy.context.object.name.startswith("COL_"):
            bpy.context.object.name = 'COL_' + target_name[4:]
        name = bpy.context.object.name

        context.active_object.RobotEditor.tag = 'COLLISION'
        self.logger.debug("Created mesh: %s", bpy.context.active_object.name)

        if 'RD_COLLISON_OBJECT_MATERIAL' in bpy.data.materials:
            bpy.ops.object.material_slot_add()
            context.active_object.data.materials[0] = bpy.data.materials[
                'RD_COLLISON_OBJECT_MATERIAL']
            self.logger.debug("Assigned material to : %s",
                              bpy.context.active_object.name)
        else:
            self.logger.debug("Could not find material for collision mesh")

        bpy.ops.object.select_all(action='DESELECT')

        model.SelectModel.run(model_name=armature)
        segments.SelectSegment.run(
            segment_name=bpy.data.objects[target_name].parent_bone)
        bpy.data.objects[name].select = True
        bpy.ops.object.parent_set(type='BONE', keep_transform=True)
        bpy.ops.object.select_all(action='DESELECT')
        model.SelectModel.run(model_name=armature)

        return {'FINISHED'}

    def invoke(self, context, event):
        return context.window_manager.invoke_props_dialog(self)
Example #7
0
class QuickExplode(ObjectModeOperator, Operator):
    """Make selected objects explode"""
    bl_idname = "object.quick_explode"
    bl_label = "Quick Explode"
    bl_options = {'REGISTER', 'UNDO'}

    style: EnumProperty(
        name="Explode Style",
        items=(
            ('EXPLODE', "Explode", ""),
            ('BLEND', "Blend", ""),
        ),
        default='EXPLODE',
    )
    amount: IntProperty(
        name="Number of Pieces",
        min=2,
        max=10000,
        soft_min=2,
        soft_max=10000,
        default=100,
    )
    frame_duration: IntProperty(
        name="Duration",
        min=1,
        max=300000,
        soft_min=1,
        soft_max=10000,
        default=50,
    )

    frame_start: IntProperty(
        name="Start Frame",
        min=1,
        max=300000,
        soft_min=1,
        soft_max=10000,
        default=1,
    )
    frame_end: IntProperty(
        name="End Frame",
        min=1,
        max=300000,
        soft_min=1,
        soft_max=10000,
        default=10,
    )

    velocity: FloatProperty(
        name="Outwards Velocity",
        min=0,
        max=300000,
        soft_min=0,
        soft_max=10,
        default=1,
    )

    fade: BoolProperty(
        name="Fade",
        description="Fade the pieces over time",
        default=True,
    )

    def execute(self, context):
        fake_context = context.copy()
        obj_act = context.active_object

        if obj_act is None or obj_act.type != 'MESH':
            self.report({'ERROR'}, "Active object is not a mesh")
            return {'CANCELLED'}

        mesh_objects = [
            obj for obj in context.selected_objects
            if obj.type == 'MESH' and obj != obj_act
        ]
        mesh_objects.insert(0, obj_act)

        if self.style == 'BLEND' and len(mesh_objects) != 2:
            self.report({'ERROR'}, "Select two mesh objects")
            self.style = 'EXPLODE'
            return {'CANCELLED'}
        elif not mesh_objects:
            self.report({'ERROR'}, "Select at least one mesh object")
            return {'CANCELLED'}

        for obj in mesh_objects:
            if obj.particle_systems:
                self.report({'ERROR'}, "Object %r already has a "
                            "particle system" % obj.name)

                return {'CANCELLED'}

        if self.style == 'BLEND':
            from_obj = mesh_objects[1]
            to_obj = mesh_objects[0]

        for obj in mesh_objects:
            fake_context["object"] = obj
            bpy.ops.object.particle_system_add(fake_context)

            settings = obj.particle_systems[-1].settings
            settings.count = self.amount
            # first set frame end, to prevent frame start clamping
            settings.frame_end = self.frame_end - self.frame_duration
            settings.frame_start = self.frame_start
            settings.lifetime = self.frame_duration
            settings.normal_factor = self.velocity
            settings.render_type = 'NONE'

            explode = obj.modifiers.new(name='Explode', type='EXPLODE')
            explode.use_edge_cut = True

            if self.fade:
                explode.show_dead = False
                uv = obj.data.uv_layers.new(name="Explode fade")
                explode.particle_uv = uv.name

                mat = object_ensure_material(obj, "Explode Fade")
                mat.blend_method = 'BLEND'
                mat.shadow_method = 'HASHED'
                if not mat.use_nodes:
                    mat.use_nodes = True

                nodes = mat.node_tree.nodes
                for node in nodes:
                    if node.type == 'OUTPUT_MATERIAL':
                        node_out_mat = node
                        break

                node_surface = node_out_mat.inputs['Surface'].links[
                    0].from_node

                node_x = node_surface.location[0]
                node_y = node_surface.location[1] - 400
                offset_x = 200

                node_mix = nodes.new('ShaderNodeMixShader')
                node_mix.location = (node_x - offset_x, node_y)
                mat.node_tree.links.new(node_surface.outputs[0],
                                        node_mix.inputs[1])
                mat.node_tree.links.new(node_mix.outputs["Shader"],
                                        node_out_mat.inputs['Surface'])
                offset_x += 200

                node_trans = nodes.new('ShaderNodeBsdfTransparent')
                node_trans.location = (node_x - offset_x, node_y)
                mat.node_tree.links.new(node_trans.outputs["BSDF"],
                                        node_mix.inputs[2])
                offset_x += 200

                node_ramp = nodes.new('ShaderNodeValToRGB')
                node_ramp.location = (node_x - offset_x, node_y)
                offset_x += 200
                mat.node_tree.links.new(node_ramp.outputs["Alpha"],
                                        node_mix.inputs["Fac"])
                color_ramp = node_ramp.color_ramp
                color_ramp.elements[0].color[3] = 0.0
                color_ramp.elements[1].color[3] = 1.0

                if self.style == 'BLEND':
                    color_ramp.elements[0].position = 0.333
                    color_ramp.elements[1].position = 0.666
                    if obj == to_obj:
                        # reverse ramp alpha
                        color_ramp.elements[0].color[3] = 1.0
                        color_ramp.elements[1].color[3] = 0.0

                node_sep = nodes.new('ShaderNodeSeparateXYZ')
                node_sep.location = (node_x - offset_x, node_y)
                offset_x += 200
                mat.node_tree.links.new(node_sep.outputs["X"],
                                        node_ramp.inputs["Fac"])

                node_uv = nodes.new('ShaderNodeUVMap')
                node_uv.location = (node_x - offset_x, node_y)
                node_uv.uv_map = uv.name
                mat.node_tree.links.new(node_uv.outputs["UV"],
                                        node_sep.inputs["Vector"])

            if self.style == 'BLEND':
                settings.physics_type = 'KEYED'
                settings.use_emit_random = False
                settings.rotation_mode = 'NOR'

                psys = obj.particle_systems[-1]

                fake_context["particle_system"] = obj.particle_systems[-1]
                bpy.ops.particle.new_target(fake_context)
                bpy.ops.particle.new_target(fake_context)

                if obj == from_obj:
                    psys.targets[1].object = to_obj
                else:
                    psys.targets[0].object = from_obj
                    settings.normal_factor = -self.velocity
                    explode.show_unborn = False
                    explode.show_dead = True
            else:
                settings.factor_random = self.velocity
                settings.angular_velocity_factor = self.velocity / 10.0

        return {'FINISHED'}

    def invoke(self, context, _event):
        self.frame_start = context.scene.frame_current
        self.frame_end = self.frame_start + self.frame_duration
        return self.execute(context)
Example #8
0
class LodGenerate(Operator):
    """Generate levels of detail using the decimate modifier"""
    bl_idname = "object.lod_generate"
    bl_label = "Generate Levels of Detail"
    bl_options = {'REGISTER', 'UNDO'}

    count = IntProperty(
        name="Count",
        default=3,
    )
    target = FloatProperty(
        name="Target Size",
        min=0.0,
        max=1.0,
        default=0.1,
    )
    package = BoolProperty(
        name="Package into Group",
        default=False,
    )

    @classmethod
    def poll(cls, context):
        return (context.active_object is not None)

    def execute(self, context):
        scene = context.scene
        ob = scene.objects.active

        lod_name = ob.name
        lod_suffix = "lod"
        lod_prefix = ""
        if lod_name.lower().endswith("lod0"):
            lod_suffix = lod_name[-3:-1]
            lod_name = lod_name[:-3]
        elif lod_name.lower().startswith("lod0"):
            lod_suffix = ""
            lod_prefix = lod_name[:3]
            lod_name = lod_name[4:]

        group_name = lod_name.strip(' ._')
        if self.package:
            try:
                bpy.ops.object.group_link(group=group_name)
            except TypeError:
                bpy.ops.group.create(name=group_name)

        step = (1.0 - self.target) / (self.count - 1)
        for i in range(1, self.count):
            scene.objects.active = ob
            bpy.ops.object.duplicate()
            lod = context.selected_objects[0]

            scene.objects.active = ob
            bpy.ops.object.lod_add()
            scene.objects.active = lod

            if lod_prefix:
                lod.name = lod_prefix + str(i) + lod_name
            else:
                lod.name = lod_name + lod_suffix + str(i)

            lod.location.y = ob.location.y + 3.0 * i

            if i == 1:
                modifier = lod.modifiers.new("lod_decimate", 'DECIMATE')
            else:
                modifier = lod.modifiers[-1]

            modifier.ratio = 1.0 - step * i

            ob.lod_levels[i].object = lod

            if self.package:
                bpy.ops.object.group_link(group=group_name)
                lod.parent = ob

        if self.package:
            for level in ob.lod_levels[1:]:
                level.object.hide = level.object.hide_render = True

        lod.select = False
        ob.select = True
        scene.objects.active = ob

        return {'FINISHED'}
Example #9
0
class SubdivisionSet(Operator):
    """Sets a Subdivision Surface Level (1-5)"""

    bl_idname = "object.subdivision_set"
    bl_label = "Subdivision Set"
    bl_options = {'REGISTER', 'UNDO'}

    level: IntProperty(
        name="Level",
        min=-100,
        max=100,
        soft_min=-6,
        soft_max=6,
        default=1,
    )
    relative: BoolProperty(
        name="Relative",
        description=("Apply the subsurf level as an offset "
                     "relative to the current level"),
        default=False,
    )

    @classmethod
    def poll(cls, context):
        obs = context.selected_editable_objects
        return (obs is not None)

    def execute(self, context):
        level = self.level
        relative = self.relative

        if relative and level == 0:
            return {'CANCELLED'}  # nothing to do

        if not relative and level < 0:
            self.level = level = 0

        def set_object_subd(obj):
            for mod in obj.modifiers:
                if mod.type == 'MULTIRES':
                    if not relative:
                        if level > mod.total_levels:
                            sub = level - mod.total_levels
                            for _ in range(sub):
                                bpy.ops.object.multires_subdivide(
                                    modifier="Multires")

                        if obj.mode == 'SCULPT':
                            if mod.sculpt_levels != level:
                                mod.sculpt_levels = level
                        elif obj.mode == 'OBJECT':
                            if mod.levels != level:
                                mod.levels = level
                        return
                    else:
                        if obj.mode == 'SCULPT':
                            if mod.sculpt_levels + level <= mod.total_levels:
                                mod.sculpt_levels += level
                        elif obj.mode == 'OBJECT':
                            if mod.levels + level <= mod.total_levels:
                                mod.levels += level
                        return

                elif mod.type == 'SUBSURF':
                    if relative:
                        mod.levels += level
                    else:
                        if mod.levels != level:
                            mod.levels = level

                    return

            # add a new modifier
            try:
                if obj.mode == 'SCULPT':
                    mod = obj.modifiers.new("Multires", 'MULTIRES')
                    if level > 0:
                        for _ in range(level):
                            bpy.ops.object.multires_subdivide(
                                modifier="Multires")
                else:
                    mod = obj.modifiers.new("Subdivision", 'SUBSURF')
                    mod.levels = level
            except:
                self.report({'WARNING'},
                            "Modifiers cannot be added to object: " + obj.name)

        for obj in context.selected_editable_objects:
            set_object_subd(obj)

        return {'FINISHED'}
Example #10
0
class ImportGLTF2(Operator, ImportHelper):
    """Load a glTF 2.0 file"""
    bl_idname = 'import_scene.gltf'
    bl_label = 'Import glTF 2.0'

    filter_glob: StringProperty(default="*.glb;*.gltf", options={'HIDDEN'})

    files: CollectionProperty(
        name="File Path",
        type=bpy.types.OperatorFileListElement,
    )

    loglevel: IntProperty(name='Log Level', description="Log Level")

    import_pack_images: BoolProperty(
        name='Pack images',
        description='Pack all images into .blend file',
        default=True)

    import_shading: EnumProperty(
        name="Shading",
        items=(("NORMALS", "Use Normal Data", ""),
               ("FLAT", "Flat Shading", ""), ("SMOOTH", "Smooth Shading", "")),
        description="How normals are computed during import",
        default="NORMALS")

    def draw(self, context):
        layout = self.layout

        layout.prop(self, 'import_pack_images')
        layout.prop(self, 'import_shading')

    def execute(self, context):
        return self.import_gltf2(context)

    def import_gltf2(self, context):
        import os

        self.set_debug_log()
        import_settings = self.as_keywords()

        if self.files:
            # Multiple file import
            ret = {'CANCELLED'}
            dirname = os.path.dirname(self.filepath)
            for file in self.files:
                path = os.path.join(dirname, file.name)
                if self.unit_import(path, import_settings) == {'FINISHED'}:
                    ret = {'FINISHED'}
            return ret
        else:
            # Single file import
            return self.unit_import(self.filepath, import_settings)

    def unit_import(self, filename, import_settings):
        import time
        from .io.imp.gltf2_io_gltf import glTFImporter
        from .blender.imp.gltf2_blender_gltf import BlenderGlTF

        self.gltf_importer = glTFImporter(filename, import_settings)
        success, txt = self.gltf_importer.read()
        if not success:
            self.report({'ERROR'}, txt)
            return {'CANCELLED'}
        success, txt = self.gltf_importer.checks()
        if not success:
            self.report({'ERROR'}, txt)
            return {'CANCELLED'}
        self.gltf_importer.log.critical(
            "Data are loaded, start creating Blender stuff")
        start_time = time.time()
        BlenderGlTF.create(self.gltf_importer)
        elapsed_s = "{:.2f}s".format(time.time() - start_time)
        self.gltf_importer.log.critical("glTF import finished in " + elapsed_s)
        self.gltf_importer.log.removeHandler(self.gltf_importer.log_handler)

        return {'FINISHED'}

    def set_debug_log(self):
        import logging
        if bpy.app.debug_value == 0:
            self.loglevel = logging.CRITICAL
        elif bpy.app.debug_value == 1:
            self.loglevel = logging.ERROR
        elif bpy.app.debug_value == 2:
            self.loglevel = logging.WARNING
        elif bpy.app.debug_value == 3:
            self.loglevel = logging.INFO
        else:
            self.loglevel = logging.NOTSET
Example #11
0
class UVEditorSettings(PropertyGroup):
    initialized: BoolProperty(default=False)

    show_stretch: BoolProperty(
        name="Display Stretch",
        description=
        "Display faces colored according to the difference in shape between UVs and their 3D coordinates (blue for low distortion, red for high distortion)",
        default=False)
    display_stretch_type: EnumProperty(
        name="Display Stretch Type",
        description="Type of stretch to draw",
        items={('ANGLE', "Angle", "Angle distortion between UV and 3D angles",
                0),
               ('AREA', "Area", "Area distortion between UV and 3D faces", 1)},
        default='ANGLE')
    uv_opacity: FloatProperty(name="UV Opacity",
                              description="Opacity of UV overlays",
                              default=1.0,
                              min=0.0,
                              max=1.0)
    edge_display_type: EnumProperty(
        name="Display style for UV edges",
        description="Type of stretch to draw",
        items={('OUTLINE', "Outline", "Display white edges with black outline",
                0), ('DASH', "Dash", "Display dashed black-white edges", 1),
               ('BLACK', "Black", "Display black edges", 2),
               ('WHITE', "White", "Display white edges", 3)},
        default='OUTLINE')
    show_modified_edges: BoolProperty(
        name="Modified Edges",
        description="Display edges after modifiers are applied",
        default=False)
    show_faces: BoolProperty(name="Faces",
                             description="Display faces over the image",
                             default=True)
    show_metadata: BoolProperty(
        name="Show Metadata",
        description="Display metadata properties of the image",
        default=True)

    tile_grid_shape: IntVectorProperty(
        name="UDIM Grid Shape",
        description="How many tiles will be shown in the background",
        size=2,
        default=(0, 0),
        min=0,
        max=100)
    use_custom_grid: BoolProperty(
        name="Custom Grid",
        description="Use a grid with a user-defined number of steps",
        default=True)
    custom_grid_subdivisions: IntProperty(
        name="Dynamic Grid Size",
        description="Number of Grid units in UV space that make one UV Unit",
        default=10,
        min=1,
        max=100)

    show_region_toolbar: BoolProperty(name="Show Toolbar",
                                      description="",
                                      default=False)
    show_region_ui: BoolProperty(name="Show Sidebar",
                                 description="",
                                 default=False)
    show_region_tool_header: BoolProperty(name="Show Tool Settings",
                                          description="",
                                          default=False)
    show_region_hud: BoolProperty(name="Show Adjust Last Operation",
                                  description="",
                                  default=False)

    pixel_snap_mode: EnumProperty(
        name="Snap to Pixels",
        description="",
        items={('DISABLED', "Disabled", "Don't snap to pixels", 0),
               ('CORNER', "Corner", "Snap to pixel corners", 1),
               ('CENTER', "Center", "Snap to pixel centers", 2)},
        default='DISABLED')
    lock_bounds: BoolProperty(
        name="Constrain to Image Bounds",
        description="Constraint to stay within the image bounds while editing",
        default=False)
    use_live_unwrap: BoolProperty(
        name="Live Unwrap",
        description=
        "Continuously unwrap the selected island while transforming pinned vertices",
        default=False)

    def set(self, area):
        space = area.spaces[0]
        uv_editor = space.uv_editor

        uv_editor.show_stretch = self.show_stretch
        uv_editor.display_stretch_type = self.display_stretch_type
        uv_editor.uv_opacity = self.uv_opacity
        uv_editor.edge_display_type = self.edge_display_type
        uv_editor.show_modified_edges = self.show_modified_edges
        uv_editor.show_faces = self.show_faces
        uv_editor.show_metadata = self.show_metadata
        uv_editor.tile_grid_shape = self.tile_grid_shape
        uv_editor.use_custom_grid = self.use_custom_grid
        uv_editor.custom_grid_subdivisions = self.custom_grid_subdivisions

        space.show_region_toolbar = self.show_region_toolbar
        space.show_region_ui = self.show_region_ui
        space.show_region_tool_header = self.show_region_tool_header
        space.show_region_hud = self.show_region_hud

        uv_editor.pixel_snap_mode = self.pixel_snap_mode
        uv_editor.lock_bounds = self.lock_bounds
        uv_editor.use_live_unwrap = self.use_live_unwrap

    def save_from_area(self, area):
        space = area.spaces[0]
        uv_editor = space.uv_editor

        self.show_stretch = uv_editor.show_stretch
        self.display_stretch_type = uv_editor.display_stretch_type
        self.uv_opacity = uv_editor.uv_opacity
        self.edge_display_type = uv_editor.edge_display_type
        self.show_modified_edges = uv_editor.show_modified_edges
        self.show_faces = uv_editor.show_faces
        self.show_metadata = uv_editor.show_metadata
        self.tile_grid_shape = uv_editor.tile_grid_shape
        self.use_custom_grid = uv_editor.use_custom_grid
        self.custom_grid_subdivisions = uv_editor.custom_grid_subdivisions

        self.show_region_toolbar = space.show_region_toolbar
        self.show_region_ui = space.show_region_ui
        self.show_region_tool_header = space.show_region_tool_header
        self.show_region_hud = space.show_region_hud

        self.pixel_snap_mode = uv_editor.pixel_snap_mode
        self.lock_bounds = uv_editor.lock_bounds
        self.use_live_unwrap = uv_editor.use_live_unwrap

    def save_from_property(self, property):
        self.show_stretch = property.show_stretch
        self.display_stretch_type = property.display_stretch_type
        self.uv_opacity = property.uv_opacity
        self.edge_display_type = property.edge_display_type
        self.show_modified_edges = property.show_modified_edges
        self.show_faces = property.show_faces
        self.show_metadata = property.show_metadata
        self.tile_grid_shape = property.tile_grid_shape
        self.use_custom_grid = property.use_custom_grid
        self.custom_grid_subdivisions = property.custom_grid_subdivisions

        self.show_region_toolbar = property.show_region_toolbar
        self.show_region_ui = property.show_region_ui
        self.show_region_tool_header = property.show_region_tool_header
        self.show_region_hud = property.show_region_hud

        self.pixel_snap_mode = property.pixel_snap_mode
        self.lock_bounds = property.lock_bounds
        self.use_live_unwrap = property.use_live_unwrap
Example #12
0
class ExportGLTF2_Base:
    # TODO: refactor to avoid boilerplate

    def __init__(self):
        from io_scene_gltf2.io.exp import gltf2_io_draco_compression_extension
        self.is_draco_available = gltf2_io_draco_compression_extension.dll_exists(
        )

    bl_options = {'UNDO', 'PRESET'}

    export_format: EnumProperty(
        name='Format',
        items=
        (('GLB', 'glTF Binary (.glb)',
          'Exports a single file, with all data packed in binary form. '
          'Most efficient and portable, but more difficult to edit later'),
         ('GLTF_EMBEDDED', 'glTF Embedded (.gltf)',
          'Exports a single file, with all data packed in JSON. '
          'Less efficient than binary, but easier to edit later'),
         ('GLTF_SEPARATE', 'glTF Separate (.gltf + .bin + textures)',
          'Exports multiple files, with separate JSON, binary and texture data. '
          'Easiest to edit later')),
        description=(
            'Output format and embedding options. Binary is most efficient, '
            'but JSON (embedded or separate) may be easier to edit later'),
        default='GLB')

    ui_tab: EnumProperty(
        items=(('GENERAL', "General", "General settings"),
               ('MESHES', "Meshes", "Mesh settings"), ('OBJECTS', "Objects",
                                                       "Object settings"),
               ('ANIMATION', "Animation", "Animation settings")),
        name="ui_tab",
        description="Export setting categories",
    )

    export_copyright: StringProperty(
        name='Copyright',
        description='Legal rights and conditions for the model',
        default='')

    export_image_format: EnumProperty(
        name='Images',
        items=
        (('NAME', 'Automatic',
          'Determine the image format from the blender image name'),
         ('JPEG', 'JPEG Format (.jpg)',
          'Encode and save textures as .jpg files. Be aware of a possible loss in quality'
          ), ('PNG', 'PNG Format (.png)',
              'Encode and save textures as .png files')),
        description=
        ('Output format for images. PNG is lossless and generally preferred, but JPEG might be preferable for web '
         'applications due to the smaller file size'),
        default='NAME')

    export_texcoords: BoolProperty(
        name='UVs',
        description='Export UVs (texture coordinates) with meshes',
        default=True)

    export_normals: BoolProperty(
        name='Normals',
        description='Export vertex normals with meshes',
        default=True)

    export_draco_mesh_compression_enable: BoolProperty(
        name='Draco mesh compression',
        description='Compress mesh using Draco',
        default=False)

    export_draco_mesh_compression_level: IntProperty(
        name='Compression level',
        description=
        'Compression level (0 = most speed, 6 = most compression, higher values currently not supported)',
        default=6,
        min=0,
        max=6)

    export_draco_position_quantization: IntProperty(
        name='Position quantization bits',
        description=
        'Quantization bits for position values (0 = no quantization)',
        default=14,
        min=0,
        max=30)

    export_draco_normal_quantization: IntProperty(
        name='Normal quantization bits',
        description='Quantization bits for normal values (0 = no quantization)',
        default=10,
        min=0,
        max=30)

    export_draco_texcoord_quantization: IntProperty(
        name='Texcoord quantization bits',
        description=
        'Quantization bits for texture coordinate values (0 = no quantization)',
        default=12,
        min=0,
        max=30)

    export_tangents: BoolProperty(
        name='Tangents',
        description='Export vertex tangents with meshes',
        default=False)

    export_materials: BoolProperty(name='Materials',
                                   description='Export materials',
                                   default=True)

    export_colors: BoolProperty(name='Vertex Colors',
                                description='Export vertex colors with meshes',
                                default=True)

    export_cameras: BoolProperty(name='Cameras',
                                 description='Export cameras',
                                 default=False)

    export_selected: BoolProperty(name='Selected Objects',
                                  description='Export selected objects only',
                                  default=False)

    export_extras: BoolProperty(
        name='Custom Properties',
        description='Export custom properties as glTF extras',
        default=False)

    export_yup: BoolProperty(name='+Y Up',
                             description='Export using glTF convention, +Y up',
                             default=True)

    export_apply: BoolProperty(
        name='Apply Modifiers',
        description='Apply modifiers (excluding Armatures) to mesh objects -'
        'WARNING: prevents exporting shape keys',
        default=False)

    export_animations: BoolProperty(
        name='Animations',
        description='Exports active actions and NLA tracks as glTF animations',
        default=True)

    export_frame_range: BoolProperty(
        name='Limit to Playback Range',
        description='Clips animations to selected playback range',
        default=True)

    export_frame_step: IntProperty(
        name='Sampling Rate',
        description='How often to evaluate animated values (in frames)',
        default=1,
        min=1,
        max=120)

    export_force_sampling: BoolProperty(
        name='Always Sample Animations',
        description='Apply sampling to all animations',
        default=True)

    export_nla_strips: BoolProperty(name='NLA Strips',
                                    description='Export NLA Strip animations',
                                    default=True)

    export_def_bones: BoolProperty(
        name='Export Deformation bones only',
        description=
        'Export Deformation bones only (and needed bones for hierarchy)',
        default=False)

    export_current_frame: BoolProperty(
        name='Use Current Frame',
        description='Export the scene in the current animation frame',
        default=False)

    export_skins: BoolProperty(name='Skinning',
                               description='Export skinning (armature) data',
                               default=True)

    export_all_influences: BoolProperty(
        name='Include All Bone Influences',
        description=
        'Allow >4 joint vertex influences. Models may appear incorrectly in many viewers',
        default=False)

    export_morph: BoolProperty(name='Shape Keys',
                               description='Export shape keys (morph targets)',
                               default=True)

    export_morph_normal: BoolProperty(
        name='Shape Key Normals',
        description='Export vertex normals with shape keys (morph targets)',
        default=True)

    export_morph_tangent: BoolProperty(
        name='Shape Key Tangents',
        description='Export vertex tangents with shape keys (morph targets)',
        default=False)

    export_lights: BoolProperty(
        name='Punctual Lights',
        description='Export directional, point, and spot lights. '
        'Uses "KHR_lights_punctual" glTF extension',
        default=False)

    export_displacement: BoolProperty(
        name='Displacement Textures (EXPERIMENTAL)',
        description='EXPERIMENTAL: Export displacement textures. '
        'Uses incomplete "KHR_materials_displacement" glTF extension',
        default=False)

    will_save_settings: BoolProperty(
        name='Remember Export Settings',
        description='Store glTF export settings in the Blender project',
        default=False)

    # Custom scene property for saving settings
    scene_key = "glTF2ExportSettings"

    #

    def invoke(self, context, event):
        settings = context.scene.get(self.scene_key)
        self.will_save_settings = False
        if settings:
            try:
                for (k, v) in settings.items():
                    setattr(self, k, v)
                self.will_save_settings = True

            except (AttributeError, TypeError):
                self.report({
                    "ERROR"
                }, "Loading export settings failed. Removed corrupted settings"
                            )
                del context.scene[self.scene_key]

        return ExportHelper.invoke(self, context, event)

    def save_settings(self, context):
        # find all export_ props
        all_props = self.properties
        export_props = {
            x: getattr(self, x)
            for x in dir(all_props)
            if x.startswith("export_") and all_props.get(x) is not None
        }

        context.scene[self.scene_key] = export_props

    def execute(self, context):
        import os
        import datetime
        from .blender.exp import gltf2_blender_export

        if self.will_save_settings:
            self.save_settings(context)

        if self.export_format == 'GLB':
            self.filename_ext = '.glb'
        else:
            self.filename_ext = '.gltf'

        # All custom export settings are stored in this container.
        export_settings = {}

        export_settings['timestamp'] = datetime.datetime.now()

        export_settings['gltf_filepath'] = bpy.path.ensure_ext(
            self.filepath, self.filename_ext)
        export_settings['gltf_filedirectory'] = os.path.dirname(
            export_settings['gltf_filepath']) + '/'

        export_settings['gltf_format'] = self.export_format
        export_settings['gltf_image_format'] = self.export_image_format
        export_settings['gltf_copyright'] = self.export_copyright
        export_settings['gltf_texcoords'] = self.export_texcoords
        export_settings['gltf_normals'] = self.export_normals
        export_settings[
            'gltf_tangents'] = self.export_tangents and self.export_normals

        if self.is_draco_available:
            export_settings[
                'gltf_draco_mesh_compression'] = self.export_draco_mesh_compression_enable
            export_settings[
                'gltf_draco_mesh_compression_level'] = self.export_draco_mesh_compression_level
            export_settings[
                'gltf_draco_position_quantization'] = self.export_draco_position_quantization
            export_settings[
                'gltf_draco_normal_quantization'] = self.export_draco_normal_quantization
            export_settings[
                'gltf_draco_texcoord_quantization'] = self.export_draco_texcoord_quantization
        else:
            export_settings['gltf_draco_mesh_compression'] = False

        export_settings['gltf_materials'] = self.export_materials
        export_settings['gltf_colors'] = self.export_colors
        export_settings['gltf_cameras'] = self.export_cameras
        export_settings['gltf_selected'] = self.export_selected
        export_settings['gltf_layers'] = True  # self.export_layers
        export_settings['gltf_extras'] = self.export_extras
        export_settings['gltf_yup'] = self.export_yup
        export_settings['gltf_apply'] = self.export_apply
        export_settings['gltf_current_frame'] = self.export_current_frame
        export_settings['gltf_animations'] = self.export_animations
        if self.export_animations:
            export_settings['gltf_frame_range'] = self.export_frame_range
            export_settings['gltf_force_sampling'] = self.export_force_sampling
            if self.export_force_sampling:
                export_settings['gltf_def_bones'] = self.export_def_bones
            else:
                export_settings['gltf_def_bones'] = False
            export_settings['gltf_nla_strips'] = self.export_nla_strips
        else:
            export_settings['gltf_frame_range'] = False
            export_settings['gltf_move_keyframes'] = False
            export_settings['gltf_force_sampling'] = False
            export_settings['gltf_def_bones'] = False
        export_settings['gltf_skins'] = self.export_skins
        if self.export_skins:
            export_settings[
                'gltf_all_vertex_influences'] = self.export_all_influences
        else:
            export_settings['gltf_all_vertex_influences'] = False
        export_settings['gltf_frame_step'] = self.export_frame_step
        export_settings['gltf_morph'] = self.export_morph
        if self.export_morph:
            export_settings['gltf_morph_normal'] = self.export_morph_normal
        else:
            export_settings['gltf_morph_normal'] = False
        if self.export_morph and self.export_morph_normal:
            export_settings['gltf_morph_tangent'] = self.export_morph_tangent
        else:
            export_settings['gltf_morph_tangent'] = False

        export_settings['gltf_lights'] = self.export_lights
        export_settings['gltf_displacement'] = self.export_displacement

        export_settings['gltf_binary'] = bytearray()
        export_settings['gltf_binaryfilename'] = os.path.splitext(
            os.path.basename(
                bpy.path.ensure_ext(self.filepath,
                                    self.filename_ext)))[0] + '.bin'

        return gltf2_blender_export.save(context, export_settings)

    def draw(self, context):
        pass
Example #13
0
class AddTwistedTorus(bpy.types.Operator):
    bl_idname = "mesh.primitive_twisted_torus_add"
    bl_label = "Add Twisted Torus"
    bl_description = "Construct a twisted torus mesh"
    bl_options = {'REGISTER', 'UNDO', 'PRESET'}

    major_radius = FloatProperty(name="Major Radius",
                                 description="Radius from the origin to the"
                                 " center of the cross section",
                                 min=0.01,
                                 max=100.0,
                                 default=1.0)
    minor_radius = FloatProperty(
        name="Minor Radius",
        description="Radius of the torus' cross section",
        min=0.01,
        max=100.0,
        default=0.25)
    major_segments = IntProperty(
        name="Major Segments",
        description="Number of segments for the main ring of the torus",
        min=3,
        max=256,
        default=48)
    minor_segments = IntProperty(
        name="Minor Segments",
        description="Number of segments for the minor ring of the torus",
        min=3,
        max=256,
        default=12)
    twists = IntProperty(name="Twists",
                         description="Number of twists of the torus",
                         min=0,
                         max=256,
                         default=1)
    use_abso = BoolProperty(
        name="Use Int/Ext Controls",
        description="Use the Int/Ext controls for torus dimensions",
        default=False)
    abso_major_rad = FloatProperty(
        name="Exterior Radius",
        description="Total Exterior Radius of the torus",
        min=0.01,
        max=100.0,
        default=1.0)
    abso_minor_rad = FloatProperty(
        name="Inside Radius",
        description="Total Interior Radius of the torus",
        min=0.01,
        max=100.0,
        default=0.5)

    def execute(self, context):

        if self.use_abso is True:
            extra_helper = (self.abso_major_rad - self.abso_minor_rad) * 0.5
            self.major_radius = self.abso_minor_rad + extra_helper
            self.minor_radius = extra_helper

        verts, faces = add_twisted_torus(self.major_radius, self.minor_radius,
                                         self.major_segments,
                                         self.minor_segments, self.twists)

        # Create the mesh object from this geometry data.
        obj = create_mesh_object(context, verts, [], faces, "TwistedTorus")

        return {'FINISHED'}
class CAP_FormatData_Alembic(PropertyGroup):

	instance_id: IntProperty(default=-1)

	# scene
	start_frame: IntProperty(
		name = "Start Frame",
		description = "The start frame of the export.  Leave at the default value (1) to take the start frame of the current scene.",
		default = 1,
	)

	end_frame: IntProperty(
		name = "End Frame",
		description = "The end frame of the export.  Leave at the default value (250) to take the start frame of the current scene.",
		default = 250,
	)

	transform_samples: IntProperty(
		name = "Transform Samples",
		description = "The number of times per-frame transformations are sampled.",
		default = 1,
		min = 1, 
		max = 128,
	)

	geometry_samples: IntProperty(
		name = "Geometry Samples",
		description = "The number of times per-frame object data is sampled.",
		default = 1,
		min = 1, 
		max = 128,
	)

	shutter_open: FloatProperty(
		name = "Shutter Open",
		description = "The time at which the shutter is open.",
		default = 0.0,
		step = 0.1,
		min = -1,
		max = 1,
	)

	shutter_close: FloatProperty(
		name = "Shutter Close",
		description = "The time at which the shutter is closed.",
		default = 1.0,
		step = 0.1,
		min = -1,
		max = 1,
	)

	flatten_hierarchy: BoolProperty(
		name = "Flatten Hierarchy",
		description = "Do not preserve object parent/child relationships on export.",
		default = False
	)

	global_scale: FloatProperty(
		name = "Global Scale",
		description = "The value to which all objects will be scaled with respect to the world's origin point.",
		default = 1.0,
		soft_min = 0.1,
		soft_max = 10,
		step = 0.1,
		min = 0.0001,
		max = 1000,
	)

	# object
	export_uvs: BoolProperty(
		name = "Export UVs",
		description = "Include mesh UVs with the export.",
		default = True
	)

	pack_uvs: BoolProperty(
		name = "Pack UV Islands",
		description = "Export UVs with packed islands.",
		default = True
	)

	export_normals: BoolProperty(
		name = "Export Normals",
		description = "Include mesh normals with the export.",
		default = True
	)

	export_colors: BoolProperty(
		name = "Export Vertex Colors",
		description = "Include vertex colors with the export.",
		default = False
	)

	export_face_sets: BoolProperty(
		name = "Export Face Sets",
		description = "Export per-face shading group assignments.",
		default = False
	)



	use_subdiv_schema: BoolProperty(
		name = "Use Subdivision Schema",
		description = "Export meshes using Alembic’s subdivision schema.",
		default = False
	)

	apply_subdiv: BoolProperty(
		name = "Apply Subsurface Divisions",
		description = "Export subdivision surfaces as meshes.",
		default = False
	)

	export_curves_as_mesh: BoolProperty(
		name = "Export Curves as Meshes",
		description = "Export curves and NURBS surfaces as meshes.",
		default = False
	)

	compression_type: EnumProperty(
		name='Compression Type',
		description='???',
		items=(
			('OGAWA', 'OGAWA', '???'),
			('HDF5', 'HDF5', '???'),
			),
	)
	



	# particles
	export_hair: BoolProperty(
		name = "Export Hair",
		description = "Exports hair particle systems as animated curves.",
		default = False
	)

	export_particles: BoolProperty(
		name = "Export Particles",
		description = "Exports non-hair particle systems.",
		default = False
	)

	def export(self, context, export_preset, filePath):
		"""
		Calls the Alembic export operator module to export the currently selected objects.
		"""

		bpy.ops.wm.alembic_export(

			# core
			filepath = filePath + ".abc",
			check_existing = False,
			as_background_job = False,

			selected = True,
			renderable_only = False,
			visible_layers_only = False,

			# scene
			start = self.start_frame,
			end = self.end_frame,
			xsamples = self.transform_samples,
			gsamples = self.geometry_samples,
			sh_open = self.shutter_open,
			sh_close = self.shutter_close,
			flatten = self.flatten_hierarchy,
			global_scale = self.global_scale,

			# object
			uvs = self.export_uvs,
			packuv = self.pack_uvs,
			normals = self.export_normals,
			vcolors = self.export_colors,
			face_sets = self.export_face_sets,

			subdiv_schema = self.use_subdiv_schema,
			apply_subdiv = self.apply_subdiv,
			curves_as_mesh = self.export_curves_as_mesh,
			compression_type = self.compression_type,
			# trianglulate = False,  # part of the API, but Capsule does this elsewhere.
			# quad_method = ???      # see above, although I should provide options like this API does.
			# ngon_method = ???      # ^
			
			# particles
			export_hair = self.export_hair,
			export_particles = self.export_particles,

		)
	
	def draw_addon_preferences(self, layout, exportData, exp):
		"""
		Draws the panel that represents all the options that the export format has.
		"""

		filepresets_box = layout.column(align=True)
		filepresets_box.separator()

		export_tabs = filepresets_box.row(align=True)

		# tab bar and tab bar padding
		export_tabs.separator()
		export_tabs.prop(exp, "alembic_menu_options", expand=True)
		export_tabs.separator()

		# separation space between tab bar and contents
		export_separator = filepresets_box.column(align=True)
		export_separator.separator()
		export_separator.separator()

		if exp.alembic_menu_options == 'Scene':
			export_main = filepresets_box.row(align=True)
			export_main.separator()

			export_1 = export_main.column(align=True)
			export_1.separator()
			export_1.prop(exportData, "start_frame")
			export_1.prop(exportData, "end_frame")
			export_1.prop(exportData, "shutter_open")
			export_1.prop(exportData, "shutter_close")

			export_main.separator()
			export_main.separator()
			export_main.separator()

			export_2 = export_main.column(align=True)
			export_2.separator()
			export_2.prop(exportData, "flatten_hierarchy")
			export_2.separator()
			export_2.prop(exportData, "transform_samples")
			export_2.prop(exportData, "geometry_samples")
			export_2.prop(exportData, "global_scale")
			export_2.separator()

			export_main.separator()

		if exp.alembic_menu_options == 'Object':
			export_main = filepresets_box.row(align=True)
			export_main.separator()

			export_1 = export_main.column(align=True)
			export_1.separator()
			export_1.prop(exportData, "use_subdiv_schema")
			export_1.prop(exportData, "apply_subdiv")
			export_1.prop(exportData, "export_curves_as_mesh")
			export_1.separator()
			export_1.prop(exportData, "compression_type")
			export_1.separator()

			export_main.separator()
			export_main.separator()
			export_main.separator()

			export_2 = export_main.column(align=True)
			export_2.separator()
			export_2.prop(exportData, "export_uvs")
			export_2.prop(exportData, "pack_uvs")
			export_2.prop(exportData, "export_normals")
			export_2.prop(exportData, "export_colors")
			export_2.prop(exportData, "export_face_sets")
			export_2.separator()

			export_main.separator()

		elif exp.alembic_menu_options == 'Particles':
			export_main = filepresets_box.row(align=True)
			export_main.separator()

			export_1 = export_main.column(align=True)
			export_1.prop(exportData, "export_hair")
			export_1.prop(exportData, "export_particles")
			export_1.separator()

			export_main.separator()
			export_main.separator()
			export_main.separator()

			export_2 = export_main.row(align=True)
			export_2.separator()

			export_main.separator()
Example #15
0
class SvListInputNode(bpy.types.Node, SverchCustomTreeNode):
    ''' Creta a float or int List '''
    bl_idname = 'SvListInputNode'
    bl_label = 'List Input'
    bl_icon = 'OUTLINER_OB_EMPTY'

    defaults = [0 for i in range(32)]
    int_ = IntProperty(name='int_',
                       description='integer number',
                       default=1,
                       min=1,
                       max=32,
                       update=updateNode)
    v_int = IntProperty(name='int_',
                        description='integer number',
                        default=1,
                        min=1,
                        max=10,
                        update=updateNode)
    int_list = IntVectorProperty(name='int_list',
                                 description="Integer list",
                                 default=defaults,
                                 size=32,
                                 update=updateNode)
    float_list = FloatVectorProperty(name='float_list',
                                     description="Float list",
                                     default=defaults,
                                     size=32,
                                     update=updateNode)
    vector_list = FloatVectorProperty(name='vector_list',
                                      description="Vector list",
                                      default=defaults,
                                      size=32,
                                      update=updateNode)

    def changeMode(self, context):
        if self.mode == 'vector':
            if 'Vector List' not in self.outputs:
                self.outputs.remove(self.outputs[0])
                self.outputs.new('VerticesSocket', 'Vector List',
                                 'Vector List')
                return
        else:
            if 'List' not in self.outputs:
                self.outputs.remove(self.outputs[0])
                self.outputs.new('StringsSocket', 'List', 'List')
                return

    modes = [("int_list", "Int", "Integer", "", 1),
             ("float_list", "Float", "Float", "", 2),
             ("vector", "Vector", "Vector", "", 3)]

    mode = EnumProperty(items=modes, default='int_list', update=changeMode)

    def init(self, context):
        self.outputs.new('StringsSocket', "List", "List")

    def draw_buttons(self, context, layout):
        if self.mode == 'vector':
            layout.prop(self, "v_int", text="List Length")
        else:
            layout.prop(self, "int_", text="List Length")

        layout.prop(self, "mode", expand=True)

        if self.mode == 'vector':
            col = layout.column(align=False)
            for i in range(self.v_int):
                row = col.row(align=True)
                for j in range(3):
                    row.prop(self,
                             'vector_list',
                             index=i * 3 + j,
                             text='XYZ'[j])
        else:
            col = layout.column(align=True)
            for i in range(self.int_):
                col.prop(self, self.mode, index=i, text=str(i))

    def update(self):
        if any((n in self.outputs
                for n in ['List', 'Vector List'])) and self.outputs[0].links:
            if self.mode == 'int_list':
                SvSetSocketAnyType(self, "List",
                                   [list(self.int_list[:self.int_])])
            elif self.mode == 'float_list':
                SvSetSocketAnyType(self, "List",
                                   [list(self.float_list[:self.int_])])
            elif self.mode == 'vector':
                c = self.v_int * 3
                v_l = list(self.vector_list)
                out = list(zip(v_l[0:c:3], v_l[1:c:3], v_l[2:c:3]))
                SvSetSocketAnyType(self, "Vector List", [out])

    def update_socket(self, context):
        self.update()
Example #16
0
class ResourcePsetProperties(PropertyGroup):
    active_pset_id: IntProperty(name="Active Pset ID")
    active_pset_name: StringProperty(name="Pset Name")
    properties: CollectionProperty(name="Properties", type=Attribute)
    pset_name: EnumProperty(items=getResourcePsetNames, name="Pset Name")
    qto_name: EnumProperty(items=getResourceQtoNames, name="Qto Name")
class FloorplanProperty(bpy.types.PropertyGroup):
    fp_types = [
        ("RECTANGULAR", "Rectangular", "", 0),
        ("CIRCULAR", "Circular", "", 1),
        ("COMPOSITE", "Composite", "", 2),
        ("H-SHAPED", "H-Shaped", "", 3),
        ("RANDOM", "Random", "", 4),
    ]

    type: EnumProperty(items=fp_types,
                       default="RECTANGULAR",
                       description="Type of floorplan")

    seed: IntProperty(
        name="Seed",
        min=0,
        max=10000,
        default=1,
        description="Seed for random generation",
    )

    width: FloatProperty(
        name="Width",
        min=0.01,
        max=100.0,
        default=4,
        unit="LENGTH",
        description="Base Width of floorplan",
    )

    length: FloatProperty(
        name="Length",
        min=0.01,
        max=100.0,
        default=4,
        unit="LENGTH",
        description="Base Length of floorplan",
    )

    random_extension_amount: BoolProperty(
        name="Random Extension Amount",
        default=True,
        description="Randomize the amount of extensions")

    extension_amount: IntProperty(
        name="Extension Amount",
        min=1,
        max=4,
        default=1,
        description="Amount of extensions to generate",
    )

    radius: FloatProperty(name="Radius",
                          min=0.1,
                          max=100.0,
                          default=1.0,
                          unit="LENGTH",
                          description="Radius of circle")

    segments: IntProperty(
        name="Segments",
        min=3,
        max=100,
        default=32,
        description="Number of segments in the circle",
    )

    def get_segment_width(self, propname):
        return self.get(propname, 1.0)

    def set_segment_width(self, value, propname):
        """
        Clamp the segment width to less than default_width + base width
        ONLY for H-Shaped floorplan
        """
        default_width = 1.0
        maximum_width = default_width + self.width

        # -- calculate offsets of adjacent segments
        adjacent_prop = {
            "tw1": "tw2",
            "tw2": "tw1",
            "tw3": "tw4",
            "tw4": "tw3",
        }.get(propname)
        maximum_width += (default_width - self.get(adjacent_prop, 1.0))

        if self.type == "H-SHAPED":
            self[propname] = clamp(value, 0.0, maximum_width)
        else:
            self[propname] = value

    tw1: FloatProperty(
        name="Tail Width 1",
        min=0.0,
        max=100.0,
        unit="LENGTH",
        description="Width of floorplan segment",
        get=lambda self: self.get_segment_width("tw1"),
        set=lambda self, value: self.set_segment_width(value, "tw1"),
    )

    tl1: FloatProperty(
        name="Tail Length 1",
        min=0.0,
        max=100.0,
        default=1,
        unit="LENGTH",
        description="Length of floorplan segment",
    )

    tw2: FloatProperty(
        name="Tail Width 2",
        min=0.0,
        max=100.0,
        unit="LENGTH",
        description="Width of floorplan segment",
        get=lambda self: self.get_segment_width("tw2"),
        set=lambda self, value: self.set_segment_width(value, "tw2"),
    )

    tl2: FloatProperty(
        name="Tail Length 2",
        min=0.0,
        max=100.0,
        default=1,
        unit="LENGTH",
        description="Length of floorplan segment",
    )

    tw3: FloatProperty(
        name="Tail Width 3",
        min=0.0,
        max=100.0,
        unit="LENGTH",
        description="Width of floorplan segment",
        get=lambda self: self.get_segment_width("tw3"),
        set=lambda self, value: self.set_segment_width(value, "tw3"),
    )

    tl3: FloatProperty(
        name="Tail Length 3",
        min=0.0,
        max=100.0,
        default=1,
        unit="LENGTH",
        description="Length of floorplan segment",
    )

    tw4: FloatProperty(
        name="Tail Width 4",
        min=0.0,
        max=100.0,
        unit="LENGTH",
        description="Width of floorplan segment",
        get=lambda self: self.get_segment_width("tw4"),
        set=lambda self, value: self.set_segment_width(value, "tw4"),
    )

    tl4: FloatProperty(
        name="Tail Length 4",
        min=0.0,
        max=100.0,
        default=1,
        unit="LENGTH",
        description="Length of floorplan segment",
    )

    cap_tris: BoolProperty(
        name="Cap Triangles",
        default=False,
        description="Set the fill type to triangles",
    )

    def draw(self, context, layout):
        row = layout.row()
        row.prop(self, "type", text="")

        box = layout.box()
        if self.type == "RECTANGULAR":
            col = box.column(align=True)
            col.prop(self, "width")
            col.prop(self, "length")

        elif self.type == "RANDOM":
            col = box.column(align=True)
            col.prop(self, "seed")
            col.prop(self, "width")
            col.prop(self, "length")
            col.prop(self, "random_extension_amount")

            if not self.random_extension_amount:
                col.prop(self, "extension_amount")

        elif self.type == "CIRCULAR":
            col = box.column(align=True)
            col.prop(self, "radius")
            col.prop(self, "segments")

            row = box.row()
            row.prop(self, "cap_tris", toggle=True)

        elif self.type == "COMPOSITE":
            row = box.row(align=True)
            row.prop(self, "width")
            row.prop(self, "length")

            col = box.column(align=True)
            col.prop(self, "tl1", text="Fan Length 1")
            col.prop(self, "tl2", text="Fan Length 2")
            col.prop(self, "tl3", text="Fan Length 3")
            col.prop(self, "tl4", text="Fan Length 4")

        elif self.type == "H-SHAPED":
            row = box.row(align=True)
            row.prop(self, "width")
            row.prop(self, "length")

            row = box.row(align=True)

            col = row.column(align=True)
            col.prop(self, "tw1")
            col.prop(self, "tw2")
            col.prop(self, "tw3")
            col.prop(self, "tw4")

            col = row.column(align=True)
            col.prop(self, "tl1")
            col.prop(self, "tl2")
            col.prop(self, "tl3")
            col.prop(self, "tl4")
Example #18
0
class WorkSchedulePsetProperties(PropertyGroup):
    active_pset_id: IntProperty(name="Active Pset ID")
    active_pset_name: StringProperty(name="Pset Name")
    properties: CollectionProperty(name="Properties", type=Attribute)
    pset_name: EnumProperty(items=getWorkSchedulePsetNames, name="Pset Name")
Example #19
0
class Voronoi2DNode(bpy.types.Node, SverchCustomTreeNode):
    """
    Triggers: Voronoi vr
    Tooltip: Generate 2D Voronoi diagram for a set of vertices.
    """
    bl_idname = 'Voronoi2DNode'
    bl_label = 'Voronoi 2D'
    bl_icon = 'OUTLINER_OB_EMPTY'
    sv_icon = 'SV_VORONOI'

    clip: FloatProperty(name='clip',
                        description='Clipping Distance',
                        default=1.0,
                        min=0,
                        update=updateNode)

    bound_modes = [('BOX', 'Bounding Box', "Bounding Box", 0),
                   ('CIRCLE', 'Bounding Circle', "Bounding Circle", 1)]

    bound_mode: EnumProperty(name='Bounds Mode',
                             description="Bounding mode",
                             items=bound_modes,
                             default='BOX',
                             update=updateNode)

    draw_bounds: BoolProperty(name="Draw Bounds",
                              description="Draw bounding edges",
                              default=True,
                              update=updateNode)

    draw_hangs: BoolProperty(
        name="Draw Tails",
        description="Draw lines that end outside of clipping area",
        default=True,
        update=updateNode)

    def update_sockets(self, context):
        if 'Faces' in self.outputs:
            self.outputs['Faces'].hide_safe = not self.make_faces
        if 'MaxSides' in self.inputs:
            self.inputs['MaxSides'].hide_safe = not self.make_faces
        updateNode(self, context)

    make_faces: BoolProperty(
        name="Make faces",
        description="Use `fill holes` function to make Voronoi polygons",
        default=False,
        update=update_sockets)

    ordered_faces: BoolProperty(
        name="Ordered faces",
        description=
        "Make sure that faces are generated in the same order as corresponding input vertices",
        default=False,
        update=updateNode)

    max_sides: IntProperty(name='Sides',
                           description='Maximum number of polygon sides',
                           default=10,
                           min=3,
                           update=updateNode)

    def sv_init(self, context):
        self.inputs.new('SvVerticesSocket', "Vertices")
        self.inputs.new('SvStringsSocket', 'MaxSides').prop_name = 'max_sides'
        self.outputs.new('SvVerticesSocket', "Vertices")
        self.outputs.new('SvStringsSocket', "Edges")
        self.outputs.new('SvStringsSocket', "Faces")
        self.update_sockets(context)

    def draw_buttons(self, context, layout):
        layout.label(text="Bounds mode:")
        layout.prop(self, "bound_mode", text='')
        layout.prop(self, "draw_bounds")
        if not self.draw_bounds:
            layout.prop(self, "draw_hangs")
        layout.prop(self, "clip", text="Clipping")
        layout.prop(self, "make_faces")

    def draw_buttons_ext(self, context, layout):
        self.draw_buttons(context, layout)
        if self.make_faces:
            layout.prop(self, 'ordered_faces')

    def process(self):

        if not self.inputs['Vertices'].is_linked:
            return

        if not self.outputs['Vertices'].is_linked:
            return

        points_in = self.inputs['Vertices'].sv_get()
        if 'MaxSides' in self.inputs:
            max_sides_in = self.inputs['MaxSides'].sv_get()
        else:
            max_sides_in = [[10]]

        pts_out = []
        edges_out = []
        faces_out = []
        for sites, max_sides in zip_long_repeat(points_in, max_sides_in):
            if isinstance(max_sides, (list, tuple)):
                max_sides = max_sides[0]

            new_vertices, edges, new_faces = voronoi_bounded(
                sites,
                bound_mode=self.bound_mode,
                clip=self.clip,
                draw_bounds=self.draw_bounds,
                draw_hangs=self.draw_hangs,
                make_faces=self.make_faces,
                ordered_faces=self.ordered_faces,
                max_sides=max_sides)

            pts_out.append(new_vertices)
            edges_out.append(edges)
            faces_out.append(new_faces)
            #edges_out.append(finite_edges)

        # outputs
        self.outputs['Vertices'].sv_set(pts_out)
        self.outputs['Edges'].sv_set(edges_out)
        if 'Faces' in self.outputs and self.make_faces:
            self.outputs['Faces'].sv_set(faces_out)
Example #20
0
class NLA_OT_bake(Operator):
    """Bake all selected objects location/scale/rotation animation to an action"""
    bl_idname = "nla.bake"
    bl_label = "Bake Action"
    bl_options = {'REGISTER', 'UNDO'}

    frame_start: IntProperty(
        name="Start Frame",
        description="Start frame for baking",
        min=0, max=300000,
        default=1,
    )
    frame_end: IntProperty(
        name="End Frame",
        description="End frame for baking",
        min=1, max=300000,
        default=250,
    )
    step: IntProperty(
        name="Frame Step",
        description="Frame Step",
        min=1, max=120,
        default=1,
    )
    only_selected: BoolProperty(
        name="Only Selected Bones",
        description="Only key selected bones (Pose baking only)",
        default=True,
    )
    visual_keying: BoolProperty(
        name="Visual Keying",
        description="Keyframe from the final transformations (with constraints applied)",
        default=False,
    )
    clear_constraints: BoolProperty(
        name="Clear Constraints",
        description="Remove all constraints from keyed object/bones, and do 'visual' keying",
        default=False,
    )
    clear_parents: BoolProperty(
        name="Clear Parents",
        description="Bake animation onto the object then clear parents (objects only)",
        default=False,
    )
    use_current_action: BoolProperty(
        name="Overwrite Current Action",
        description="Bake animation into current action, instead of creating a new one "
        "(useful for baking only part of bones in an armature)",
        default=False,
    )
    clean_curves: BoolProperty(
        name="Clean Curves",
        description="After baking curves, remove redundant keys",
        default=False,
    )
    bake_types: EnumProperty(
        name="Bake Data",
        description="Which data's transformations to bake",
        options={'ENUM_FLAG'},
        items=(
             ('POSE', "Pose", "Bake bones transformations"),
             ('OBJECT', "Object", "Bake object transformations"),
        ),
        default={'POSE'},
    )

    def execute(self, context):
        from bpy_extras import anim_utils
        do_pose = 'POSE' in self.bake_types
        do_object = 'OBJECT' in self.bake_types

        objects = context.selected_editable_objects
        if do_pose and not do_object:
            objects = [obj for obj in objects if obj.pose is not None]

        object_action_pairs = (
            [(obj, getattr(obj.animation_data, "action", None)) for obj in objects]
            if self.use_current_action else
            [(obj, None) for obj in objects]
        )

        actions = anim_utils.bake_action_objects(
            object_action_pairs,
            frames=range(self.frame_start, self.frame_end + 1, self.step),
            only_selected=self.only_selected,
            do_pose=do_pose,
            do_object=do_object,
            do_visual_keying=self.visual_keying,
            do_constraint_clear=self.clear_constraints,
            do_parents_clear=self.clear_parents,
            do_clean=self.clean_curves,
        )

        if not any(actions):
            self.report({'INFO'}, "Nothing to bake")
            return {'CANCELLED'}

        return {'FINISHED'}

    def invoke(self, context, _event):
        scene = context.scene
        self.frame_start = scene.frame_start
        self.frame_end = scene.frame_end
        self.bake_types = {'POSE'} if context.mode == 'POSE' else {'OBJECT'}

        wm = context.window_manager
        return wm.invoke_props_dialog(self)
Example #21
0
class QuickFur(ObjectModeOperator, Operator):
    """Add fur setup to the selected objects"""
    bl_idname = "object.quick_fur"
    bl_label = "Quick Fur"
    bl_options = {'REGISTER', 'UNDO'}

    density: EnumProperty(
        name="Fur Density",
        items=(('LIGHT', "Light", ""), ('MEDIUM', "Medium", ""),
               ('HEAVY', "Heavy", "")),
        default='MEDIUM',
    )
    view_percentage: IntProperty(
        name="View %",
        min=1,
        max=100,
        soft_min=1,
        soft_max=100,
        default=10,
    )
    length: FloatProperty(
        name="Length",
        min=0.001,
        max=100,
        soft_min=0.01,
        soft_max=10,
        default=0.1,
    )

    def execute(self, context):
        fake_context = context.copy()
        mesh_objects = [
            obj for obj in context.selected_objects if obj.type == 'MESH'
        ]

        if not mesh_objects:
            self.report({'ERROR'}, "Select at least one mesh object")
            return {'CANCELLED'}

        mat = bpy.data.materials.new("Fur Material")

        for obj in mesh_objects:
            fake_context["object"] = obj
            bpy.ops.object.particle_system_add(fake_context)

            psys = obj.particle_systems[-1]
            psys.settings.type = 'HAIR'

            if self.density == 'LIGHT':
                psys.settings.count = 100
            elif self.density == 'MEDIUM':
                psys.settings.count = 1000
            elif self.density == 'HEAVY':
                psys.settings.count = 10000

            psys.settings.child_nbr = self.view_percentage
            psys.settings.hair_length = self.length
            psys.settings.use_strand_primitive = True
            psys.settings.use_hair_bspline = True
            psys.settings.child_type = 'INTERPOLATED'
            psys.settings.tip_radius = 0.25

            obj.data.materials.append(mat)
            psys.settings.material = len(obj.data.materials)

        return {'FINISHED'}
Example #22
0
class SvListItemNode(bpy.types.Node, SverchCustomTreeNode):
    '''
    Triggers: List Item Out
    Tooltip: Get elements from list at desired indexes
    '''
    bl_idname = 'SvListItemNode'
    bl_label = 'List Item'
    bl_icon = 'OUTLINER_OB_EMPTY'
    sv_icon = 'SV_LIST_ITEM'

    level: IntProperty(name='level_to_count',
                       default=2,
                       min=1,
                       update=updateNode)
    index: IntProperty(name='Index', default=0, update=updateNode)
    typ: StringProperty(name='typ', default='')
    newsock: BoolProperty(name='newsock', default=False)

    def draw_buttons(self, context, layout):
        '''draw buttons on the node'''
        layout.prop(self, "level", text="level")

    def sv_init(self, context):
        '''create sockets'''
        self.inputs.new('SvStringsSocket', "Data")
        self.inputs.new('SvStringsSocket', "Index").prop_name = 'index'
        self.outputs.new('SvStringsSocket', "Item")
        self.outputs.new('SvStringsSocket', "Other")

    def migrate_from(self, old_node):
        self.index = old_node.item

    def sv_update(self):
        """adapt socket type to input type"""
        if self.inputs['Data'].is_linked:
            inputsocketname = 'Data'
            outputsocketname = ['Item', 'Other']
            changable_sockets(self, inputsocketname, outputsocketname)

    def process(self):
        data = self.inputs['Data'].sv_get(default=[], deepcopy=False)
        indexes = self.inputs['Index'].sv_get(deepcopy=False)

        if self.level - 1:
            out = self.get_(data, self.level - 1, indexes, self.get_items)
        else:
            out = self.get_items(data, indexes[0])
        self.outputs[0].sv_set(out)

        if self.level - 1:
            out = self.get_(data, self.level - 1, indexes, self.get_other)
        else:
            out = self.get_other(data, indexes[0])
        self.outputs[1].sv_set(out)

    def get_items(self, data, indexes):
        '''extract the indexes from the list'''
        if type(data) in [list, tuple]:
            return [
                data[index] for index in indexes
                if -len(data) <= index < len(data)
            ]
        if type(data) == str:
            return ''.join([
                data[index] for index in indexes
                if -len(data) <= index < len(data)
            ])
        elif type(data) == np.ndarray:
            return data[indexes]
        else:
            return None

    def get_other(self, data, indexes):
        '''remove the indexes from the list'''
        if type(data) == np.ndarray:
            mask = np.ones(len(data), bool)
            mask[indexes] = False
            return data[mask]
        is_tuple = False
        if type(data) == tuple:
            data = list(data)
            is_tuple = True
        if type(data) == list:
            out_data = data.copy()
            m_indexes = indexes.copy()
            for idx, index in enumerate(indexes):
                if index < 0:
                    m_indexes[idx] = len(out_data) - abs(index)
            for i in sorted(set(m_indexes), reverse=True):
                if -1 < i < len(out_data):
                    del out_data[i]
            if is_tuple:
                return tuple(out_data)
            else:
                return out_data
        if type(data) == str:
            return ''.join(
                [d for idx, d in enumerate(data) if idx not in indexes])
        else:
            return None

    def get_(self, data, level, indexes,
             func):  # get is build-in method of Node class
        """iterative function to get down to the requested level"""
        if level == 1:
            obj_num = max(len(data), len(indexes))
            index_iter = repeat_last(indexes)
            data_iter = repeat_last(data)
            return [
                self.get_(next(data_iter), level - 1, next(index_iter), func)
                for _ in range(obj_num)
            ]
        elif level:
            return [self.get_(obj, level - 1, indexes, func) for obj in data]
        else:
            return func(data, indexes)
class AddGem(Operator):
    bl_idname = "mesh.primitive_gem_add"
    bl_label = "Add Gem"
    bl_description = "Construct an offset faceted gem mesh"
    bl_options = {'REGISTER', 'UNDO', 'PRESET'}

    Gem : BoolProperty(name = "Gem",
                default = True,
                description = "Gem")

    #### change properties
    name : StringProperty(name = "Name",
                    description = "Name")

    change : BoolProperty(name = "Change",
                default = False,
                description = "change Gem")
    
    segments: IntProperty(
            name="Segments",
            description="Longitudial segmentation",
            min=3,
            max=265,
            default=8
            )
    pavilion_radius: FloatProperty(
            name="Radius",
            description="Radius of the gem",
            min=0.01,
            max=9999.0,
            default=1.0
            )
    crown_radius: FloatProperty(
            name="Table Radius",
            description="Radius of the table(top)",
            min=0.01,
            max=9999.0,
            default=0.6
            )
    crown_height: FloatProperty(
            name="Table height",
            description="Height of the top half",
            min=0.01,
            max=9999.0,
            default=0.35
            )
    pavilion_height: FloatProperty(
            name="Pavilion height",
            description="Height of bottom half",
            min=0.01,
            max=9999.0,
            default=0.8
            )

    def draw(self, context):
        layout = self.layout
        box = layout.box()
        box.prop(self, "segments")
        box.prop(self, "pavilion_radius")
        box.prop(self, "crown_radius")
        box.prop(self, "crown_height")
        box.prop(self, "pavilion_height")
    
    def execute(self, context):
        
        if bpy.context.mode == "OBJECT":
            if context.selected_objects != [] and context.active_object and \
            ('Gem' in context.active_object.data.keys()) and (self.change == True):
                obj = context.active_object
                oldmesh = obj.data
                oldmeshname = obj.data.name
                verts, faces = add_gem(
                    self.pavilion_radius,
                    self.crown_radius,
                    self.segments,
                    self.pavilion_height,
                    self.crown_height)
                mesh = bpy.data.meshes.new("TMP")
                mesh.from_pydata(verts, [], faces)
                mesh.update()
                obj.data = mesh
                for material in oldmesh.materials:
                    obj.data.materials.append(material)
                bpy.data.meshes.remove(oldmesh)
                obj.data.name = oldmeshname
            else:
                verts, faces = add_gem(
                    self.pavilion_radius,
                    self.crown_radius,
                    self.segments,
                    self.pavilion_height,
                    self.crown_height)

                obj = create_mesh_object(context, verts, [], faces, "Gem")
        
            obj.data["Gem"] = True
            obj.data["change"] = False
            for prm in GemParameters():
                obj.data[prm] = getattr(self, prm)
        
        if bpy.context.mode == "EDIT_MESH":
            active_object = context.active_object
            name_active_object = active_object.name
            bpy.ops.object.mode_set(mode='OBJECT')
            verts, faces = add_gem(
                self.pavilion_radius,
                self.crown_radius,
                self.segments,
                self.pavilion_height,
                self.crown_height)

            obj = create_mesh_object(context, verts, [], faces, "TMP")
            
            obj.select_set(True)
            active_object.select_set(True)
            bpy.ops.object.join()
            context.active_object.name = name_active_object
            bpy.ops.object.mode_set(mode='EDIT')

        return {'FINISHED'}
Example #24
0
class ImageNode(bpy.types.Node, SverchCustomTreeNode):
    ''' Image '''
    bl_idname = 'ImageNode'
    bl_label = 'Image'
    bl_icon = 'FILE_IMAGE'

    name_image = StringProperty(name='image_name',
                                description='image name',
                                default='',
                                update=updateNode)

    R = FloatProperty(name='R',
                      description='R',
                      default=0.30,
                      min=0,
                      max=1,
                      options={'ANIMATABLE'},
                      update=updateNode)
    G = FloatProperty(name='G',
                      description='G',
                      default=0.59,
                      min=0,
                      max=1,
                      options={'ANIMATABLE'},
                      update=updateNode)
    B = FloatProperty(name='B',
                      description='B',
                      default=0.11,
                      min=0,
                      max=1,
                      options={'ANIMATABLE'},
                      update=updateNode)
    Xvecs = IntProperty(name='Xvecs',
                        description='Xvecs',
                        default=10,
                        min=2,
                        max=100,
                        options={'ANIMATABLE'},
                        update=updateNode)
    Yvecs = IntProperty(name='Yvecs',
                        description='Yvecs',
                        default=10,
                        min=2,
                        max=100,
                        options={'ANIMATABLE'},
                        update=updateNode)
    Xstep = FloatProperty(name='Xstep',
                          description='Xstep',
                          default=1.0,
                          min=0.01,
                          max=100,
                          options={'ANIMATABLE'},
                          update=updateNode)
    Ystep = FloatProperty(name='Ystep',
                          description='Ystep',
                          default=1.0,
                          min=0.01,
                          max=100,
                          options={'ANIMATABLE'},
                          update=updateNode)

    def sv_init(self, context):
        self.inputs.new('StringsSocket', "vecs X",
                        "vecs X").prop_name = 'Xvecs'
        self.inputs.new('StringsSocket', "vecs Y",
                        "vecs Y").prop_name = 'Yvecs'
        self.inputs.new('StringsSocket', "Step X",
                        "Step X").prop_name = 'Xstep'
        self.inputs.new('StringsSocket', "Step Y",
                        "Step Y").prop_name = 'Ystep'
        self.outputs.new('VerticesSocket', "vecs", "vecs")
        self.outputs.new('StringsSocket', "edgs", "edgs")
        self.outputs.new('StringsSocket', "pols", "pols")

    def draw_buttons(self, context, layout):
        layout.prop_search(self,
                           "name_image",
                           bpy.data,
                           'images',
                           text="image")
        row = layout.row(align=True)
        row.scale_x = 10.0
        row.prop(self, "R", text="R")
        row.prop(self, "G", text="G")
        row.prop(self, "B", text="B")

    def process(self):
        # inputs
        if 'vecs X' in self.inputs and self.inputs['vecs X'].is_linked:
            IntegerX = min(
                int(SvGetSocketAnyType(self, self.inputs['vecs X'])[0][0]),
                100)
        else:
            IntegerX = int(self.Xvecs)

        if 'vecs Y' in self.inputs and self.inputs['vecs Y'].is_linked:
            IntegerY = min(
                int(SvGetSocketAnyType(self, self.inputs['vecs Y'])[0][0]),
                100)
        else:
            IntegerY = int(self.Yvecs)

        if 'Step X' in self.inputs and self.inputs['Step X'].is_linked:
            StepX = SvGetSocketAnyType(self, self.inputs['Step X'])[0]
            fullList(StepX, IntegerX)

        else:
            StepX = [self.Xstep]
            fullList(StepX, IntegerX)

        if 'Step Y' in self.inputs and self.inputs['Step Y'].is_linked:
            StepY = SvGetSocketAnyType(self, self.inputs['Step Y'])[0]
            fullList(StepY, IntegerY)

        else:
            StepY = [self.Ystep]
            fullList(StepY, IntegerY)

        # outputs
        if 'vecs' in self.outputs and self.outputs['vecs'].is_linked:
            out = self.make_vertices(IntegerX - 1, IntegerY - 1, StepX, StepY,
                                     self.name_image)
            SvSetSocketAnyType(self, 'vecs', [out])
        else:
            SvSetSocketAnyType(self, 'vecs', [[[]]])

        if 'edgs' in self.outputs and self.outputs['edgs'].is_linked:

            listEdg = []
            for i in range(IntegerY):
                for j in range(IntegerX - 1):
                    listEdg.append((IntegerX * i + j, IntegerX * i + j + 1))
            for i in range(IntegerX):
                for j in range(IntegerY - 1):
                    listEdg.append(
                        (IntegerX * j + i, IntegerX * j + i + IntegerX))

            edg = list(listEdg)
            SvSetSocketAnyType(self, 'edgs', [edg])
        else:
            SvSetSocketAnyType(self, 'edgs', [[[]]])

        if 'pols' in self.outputs and self.outputs['pols'].is_linked:

            listPlg = []
            for i in range(IntegerX - 1):
                for j in range(IntegerY - 1):
                    listPlg.append((IntegerX * j + i, IntegerX * j + i + 1,
                                    IntegerX * j + i + IntegerX + 1,
                                    IntegerX * j + i + IntegerX))
            plg = list(listPlg)
            SvSetSocketAnyType(self, 'pols', [plg])
        else:
            SvSetSocketAnyType(self, 'pols', [[[]]])

    def make_vertices(self, delitelx, delitely, stepx, stepy, image_name):
        lenx = bpy.data.images[image_name].size[0]
        leny = bpy.data.images[image_name].size[1]
        if delitelx > lenx:
            delitelx = lenx
        if delitely > leny:
            delitely = leny
        R, G, B = self.R, self.G, self.B
        xcoef = lenx // delitelx
        ycoef = leny // delitely
        # copy images data, pixels is created on every access with [i], extreme speedup.
        # http://blender.stackexchange.com/questions/3673/why-is-accessing-image-data-so-slow
        imag = bpy.data.images[image_name].pixels[:]
        vertices = []
        addition = 0
        for y in range(delitely + 1):
            addition = int(ycoef * y * 4 * lenx)
            for x in range(delitelx + 1):
                #  каждый пиксель кодируется RGBA, и записан строкой, без разделения на строки и столбцы.
                middle = (imag[addition] * R + imag[addition + 1] * G +
                          imag[addition + 2] * B) * imag[addition + 3]
                vertex = [x * stepx[x], y * stepy[y], middle]
                vertices.append(vertex)
                addition += int(xcoef * 4)
        return vertices
Example #25
0
class FractureCell(Operator):
    bl_idname = "object.add_fracture_cell_objects"
    bl_label = "Cell fracture selected mesh objects"
    bl_options = {'PRESET'}

    # -------------------------------------------------------------------------
    # Source Options
    source: EnumProperty(
        name="Source",
        items=(
            ('VERT_OWN', "Own Verts", "Use own vertices"),
            ('VERT_CHILD', "Child Verts", "Use child object vertices"),
            ('PARTICLE_OWN', "Own Particles", ("All particle systems of the "
                                               "source object")),
            ('PARTICLE_CHILD', "Child Particles",
             ("All particle systems of the "
              "child objects")),
            ('PENCIL', "Grease Pencil", "This object's grease pencil"),
        ),
        options={'ENUM_FLAG'},
        default={'PARTICLE_OWN'},
    )

    source_limit: IntProperty(
        name="Source Limit",
        description="Limit the number of input points, 0 for unlimited",
        min=0,
        max=5000,
        default=100,
    )

    source_noise: FloatProperty(
        name="Noise",
        description="Randomize point distribution",
        min=0.0,
        max=1.0,
        default=0.0,
    )

    cell_scale: FloatVectorProperty(
        name="Scale",
        description="Scale Cell Shape",
        size=3,
        min=0.0,
        max=1.0,
        default=(1.0, 1.0, 1.0),
    )

    # -------------------------------------------------------------------------
    # Recursion

    recursion: IntProperty(
        name="Recursion",
        description="Break shards recursively",
        min=0,
        max=5000,
        default=0,
    )

    recursion_source_limit: IntProperty(
        name="Source Limit",
        description=
        "Limit the number of input points, 0 for unlimited (applies to recursion only)",
        min=0,
        max=5000,
        default=8,
    )

    recursion_clamp: IntProperty(
        name="Clamp Recursion",
        description=
        "Finish recursion when this number of objects is reached (prevents recursing for extended periods of time), zero disables",
        min=0,
        max=10000,
        default=250,
    )

    recursion_chance: FloatProperty(
        name="Random Factor",
        description="Likelihood of recursion",
        min=0.0,
        max=1.0,
        default=0.25,
    )

    recursion_chance_select: EnumProperty(
        name="Recurse Over",
        items=(
            ('RANDOM', "Random", ""),
            ('SIZE_MIN', "Small", "Recursively subdivide smaller objects"),
            ('SIZE_MAX', "Big", "Recursively subdivide bigger objects"),
            ('CURSOR_MIN', "Cursor Close",
             "Recursively subdivide objects closer to the cursor"),
            ('CURSOR_MAX', "Cursor Far",
             "Recursively subdivide objects farther from the cursor"),
        ),
        default='SIZE_MIN',
    )

    # -------------------------------------------------------------------------
    # Mesh Data Options

    use_smooth_faces: BoolProperty(
        name="Smooth Faces",
        default=False,
    )

    use_sharp_edges: BoolProperty(
        name="Sharp Edges",
        description="Set sharp edges when disabled",
        default=True,
    )

    use_sharp_edges_apply: BoolProperty(
        name="Apply Split Edge",
        description="Split sharp hard edges",
        default=True,
    )

    use_data_match: BoolProperty(
        name="Match Data",
        description="Match original mesh materials and data layers",
        default=True,
    )

    use_island_split: BoolProperty(
        name="Split Islands",
        description="Split disconnected meshes",
        default=True,
    )

    margin: FloatProperty(
        name="Margin",
        description="Gaps for the fracture (gives more stable physics)",
        min=0.0,
        max=1.0,
        default=0.001,
    )

    material_index: IntProperty(
        name="Material",
        description="Material index for interior faces",
        default=0,
    )

    use_interior_vgroup: BoolProperty(
        name="Interior VGroup",
        description="Create a vertex group for interior verts",
        default=False,
    )

    # -------------------------------------------------------------------------
    # Physics Options

    mass_mode: EnumProperty(
        name="Mass Mode",
        items=(
            ('VOLUME', "Volume",
             "Objects get part of specified mass based on their volume"),
            ('UNIFORM', "Uniform", "All objects get the specified mass"),
        ),
        default='VOLUME',
    )

    mass: FloatProperty(
        name="Mass",
        description="Mass to give created objects",
        min=0.001,
        max=1000.0,
        default=1.0,
    )

    # -------------------------------------------------------------------------
    # Object Options

    use_recenter: BoolProperty(
        name="Recenter",
        description="Recalculate the center points after splitting",
        default=True,
    )

    use_remove_original: BoolProperty(
        name="Remove Original",
        description="Removes the parents used to create the shatter",
        default=True,
    )

    # -------------------------------------------------------------------------
    # Scene Options
    #
    # .. different from object options in that this controls how the objects
    #    are setup in the scene.

    use_layer_index: IntProperty(
        name="Layer Index",
        description="Layer to add the objects into or 0 for existing",
        default=0,
        min=0,
        max=20,
    )

    use_layer_next: BoolProperty(
        name="Next Layer",
        description="At the object into the next layer (layer index overrides)",
        default=True,
    )

    group_name: StringProperty(
        name="Group",
        description="Create objects int a group "
        "(use existing or create new)",
    )

    # -------------------------------------------------------------------------
    # Debug
    use_debug_points: BoolProperty(
        name="Debug Points",
        description="Create mesh data showing the points used for fracture",
        default=False,
    )

    use_debug_redraw: BoolProperty(
        name="Show Progress Realtime",
        description="Redraw as fracture is done",
        default=True,
    )

    use_debug_bool: BoolProperty(
        name="Debug Boolean",
        description="Skip applying the boolean modifier",
        default=False,
    )

    def execute(self, context):
        keywords = self.as_keywords()  # ignore=("blah",)

        main(context, **keywords)

        return {'FINISHED'}

    def invoke(self, context, event):
        print(self.recursion_chance_select)
        wm = context.window_manager
        return wm.invoke_props_dialog(self, width=600)

    def draw(self, context):
        layout = self.layout
        box = layout.box()
        col = box.column()
        col.label(text="Point Source")
        rowsub = col.row()
        rowsub.prop(self, "source")
        rowsub = col.row()
        rowsub.prop(self, "source_limit")
        rowsub.prop(self, "source_noise")
        rowsub = col.row()
        rowsub.prop(self, "cell_scale")

        box = layout.box()
        col = box.column()
        col.label(text="Recursive Shatter")
        rowsub = col.row(align=True)
        rowsub.prop(self, "recursion")
        rowsub.prop(self, "recursion_source_limit")
        rowsub.prop(self, "recursion_clamp")
        rowsub = col.row()
        rowsub.prop(self, "recursion_chance")
        rowsub.prop(self, "recursion_chance_select", expand=True)

        box = layout.box()
        col = box.column()
        col.label(text="Mesh Data")
        rowsub = col.row()
        rowsub.prop(self, "use_smooth_faces")
        rowsub.prop(self, "use_sharp_edges")
        rowsub.prop(self, "use_sharp_edges_apply")
        rowsub.prop(self, "use_data_match")
        rowsub = col.row()

        # on same row for even layout but infact are not all that related
        rowsub.prop(self, "material_index")
        rowsub.prop(self, "use_interior_vgroup")

        # could be own section, control how we subdiv
        rowsub.prop(self, "margin")
        rowsub.prop(self, "use_island_split")

        box = layout.box()
        col = box.column()
        col.label(text="Physics")
        rowsub = col.row(align=True)
        rowsub.prop(self, "mass_mode")
        rowsub.prop(self, "mass")

        box = layout.box()
        col = box.column()
        col.label(text="Object")
        rowsub = col.row(align=True)
        rowsub.prop(self, "use_recenter")

        box = layout.box()
        col = box.column()
        col.label(text="Scene")
        rowsub = col.row(align=True)
        rowsub.prop(self, "use_layer_index")
        rowsub.prop(self, "use_layer_next")
        rowsub.prop(self, "group_name")

        box = layout.box()
        col = box.column()
        col.label(text="Debug")
        rowsub = col.row(align=True)
        rowsub.prop(self, "use_debug_redraw")
        rowsub.prop(self, "use_debug_points")
        rowsub.prop(self, "use_debug_bool")
def register():
    Scene.armature = EnumProperty(
        name='Armature',
        description='Select the armature which will be used by Cats',
        items=Common.get_armature_list,
        update=Common.update_material_list
    )

    Scene.full_body = BoolProperty(
        name='Apply Full Body Tracking Fix',
        description="Applies a general fix for Full Body Tracking.\n\n"
                    'Can potentially reduce the knee bending of every avatar in VRChat.\n'
                    'You can safely ignore the "Spine length zero" warning in Unity',
        default=False
    )

    Scene.combine_mats = BoolProperty(
        name='Combine Same Materials',
        description="Combines similar materials into one, reducing draw calls.\n\n"
                    'Your avatar should visibly look the same after this operation.\n'
                    'This is a very important step for optimizing your avatar.\n'
                    'If you have problems with this, uncheck this option and tell us!\n',
        default=True
    )

    Scene.remove_zero_weight = BoolProperty(
        name='Remove Zero Weight Bones',
        description="Cleans up the bones hierarchy, deleting all bones that don't directly affect any vertices.\n"
                    'Uncheck this if bones you want to keep got deleted',
        default=True
    )

    Scene.keep_end_bones = BoolProperty(
        name='Keep End Bones',
        description="Saves end bones from deletion."
                    '\n\nThis can improve skirt movement for dynamic bones, but increases the bone count.'
                    '\nThis can also fix issues with crumbled finger bones in Unity.'
                    '\nMake sure to always uncheck "Add Leaf Bones" when exporting or use the CATS export button',
        default=False
    )

    Scene.join_meshes = BoolProperty(
        name='Join Meshes',
        description='Joins all meshes of this model together.'
                    '\nIt also:'
                    '\n  - Applies all transformations'
                    '\n  - Repairs broken armature modifiers'
                    '\n  - Applies all decimation and mirror modifiers'
                    '\n  - Merges UV maps correctly'
                    '\n'
                    '\nINFO: You should always join your meshes',
        default=True
    )

    Scene.connect_bones = BoolProperty(
        name='Connect Bones',
        description="This connects all bones to their child bone if they have exactly one child bone.\n"
                    "This will not change how the bones function in any way, it just improves the aesthetic of the armature",
        default=True
    )

    Scene.use_google_only = BoolProperty(
        name='Use Old Translations (not recommended)',
        description="Ignores the internal dictionary and only uses the Google Translator for shape key translations."
                    "\n"
                    '\nThis will result in slower translation speed and worse translations, but the translations will be like in CATS version 0.9.0 and older.'
                    "\nOnly use this if you have animations which rely on the old translations and you don't want to convert them to the new ones",
        default=False
    )

    Scene.show_more_options = BoolProperty(
        name='Show More Options',
        description="Shows more model options",
        default=False
    )

    Scene.merge_mode = EnumProperty(
        name="Merge Mode",
        description="Mode",
        items=[
            ("ARMATURE", "Merge Armatures", "Here you can merge two armatures together."),
            ("MESH", "Attach Mesh", "Here you can attach a mesh to an armature.")
        ]
    )

    Scene.merge_armature_into = EnumProperty(
        name='Base Armature',
        description='Select the armature into which the other armature will be merged\n',
        items=Common.get_armature_list
    )

    Scene.merge_armature = EnumProperty(
        name='Merge Armature',
        description='Select the armature which will be merged into the selected armature above\n',
        items=Common.get_armature_merge_list
    )

    Scene.attach_to_bone = EnumProperty(
        name='Attach to Bone',
        description='Select the bone to which the armature will be attached to\n',
        items=Common.get_bones_merge
    )

    Scene.attach_mesh = EnumProperty(
        name='Attach Mesh',
        description='Select the mesh which will be attached to the selected bone in the selected armature\n',
        items=Common.get_top_meshes
    )

    Scene.merge_same_bones = BoolProperty(
        name='Merge All Bones',
        description='Merges all bones together that have the same name instead of only the base bones (Hips, Spine, etc).'
                    '\nYou will have to make sure that all the bones you want to merge have the same name.'
                    '\n'
                    "\nIf this is checked, you won't need to fix the model with CATS beforehand but it is still advised to do so."
                    "\nIf this is unchecked, CATS will only merge the base bones (Hips, Spine, etc)."
                    "\n"
                    "\nThis can have unintended side effects, so check your model afterwards!"
                    "\n",
        default=False
    )

    Scene.apply_transforms = BoolProperty(
        name='Apply Transforms',
        description='Check this if both armatures and meshes are already at their correct positions.'
                    '\nThis will cause them to stay exactly like they are when merging',
        default=False
    )

    # Decimation
    Scene.decimation_mode = EnumProperty(
        name="Decimation Mode",
        description="Decimation Mode",
        items=[
            ("SAFE", "Safe", 'Decent results - no shape key loss\n'
                             '\n'
                             "This will only decimate meshes with no shape keys.\n"
                             "The results are decent and you won't lose any shape keys.\n"
                             'Eye Tracking and Lip Syncing will be fully preserved.'),

            ("HALF", "Half", 'Good results - minimal shape key loss\n'
                             "\n"
                             "This will only decimate meshes with less than 4 shape keys as those are often not used.\n"
                             'The results are better but you will lose the shape keys in some meshes.\n'
                             'Eye Tracking and Lip Syncing should still work.'),

            ("FULL", "Full", 'Best results - full shape key loss\n'
                             '\n'
                             "This will decimate your whole model deleting all shape keys in the process.\n"
                             'This will give the best results but you will lose the ability to add blinking and Lip Syncing.\n'
                             'Eye Tracking will still work if you disable Eye Blinking.'),

            ("CUSTOM", "Custom", 'Custom results - custom shape key loss\n'
                                 '\n'
                                 "This will let you choose which meshes and shape keys should not be decimated.\n")
        ],
        default='HALF'
    )

    Scene.selection_mode = EnumProperty(
        name="Selection Mode",
        description="Selection Mode",
        items=[
            ("SHAPES", "Shape Keys", 'Select all the shape keys you want to preserve here.'),
            ("MESHES", "Meshes", "Select all the meshes you don't want to decimate here.")
        ]
    )

    Scene.add_shape_key = EnumProperty(
        name='Shape',
        description='The shape key you want to keep',
        items=Common.get_shapekeys_decimation
    )

    Scene.add_mesh = EnumProperty(
        name='Mesh',
        description='The mesh you want to leave untouched by the decimation',
        items=Common.get_meshes_decimation
    )

    Scene.decimate_fingers = BoolProperty(
        name="Save Fingers",
        description="Check this if you don't want to decimate your fingers!\n"
                    "Results will be worse but there will be no issues with finger movement.\n"
                    "This is probably only useful if you have a VR headset.\n"
                    "\n"
                    "This operation requires the finger bones to be named specifically:\n"
                    "Thumb(0-2)_(L/R)\n"
                    "IndexFinger(1-3)_(L/R)\n"
                    "MiddleFinger(1-3)_(L/R)\n"
                    "RingFinger(1-3)_(L/R)\n"
                    "LittleFinger(1-3)_(L/R)"
    )

    Scene.decimate_hands = BoolProperty(
        name="Save Hands",
        description="Check this if you don't want to decimate your full hands!\n"
                    "Results will be worse but there will be no issues with hand movement.\n"
                    "This is probably only useful if you have a VR headset.\n"
                    "\n"
                    "This operation requires the finger and hand bones to be named specifically:\n"
                    "Left/Right wrist\n"
                    "Thumb(0-2)_(L/R)\n"
                    "IndexFinger(1-3)_(L/R)\n"
                    "MiddleFinger(1-3)_(L/R)\n"
                    "RingFinger(1-3)_(L/R)\n"
                    "LittleFinger(1-3)_(L/R)"
    )

    Scene.max_tris = IntProperty(
        name='Tris',
        description="The target amount of tris after decimation",
        default=70000,
        min=1,
        max=200000
    )

    # Eye Tracking
    Scene.eye_mode = EnumProperty(
        name="Eye Mode",
        description="Mode",
        items=[
            ("CREATION", "Creation", "Here you can create eye tracking."),
            ("TESTING", "Testing", "Here you can test how eye tracking will look ingame.")
        ],
        update=Eyetracking.stop_testing
    )

    Scene.mesh_name_eye = EnumProperty(
        name='Mesh',
        description='The mesh with the eyes vertex groups',
        items=Common.get_meshes
    )

    Scene.head = EnumProperty(
        name='Head',
        description='The head bone containing the eye bones',
        items=Common.get_bones_head
    )

    Scene.eye_left = EnumProperty(
        name='Left Eye',
        description='The models left eye bone',
        items=Common.get_bones_eye_l
    )

    Scene.eye_right = EnumProperty(
        name='Right Eye',
        description='The models right eye bone',
        items=Common.get_bones_eye_r
    )

    Scene.wink_left = EnumProperty(
        name='Blink Left',
        description='The shape key containing a blink with the left eye',
        items=Common.get_shapekeys_eye_blink_l
    )

    Scene.wink_right = EnumProperty(
        name='Blink Right',
        description='The shape key containing a blink with the right eye',
        items=Common.get_shapekeys_eye_blink_r
    )

    Scene.lowerlid_left = EnumProperty(
        name='Lowerlid Left',
        description='The shape key containing a slightly raised left lower lid.\n'
                    'Can be set to "Basis" to disable lower lid movement',
        items=Common.get_shapekeys_eye_low_l
    )

    Scene.lowerlid_right = EnumProperty(
        name='Lowerlid Right',
        description='The shape key containing a slightly raised right lower lid.\n'
                    'Can be set to "Basis" to disable lower lid movement',
        items=Common.get_shapekeys_eye_low_r
    )

    Scene.disable_eye_movement = BoolProperty(
        name='Disable Eye Movement',
        description='IMPORTANT: Do your decimation first if you check this!\n'
                    '\n'
                    'Disables eye movement. Useful if you only want blinking.\n'
                    'This creates eye bones with no movement bound to them.\n'
                    'You still have to assign "LeftEye" and "RightEye" to the eyes in Unity',
        subtype='DISTANCE'
    )

    Scene.disable_eye_blinking = BoolProperty(
        name='Disable Eye Blinking',
        description='Disables eye blinking. Useful if you only want eye movement.\n'
                    'This will create the necessary shape keys but leaves them empty',
        subtype='NONE'
    )

    Scene.eye_distance = FloatProperty(
        name='Eye Movement Range',
        description='Higher = more eye movement\n'
                    'Lower = less eye movement\n'
                    'Warning: Too little or too much range can glitch the eyes.\n'
                    'Test your results in the "Eye Testing"-Tab!\n',
        default=0.8,
        min=0.0,
        max=2.0,
        step=1.0,
        precision=2,
        subtype='FACTOR'
    )

    Scene.eye_rotation_x = IntProperty(
        name='Up - Down',
        description='Rotate the eye bones on the vertical axis',
        default=0,
        min=-19,
        max=25,
        step=1,
        subtype='FACTOR',
        update=Eyetracking.set_rotation
    )

    Scene.eye_rotation_y = IntProperty(
        name='Left - Right',
        description='Rotate the eye bones on the horizontal axis.'
                    '\nThis is from your own point of view',
        default=0,
        min=-19,
        max=19,
        step=1,
        subtype='FACTOR',
        update=Eyetracking.set_rotation
    )

    Scene.iris_height = IntProperty(
        name='Iris Height',
        description='Moves the iris away from the eye ball',
        default=0,
        min=0,
        max=100,
        step=1,
        subtype='FACTOR'
    )

    Scene.eye_blink_shape = FloatProperty(
        name='Blink Strength',
        description='Test the blinking of the eye',
        default=1.0,
        min=0.0,
        max=1.0,
        step=1.0,
        precision=2,
        subtype='FACTOR'
    )

    Scene.eye_lowerlid_shape = FloatProperty(
        name='Lowerlid Strength',
        description='Test the lowerlid blinking of the eye',
        default=1.0,
        min=0.0,
        max=1.0,
        step=1.0,
        precision=2,
        subtype='FACTOR'
    )

    # Visemes
    Scene.mesh_name_viseme = EnumProperty(
        name='Mesh',
        description='The mesh with the mouth shape keys',
        items=Common.get_meshes
    )

    Scene.mouth_a = EnumProperty(
        name='Viseme AA',
        description='Shape key containing mouth movement that looks like someone is saying "aa".\nDo not put empty shape keys like "Basis" in here',
        items=Common.get_shapekeys_mouth_ah,
    )

    Scene.mouth_o = EnumProperty(
        name='Viseme OH',
        description='Shape key containing mouth movement that looks like someone is saying "oh".\nDo not put empty shape keys like "Basis" in here',
        items=Common.get_shapekeys_mouth_oh,
    )

    Scene.mouth_ch = EnumProperty(
        name='Viseme CH',
        description='Shape key containing mouth movement that looks like someone is saying "ch". Opened lips and clenched teeth.\nDo not put empty shape keys like "Basis" in here',
        items=Common.get_shapekeys_mouth_ch,
    )

    Scene.shape_intensity = FloatProperty(
        name='Shape Key Mix Intensity',
        description='Controls the strength in the creation of the shape keys. Lower for less mouth movement strength',
        default=1.0,
        min=0.0,
        max=10.0,
        step=0.1,
        precision=2,
        subtype='FACTOR'
    )

    # Bone Parenting
    Scene.root_bone = EnumProperty(
        name='To Parent',
        description='List of bones that look like they could be parented together to a root bone',
        items=Rootbone.get_parent_root_bones,
    )

    # Optimize
    Scene.optimize_mode = EnumProperty(
        name="Optimize Mode",
        description="Mode",
        items=[
            ("ATLAS", "Atlas", "Allows you to make a texture atlas."),
            ("MATERIAL", "Material", "Some various options on material manipulation."),
            ("BONEMERGING", "Bone Merging", "Allows child bones to be merged into their parents."),
        ]
    )

    # Atlas
    # Material.add_to_atlas = BoolProperty(
    #     description='Add this material to the atlas',
    #     default=False
    # )

    # Scene.material_list_index = IntProperty(
    #     default=0
    # )

    # Scene.material_list = CollectionProperty(
    #     type=Atlas.MaterialsGroup
    # )

    # Scene.clear_materials = BoolProperty(
    #     description='Clear materials checkbox',
    #     default=True
    # )

    # Bone Merging
    Scene.merge_ratio = FloatProperty(
        name='Merge Ratio',
        description='Higher = more bones will be merged\n'
                    'Lower = less bones will be merged\n',
        default=50,
        min=1,
        max=100,
        step=1,
        precision=0,
        subtype='PERCENTAGE'
    )

    Scene.merge_mesh = EnumProperty(
        name='Mesh',
        description='The mesh with the bones vertex groups',
        items=Common.get_meshes
    )

    Scene.merge_bone = EnumProperty(
        name='To Merge',
        description='List of bones that look like they could be merged together to reduce overall bones',
        items=Rootbone.get_parent_root_bones,
    )

    # Settings
    Scene.embed_textures = BoolProperty(
        name='Embed Textures on Export',
        description='Enable this to embed the texture files into the FBX file upon export.'
                    '\nUnity will automatically extract these textures and put them into a separate folder.'
                    '\nThis might not work for everyone and it increases the file size of the exported FBX file',
        default=False,
        update=Settings.update_settings
    )
    Scene.use_custom_mmd_tools = BoolProperty(
        name='Use Custom mmd_tools',
        description='Enable this to use your own version of mmd_tools. This will disable the internal cats mmd_tools',
        default=False,
        update=Settings.update_settings
    )

    Scene.debug_translations = BoolProperty(
        name='Debug Google Translations',
        description='Tests the Google Translations and prints the Google response in case of error',
        default=False
    )
Example #27
0
class BlenderkitDownloadOperator(bpy.types.Operator):
    """Download and link asset to scene. Only link if asset already available locally."""
    bl_idname = "scene.blenderkit_download"
    bl_label = "BlenderKit Asset Download"
    bl_options = {'REGISTER', 'UNDO', 'INTERNAL'}

    asset_type: EnumProperty(
        name="Type",
        items=asset_types,
        description="Type of download",
        default="MODEL",
    )
    asset_index: IntProperty(name="Asset Index",
                             description='asset index in search results',
                             default=-1)

    target_object: StringProperty(
        name="Target Object",
        description="Material or object target for replacement",
        default="")

    material_target_slot: IntProperty(
        name="Asset Index",
        description='asset index in search results',
        default=0)
    model_location: FloatVectorProperty(name='Asset Location',
                                        default=(0, 0, 0))
    model_rotation: FloatVectorProperty(name='Asset Rotation',
                                        default=(0, 0, 0))

    replace: BoolProperty(name='Replace',
                          description='replace selection with the asset',
                          default=False)

    cast_parent: StringProperty(name="Particles Target Object",
                                description="",
                                default="")

    # @classmethod
    # def poll(cls, context):
    #     return bpy.context.window_manager.BlenderKitModelThumbnails is not ''

    def execute(self, context):
        s = bpy.context.scene
        sr = s['search results']

        asset_data = sr[self.asset_index].to_dict(
        )  # TODO CHECK ALL OCCURRENCES OF PASSING BLENDER ID PROPS TO THREADS!
        au = s.get('assets used')
        if au == None:
            s['assets used'] = {}
        if asset_data['asset_base_id'] in s.get('assets used'):
            asset_data = s['assets used'][
                asset_data['asset_base_id']].to_dict()

        atype = asset_data['asset_type']
        if bpy.context.mode != 'OBJECT' and (
                atype == 'model' or atype == 'material'
        ) and bpy.context.view_layer.objects.active is not None:
            bpy.ops.object.mode_set(mode='OBJECT')

        if self.replace:  # cleanup first, assign later.
            obs = utils.get_selected_models()

            for ob in obs:
                kwargs = {
                    'cast_parent': self.cast_parent,
                    'target_object': ob.name,
                    'material_target_slot': ob.active_material_index,
                    'model_location': tuple(ob.matrix_world.translation),
                    'model_rotation': tuple(ob.matrix_world.to_euler()),
                    'replace': False,
                    'parent': ob.parent
                }
                utils.delete_hierarchy(ob)
                start_download(asset_data, **kwargs)
        else:
            kwargs = {
                'cast_parent': self.cast_parent,
                'target_object': self.target_object,
                'material_target_slot': self.material_target_slot,
                'model_location': tuple(self.model_location),
                'model_rotation': tuple(self.model_rotation),
                'replace': False
            }

            start_download(asset_data, **kwargs)
        return {'FINISHED'}
class OUT_DebugNode(buildingNode, BuildingTree):
    '''Building Output'''
    bl_idname = 'OUT_DebugNode'
    bl_label = 'Debug'
    bl_icon = 'NODETREE'

    bl_width_min = 200

    ##\brief An empty function to silence some custom property updates.
    #\detail The superclass method cannot be used, Properties can't find it.
    def updateEmpty(self, context):
        return

    lastmode = StringProperty(default="", update=updateEmpty)

    value = StringProperty(default="", update=updateEmpty)

    stringX = StringProperty(default="", update=updateEmpty)
    stringY = StringProperty(default="", update=updateEmpty)
    stringZ = StringProperty(default="", update=updateEmpty)

    ob_name = StringProperty(default="", update=updateEmpty)
    mesh_name = StringProperty(default="", update=updateEmpty)

    v_count = IntProperty(update=updateEmpty)
    e_count = IntProperty(update=updateEmpty)
    f_count = IntProperty(update=updateEmpty)

    ob_pos_X = StringProperty(default="", update=updateEmpty)
    ob_pos_Y = StringProperty(default="", update=updateEmpty)
    ob_pos_Z = StringProperty(default="", update=updateEmpty)

    color = FloatVectorProperty(size=3, update=updateEmpty)

    ##\brief Checks whether the node needs to be updated.
    def updateNode(self, context):
        if not self.lastmode == self.mode_list:
            self.lastmode = self.mode_list
            self.updateInputs(self.mode_list)

    modes = [("Value", "Value", ""), ("Vec3", "Vec3", ""),
             ("Mesh", "Mesh", ""), ("Selection", "Selection", ""),
             ("Color", "Color", "")]

    mode_list = EnumProperty(name="Debug Mode", items=modes, update=updateNode)

    ##\brief Empty method, to avoid exceptions in the update process.
    def triggerData(self, context):
        return

    ##\brief Custom flooding method, returns the node's pointer.
    def floodObsolete(self, context):
        return [self.as_pointer()]

    ##\brief Re-calculates the node's data.
    def recalculate(self):

        if len(self.inputs) > 0:
            if len(self.inputs[0].links) != 0:
                if self.mode_list == "Value":

                    floats = self.inputs[0].returnData()
                    string = ""
                    for f in floats:
                        string = string + str(f)[:8] + ", "

                    string = string[:len(string) - 2]

                    self.value = string

        if len(self.inputs) > 1:
            if len(self.inputs[1].links) != 0:
                if self.mode_list == "Vec3":

                    array = self.inputs[1].returnData()[0]

                    self.stringX = str(array[0])
                    self.stringY = str(array[1])
                    self.stringZ = str(array[2])

        if len(self.inputs) > 2:
            if len(self.inputs[2].links) != 0:
                if self.mode_list == "Mesh":

                    obs = self.inputs[2].returnData()[0]
                    self.ob_name = obs[0].name
                    self.mesh_name = obs[0].data.name

        if len(self.inputs) > 3:
            if len(self.inputs[3].links) != 0:
                if self.mode_list == "Selection":
                    sel = self.inputs[3].returnData()[0]

                    self.v_count = len(sel[0])
                    self.e_count = len(sel[1])
                    self.f_count = len(sel[2])

        if len(self.inputs) > 4:
            if len(self.inputs[4].links) != 0:
                if self.mode_list == "Color":
                    self.color = self.inputs[4].returnData()[0]

        else:
            self.ob_name = ""
            self.stringX = ""
            self.stringY = ""
            self.stringZ = ""
            self.value = ""
            self.v_count = ""
            self.e_count = ""
            self.f_count = ""

    ##\brief Initializes the node.
    def init(self, context):
        self.inputs.new("socket_FLOAT", "Value")
        self.inputs.new("socket_VEC3_F", "Vec3")
        self.inputs.new("socket_MESH", "Mesh")
        self.inputs.new("socket_SELECTION", "Selection")
        self.inputs.new("socket_COL", "Color")

        self.use_custom_color = True
        self.color = (1, 1, 1)

        self.updateNode(context)

    ##\brief GUI.
    def draw_buttons(self, context, layout):

        #Needed for the update operator - this node gives the operator a self-reference so that the operator can backtrack to its caller and call this node's "recalculate()" method
        layout.context_pointer_set("CALLER", self)

        layout.separator()
        row1 = layout.row(align=True)
        row1.prop(self, "mode_list", "")
        layout.separator()
        if self.mode_list == "Value":
            layout.label(text=self.value)
        elif self.mode_list == "Vec3":
            row = layout.row(align=True)
            col1 = row.column(align=True)
            col2 = row.column(align=True)
            rowC11 = col1.row(align=True)
            rowC12 = col1.row(align=True)
            rowC13 = col1.row(align=True)

            rowC21 = col2.row(align=True)
            rowC22 = col2.row(align=True)
            rowC23 = col2.row(align=True)

            rowC11.label(text="X:")
            rowC12.label(text="Y:")
            rowC13.label(text="Z:")

            rowC21.label(text=self.stringX)
            rowC22.label(text=self.stringY)
            rowC23.label(text=self.stringZ)

        elif self.mode_list == "Mesh":
            rowNO = layout.row(align=False)
            rowNO.label(text=self.ob_name, icon='OBJECT_DATA')
            rowNM = layout.row(align=False)
            rowNM.label(text=self.mesh_name, icon='MESH_DATA')

        elif self.mode_list == "Color":
            row1 = layout.row()
            if len(self.inputs[4].links) > 0:
                row1.label(text="RGB: " + str(round(self.color[0], 2)) + ", " +
                           str(round(self.color[1], 2)) + ", " +
                           str(round(self.color[2], 2)))
            else:
                row1.label(text="RGB: NO INPUT")

        else:
            rowVC = layout.row(align=True)
            rowEC = layout.row(align=True)
            rowFC = layout.row(align=True)

            VCcol1 = rowVC.column(align=True)
            VCcol2 = rowVC.column(align=True)
            ECcol1 = rowEC.column(align=True)
            ECcol2 = rowEC.column(align=True)
            FCcol1 = rowFC.column(align=True)
            FCcol2 = rowFC.column(align=True)

            VCcol1.label("Vertices:")
            ECcol1.label("Edges:")
            FCcol1.label("Faces:")

            VCcol2.label(str(self.v_count))
            ECcol2.label(str(self.e_count))
            FCcol2.label(str(self.f_count))

        layout.operator("output.update", text="Update", emboss=True)

        layout.separator()

    ##\brief Makes inputs and outputs visible, based on the node's current settings.
    def updateInputs(self, context):

        #hide all inputs
        for input in self.inputs:
            input.enabled = False

        #add new inputs, based on the selected mode
        if self.mode_list == "Value":
            self.inputs[0].enabled = True
        elif self.mode_list == "Vec3":
            self.inputs[1].enabled = True
        elif self.mode_list == "Mesh":
            self.inputs[2].enabled = True
        elif self.mode_list == "Selection":
            self.inputs[3].enabled = True
        elif self.mode_list == "Color":
            self.inputs[4].enabled = True
        else:
            return ()
Example #29
0
class SvOBJInsolationNode(bpy.types.Node, SverchCustomTreeNode):
    ''' Insolation by RayCast Object '''
    bl_idname = 'SvOBJInsolationNode'
    bl_label = 'Object ID Insolation'
    bl_icon = 'OUTLINER_OB_EMPTY'

    mode: BoolProperty(name='input mode', default=False, update=updateNode)
    #mode2 = BoolProperty(name='output mode', default=False, update=updateNode)
    sort_critical: IntProperty(name='sort_critical',
                               default=12,
                               min=1,
                               max=24,
                               update=updateNode)
    separate: BoolProperty(name='separate the',
                           default=False,
                           update=updateNode)

    def sv_init(self, context):
        si, so = self.inputs.new, self.outputs.new
        #si('StringsSocket', 'Date')
        si('SvObjectSocket', 'Predator')
        si('SvObjectSocket', 'Victim')
        si('VerticesSocket', 'SunRays').use_prop = True
        #so('SvColorSocket',  "Color")
        so('VerticesSocket', "Centers")
        #so('VerticesSocket', "HitP")
        so('StringsSocket', "Hours")
        # self.inputs[2].prop[2] = -1  # z down   # <--- mayybe?

    def draw_buttons_ext(self, context, layout):
        row = layout.row(align=True)
        row.prop(self, "mode", text="In Mode")
        row.prop(self, "sort_critical", text="Limit")
        #row.prop(self,    "mode2",   text="Out Mode")

    def process(self):
        o, r, e = self.inputs
        #dd,o,r,e = self.inputs
        N, H = self.outputs
        #S,H,P,N = self.outputs
        outfin, OutLoc_, obj, rec, sm1, sc = [], [], o.sv_get(), r.sv_get(
        )[0], self.mode, self.sort_critical
        #lenor = len(s.sv_get()[0])
        lendir = len(e.sv_get()[0])
        leno = len(obj)
        #st, en = match_cross([s.sv_get()[0], e.sv_get()[0]]) # 1,1,1,2,2,2 + 4,5,6,4,5,6
        st = []
        for i in rec.data.polygons:
            st.append(i.center[:])
            #(np.array(st_).sum(axis=1)/len(i.vertices)).tolist())
            #(np.array([[rec.data.vertices[k].co[:] for k in i.vertices]/len(i.vertices) for i in rec.data.polygons]).sum(axis=1)).tolist()
        if N.is_linked:
            N.sv_set([st])
        lenor = len(st)
        st, en = match_cross([st, e.sv_get()[0]])  # 1,1,1,2,2,2 + 4,5,6,4,5,6

        for OB in obj:
            if OB.type == 'FONT':
                NOB = FakeObj(OB)
            else:
                NOB = OB

            if sm1:
                obm = NOB.matrix_local.inverted()
                outfin.append([
                    NOB.ray_cast(obm @ Vector(i), obm @ Vector(i2))
                    for i, i2 in zip(st, en)
                ])
            else:
                outfin.append([NOB.ray_cast(i, i2) for i, i2 in zip(st, en)])

            if OB.type == 'FONT':
                del NOB
        self.debug(outfin)

        OutS_ = np.array([[i[0] for i in i2]
                          for i2 in outfin]).reshape([leno, lenor, lendir])

        def colset(rec, OutS_):
            OutS_ = 1 - OutS_.sum(axis=2) / lendir
            OutS = np.array([[[i, i, i] for i in k] for k in OutS_.tolist()
                             ]).reshape([leno, lenor, 3]).tolist()
            if not 'SvInsol' in rec.data.vertex_colors:
                rec.data.vertex_colors.new(name='SvInsol')
            colors = rec.data.vertex_colors['SvInsol'].data
            for i, pol in enumerate(rec.data.polygons):
                self.debug(pol.loop_indices, OutS[0][i])
                for co in pol.loop_indices:
                    colors[co].color = OutS[0][i]

        colset(rec, OutS_)

        def matset(rec):
            # add new material with nodes
            ms = rec.material_slots
            if not 'svmat' in bpy.data.materials:
                manew = bpy.data.materials.new('svmat')
                manew.use_nodes = True
            if not len(ms):
                # append if no slots
                rec.data.materials.append(manew)
            if not ms[-1].material:
                # assign if no material in slot
                ms[-1].material = manew
            trem = ms[-1].material.node_tree
            matnodes = trem.nodes
            if not 'Attribute' in matnodes:
                att = matnodes.new('ShaderNodeAttribute')
            else:
                att = matnodes['Attribute']
            if not 'Diffuse BSDF' in matnodes:
                dif = matnodes.new('ShaderNodeBsdfDiffuse')
            else:
                dif = matnodes['Diffuse BSDF']
            att.attribute_name = 'SvInsol'
            trem.links.new(dif.inputs[0], att.outputs[0])

        matset(rec)
        if H.is_linked:
            OutH = []
            for k in OutS_.sum(axis=2).tolist():
                OutH_ = []
                for i in k:
                    li = lendir - i
                    if li < sc + 1:
                        OutH_.append([str(li)])
                    else:
                        OutH_.append([''])
                OutH.append(OutH_)
            #OutH = [[[str(lendir-i)] for i in k] for k in OutS_.sum(axis=2).tolist()]
            H.sv_set(OutH)
        '''if S.is_linked:
            OutS = np.array([[[i,i,0,1.0] for i in k] for k in OutS_.tolist()]).reshape([leno,lenor,4]).tolist()
            #OutS = 1-OutS_.sum(axis=2)/lendir
            #OutS = np.array([[[[i,i,0,1.0] for t in range(4)] for i in k] for k in OutS_.tolist()]).reshape([leno,lenor*4,4]).tolist() #.reshape([leno,lenor*4,4]).tolist()
            #OutS = [round(1-sum([OutS_[0][k*u] for u in range(lendir)])/lendir, 1) for k in range(lenor)]
            S.sv_set(OutS)'''
        ''' # colors works wrong
        if sm2:
            if P.is_linked:
                for i,i2 in zip(obj,outfin):
                    omw = i.matrix_world
                    OutLoc_.append([(omw*i[1])[:] for i in i2])
                OutLoc_ = np.array(OutLoc_).reshape([leno,lenor,lendir,3])
                OutLoc = OutLoc_[0,:,0]
                #OutLoc = [[OutLoc_[0][k*u] for u in range(lendir)] for k in range(lenor)]
                P.sv_set([OutLoc.tolist()])
        else:
            if P.is_linked:
                OutLoc_ = np.array([[i[1][:] for i in i2] for i2 in outfin]).reshape([leno,lenor,lendir,3])
                #OutLoc_ = [[i[1][:] for i in i2] for i2 in outfin]
                OutLoc = OutLoc_[0,:,0]
                #OutLoc = [[OutLoc_[0][k*u] for u in range(lendir)] for k in range(lenor)]
                P.sv_set([OutLoc.tolist()])
        '''
        ''' # N solved upper easily
class LightMapPack(Operator):
    '''Follow UVs from active quads along continuous face loops'''
    bl_idname = "uv.lightmap_pack"
    bl_label = "Lightmap Pack"
    bl_options = {'REGISTER', 'UNDO'}

    PREF_CONTEXT = bpy.props.EnumProperty(
            name="Selection",
            items=(("SEL_FACES", "Selected Faces", "Space all UVs evently"),
                   ("ALL_FACES", "All Faces", "Average space UVs edge length of each loop"),
                   ("ALL_OBJECTS", "Selected Mesh Object", "Average space UVs edge length of each loop")
                   ),
            )

    # Image & UVs...
    PREF_PACK_IN_ONE = BoolProperty(
            name="Share Tex Space",
            description=("Objects Share texture space, map all objects "
                         "into 1 uvmap"),
            default=True,
            )
    PREF_NEW_UVLAYER = BoolProperty(
            name="New UV Layer",
            description="Create a new UV layer for every mesh packed",
            default=False,
            )
    PREF_APPLY_IMAGE = BoolProperty(
            name="New Image",
            description=("Assign new images for every mesh (only one if "
                         "shared tex space enabled)"),
            default=False,
            )
    PREF_IMG_PX_SIZE = IntProperty(
            name="Image Size",
            description="Width and Height for the new image",
            min=64, max=5000,
            default=512,
            )
    # UV Packing...
    PREF_BOX_DIV = IntProperty(
            name="Pack Quality",
            description="Pre Packing before the complex boxpack",
            min=1, max=48,
            default=12,
            )
    PREF_MARGIN_DIV = FloatProperty(
            name="Margin",
            description="Size of the margin as a division of the UV",
            min=0.001, max=1.0,
            default=0.1,
            )

    def execute(self, context):
        kwargs = self.as_keywords()
        PREF_CONTEXT = kwargs.pop("PREF_CONTEXT")

        if PREF_CONTEXT == 'SEL_FACES':
            kwargs["PREF_ACT_ONLY"] = True
            kwargs["PREF_SEL_ONLY"] = True
        elif PREF_CONTEXT == 'ALL_FACES':
            kwargs["PREF_ACT_ONLY"] = True
            kwargs["PREF_SEL_ONLY"] = False
        elif PREF_CONTEXT == 'ALL_OBJECTS':
            kwargs["PREF_ACT_ONLY"] = False
            kwargs["PREF_SEL_ONLY"] = False
        else:
            raise Exception("invalid context")

        kwargs["PREF_MARGIN_DIV"] = int(1.0 / (kwargs["PREF_MARGIN_DIV"] / 100.0))

        return unwrap(self, context, **kwargs)

    def invoke(self, context, event):
        wm = context.window_manager
        return wm.invoke_props_dialog(self)