Example #1
0
class LuxCoreLightProps(bpy.types.PropertyGroup):
    def update_image(self, context):
        if context.lamp:
            # For spot lamp (toggle projection mode)
            if context.lamp.type == "AREA":
                context.lamp.use_square = self.image is not None

    def update_is_laser(self, context):
        if context.lamp:
            # For area lamp (laser can't be rectangular)
            if self.is_laser:
                context.lamp.shape = "SQUARE"

    ##############################################
    # BlendLuxCore specific properties needed to translate LuxCore light concepts to Blender
    sun_types = [
        ("sun", "Sun", "Sun", 0),
        ("distant", "Distant",
         "Distant star without atmosphere simulation (emits parallel light)",
         1),
    ]
    sun_type = EnumProperty(name="Sun Type", items=sun_types, default="sun")

    is_laser = BoolProperty(
        name="Laser",
        default=False,
        update=update_is_laser,
        description="Laser light emitting parallel light rays")

    ##############################################
    # Generic properties shared by all light types
    gain = FloatProperty(name="Gain",
                         default=1,
                         min=0,
                         description="Brightness multiplier")
    rgb_gain = FloatVectorProperty(name="Tint",
                                   default=(1, 1, 1),
                                   min=0,
                                   max=1,
                                   subtype="COLOR")
    samples = IntProperty(name="Samples",
                          default=-1,
                          min=-1,
                          description=SAMPLES_DESCRIPTION)
    importance = FloatProperty(name="Importance",
                               default=1,
                               min=0,
                               description=IMPORTANCE_DESCRIPTION)
    # TODO: id

    ##############################################
    # Light type specific properties (some are shared by multiple lights, noted in comments)
    # TODO: check min/max, add descriptions

    # sun, sky2
    turbidity = FloatProperty(name="Turbidity", default=2.2, min=0, max=30)

    # sun
    relsize = FloatProperty(name="Relative Size", default=1, min=0.05)

    # sky2 (is in world propertys, not sure if it's necessary to have a sky2 light)
    # groundalbedo = FloatVectorProperty(name="Ground Albedo", default=(0.5, 0.5, 0.5), min=0, max=1, subtype="COLOR")
    # ground_enable = BoolProperty(name="Use Ground Color", default=False)
    # ground_color = FloatVectorProperty(name="Ground Color", default=(0.5, 0.5, 0.5), min=0, max=1, subtype="COLOR")

    # The image property has different names on different lights:
    # infinite: file
    # mappoint: mapfile
    # projection: mapfile
    image = PointerProperty(name="Image",
                            type=bpy.types.Image,
                            update=update_image)
    gamma = FloatProperty(name="Gamma",
                          default=1,
                          min=0,
                          description=GAMMA_DESCRIPTION)

    # infinite
    sampleupperhemisphereonly = BoolProperty(
        name="Sample Upper Hemisphere Only",
        default=False,
        description=SAMPLEUPPERHEMISPHEREONLY_DESCRIPTION)

    # point, mappoint, spot, laser
    power = FloatProperty(name="Power (W)",
                          default=0,
                          min=0,
                          description=POWER_DESCRIPTION)
    efficacy = FloatProperty(name="Efficacy (lm/W)",
                             default=0,
                             min=0,
                             description=EFFICACY_DESCRIPTION)

    # mappoint
    iesfile = StringProperty(name="IES File", subtype="FILE_PATH")
    flipz = BoolProperty(name="Flip IES Z Axis", default=False)
    # not exposed: emission.map.width, emission.map.height - do we need them?

    # spot
    # Note: coneangle and conedeltaangle are set with default Blender properties
    # (spot_size and spot_blend)

    # projection
    # Note: fov is set with default Blender properties

    # distant
    theta = FloatProperty(name="Size", default=10, min=0, soft_min=0.05)
    def init_props(cls, scene):
        def get_func(_):
            return MUV_OT_TextureProjection.is_running(bpy.context)

        def set_func(_, __):
            pass

        def update_func(_, __):
            bpy.ops.uv.muv_texture_projection('INVOKE_REGION_WIN')

        scene.muv_texture_projection_enabled = BoolProperty(
            name="Texture Projection Enabled",
            description="Texture Projection is enabled",
            default=False)
        scene.muv_texture_projection_enable = BoolProperty(
            name="Texture Projection Enabled",
            description="Texture Projection is enabled",
            default=False,
            get=get_func,
            set=set_func,
            update=update_func)
        scene.muv_texture_projection_tex_scaling = FloatVectorProperty(
            name="Scaling",
            description="Texture Scale",
            default=(0.5, 0.5),
            min=-100.0,
            max=100.0,
            size=2,
            subtype='XYZ')
        scene.muv_texture_projection_tex_rotation = FloatProperty(
            name="Rotation",
            description="Texture Rotate",
            default=0.0,
            min=-360.0,
            max=360.0,
            subtype='ANGLE')
        scene.muv_texture_projection_tex_translation = FloatVectorProperty(
            name="Translation",
            description="Texture Translate",
            default=(0.0, 0.0),
            min=-2000.0,
            max=2000.0,
            size=2,
            subtype='XYZ')
        scene.muv_texture_projection_tex_image = EnumProperty(
            name="Image",
            description="Texture Image",
            items=_get_loaded_texture_name)
        scene.muv_texture_projection_tex_transparency = FloatProperty(
            name="Transparency",
            description="Texture Transparency",
            default=0.2,
            min=0.0,
            max=1.0)
        scene.muv_texture_projection_adjust_window = BoolProperty(
            name="Adjust Window",
            description="Scale of renderered texture is fitted to window",
            default=True)
        scene.muv_texture_projection_apply_tex_aspect = BoolProperty(
            name="Texture Aspect Ratio",
            description="Apply Texture Aspect ratio to displayed texture",
            default=True)
        scene.muv_texture_projection_assign_uvmap = BoolProperty(
            name="Assign UVMap",
            description="Assign UVMap when no UVmaps are available",
            default=True)
class OBJECT_OT_add_random_object(Operator, AddObjectHelper):
    """Create Random Object"""
    bl_idname = "mesh.add_random_object"
    bl_label = "Swap Random Object"
    bl_options = {'REGISTER', 'UNDO'}

    scale: FloatVectorProperty(
        name="scale",
        default=(1.0, 1.0, 1.0),
        subtype='TRANSLATION',
        description="scaling",
    )

    def execute(self, context):
        selected_objects = bpy.context.selected_objects
        old_bounds = ["-1", "-1", "-1", "-1", "1", "1", "1", "1"]
        if selected_objects:
            for obj in selected_objects:
                bpy.ops.view3d.snap_cursor_to_selected()
                bpy.context.scene.cursor.rotation_euler = obj.rotation_euler
                # old_bound_box_corners_in_world_space = [obj.matrix_world @ Vector(corner) for corner in obj.bound_box]

                # get longest bounding box edge size
                bb = obj.bound_box
                dx_local = max(bb[i][0]
                               for i in range(8)) - min(bb[i][0]
                                                        for i in range(8))
                dy_local = max(bb[i][1]
                               for i in range(8)) - min(bb[i][1]
                                                        for i in range(8))
                dz_local = max(bb[i][2]
                               for i in range(8)) - min(bb[i][2]
                                                        for i in range(8))
                old_longest_side = max(dx_local * obj.scale[0],
                                       dx_local * obj.scale[1],
                                       dx_local * obj.scale[2])

                bpy.data.objects.remove(bpy.data.objects[obj.name],
                                        do_unlink=True)
                empty_trash(self, context)

        object_commands = [
            "bpy.ops.mesh.primitive_cube_add(",
            "bpy.ops.mesh.primitive_cube_add(",
            "bpy.ops.mesh.primitive_cube_add(",
            "bpy.ops.mesh.primitive_cube_add(",
            "bpy.ops.mesh.primitive_cube_add(",
            "bpy.ops.mesh.primitive_cone_add(",
            "bpy.ops.mesh.primitive_cross_joint_add(",
            "bpy.ops.mesh.primitive_cylinder_add(",
            "bpy.ops.mesh.primitive_diamond_add(",
            "bpy.ops.mesh.primitive_elbow_joint_add(",
            "bpy.ops.mesh.primitive_gear(", "bpy.ops.mesh.primitive_gem_add(",
            "bpy.ops.mesh.primitive_ico_sphere_add(",
            "bpy.ops.mesh.primitive_monkey_add(",
            "bpy.ops.mesh.primitive_plane_add(",
            "bpy.ops.mesh.primitive_round_cube_add(",
            "bpy.ops.mesh.primitive_star_add(",
            "bpy.ops.mesh.primitive_steppyramid_add(",
            "bpy.ops.mesh.primitive_supertoroid_add(",
            "bpy.ops.mesh.primitive_teapot_add(",
            "bpy.ops.mesh.primitive_tee_joint_add(",
            "bpy.ops.mesh.primitive_torus_add(",
            "bpy.ops.mesh.primitive_torusknot_add(",
            "bpy.ops.mesh.primitive_uv_sphere_add(",
            "bpy.ops.mesh.primitive_wye_joint_add("
        ]
        i = len(object_commands) - 1
        if i > 0:
            random_int = random.randint(0, i)
            while (random_int == previous_random_object_int):
                random_int = random.randint(0, i)
                if (random_int != previous_random_object_int):
                    break
        else:
            random_int = 0

        print(object_commands[random_int] + "==========================")
        eval(object_commands[random_int] + "rotation=(" +
             str(bpy.context.scene.cursor.rotation_euler[0]) + " ," +
             str(bpy.context.scene.cursor.rotation_euler[1]) + " ," +
             str(bpy.context.scene.cursor.rotation_euler[2]) + "))")

        new_random_object = bpy.context.selected_objects[0]
        # new_random_object.bound_box = old_bounds

        if selected_objects:
            # fit to old object
            bb = new_random_object.bound_box
            dx_local = max(bb[i][0] for i in range(8)) - min(bb[i][0]
                                                             for i in range(8))
            dy_local = max(bb[i][1] for i in range(8)) - min(bb[i][1]
                                                             for i in range(8))
            dz_local = max(bb[i][2] for i in range(8)) - min(bb[i][2]
                                                             for i in range(8))
            new_longest_side = max(dx_local * new_random_object.scale[0],
                                   dx_local * new_random_object.scale[1],
                                   dx_local * new_random_object.scale[2])
            new_scale = old_longest_side / new_longest_side
        else:
            new_scale = 1

        new_random_object.scale = [new_scale, new_scale, new_scale]
        bpy.ops.object.transform_apply(location=False,
                                       rotation=False,
                                       scale=True)
        bpy.ops.object.mode_set(mode='EDIT')
        bpy.ops.mesh.remove_doubles()
        bpy.ops.mesh.region_to_loop()
        bpy.ops.mesh.edge_face_add()
        bpy.ops.mesh.select_all(action='TOGGLE')
        bpy.ops.mesh.normals_make_consistent(inside=False)

        bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
        bpy.ops.object.shade_smooth()
        new_random_object.data.use_auto_smooth = True
        # new_random_object.data.auto_smooth_angle = 0.785398 #45
        new_random_object.data.auto_smooth_angle = 1.15192  #66

        bpy.ops.object.select_all(action='DESELECT')
        new_random_object = bpy.context.view_layer.objects.active
        new_random_object.select_set(state=True)
        bpy.context.view_layer.objects.active = new_random_object

        layer = bpy.context.view_layer
        layer.update()

        return {'FINISHED'}
Example #4
0
class SverchokPreferences(AddonPreferences):

    bl_idname = __package__

    def update_debug_mode(self, context):
        data_structure.DEBUG_MODE = self.show_debug

    def update_heat_map(self, context):
        data_structure.heat_map_state(self.heat_map)

    def set_frame_change(self, context):
        handlers.set_frame_change(self.frame_change_mode)

    def update_theme(self, context):
        color_def.rebuild_color_cache()
        if self.auto_apply_theme:
            color_def.apply_theme()

    tab_modes = [(k, k, '', i)
                 for i, k in enumerate(["General", "Node Defaults", "Theme"])]

    selected_tab: bpy.props.EnumProperty(items=tab_modes,
                                         description="pick viewing mode",
                                         default="General")

    #  debugish...
    show_debug: BoolProperty(name="Print update timings",
                             description="Print update timings in console",
                             default=False,
                             subtype='NONE',
                             update=update_debug_mode)

    no_data_color: FloatVectorProperty(
        name="No data",
        description='When a node can not get data',
        size=3,
        min=0.0,
        max=1.0,
        default=(1, 0.3, 0),
        subtype='COLOR',
        update=update_system.update_error_colors)

    exception_color: FloatVectorProperty(
        name="Error",
        description='When node has an exception',
        size=3,
        min=0.0,
        max=1.0,
        default=(0.8, 0.0, 0),
        subtype='COLOR',
        update=update_system.update_error_colors)

    #  heat map settings
    heat_map: BoolProperty(name="Heat map",
                           description="Color nodes according to time",
                           default=False,
                           subtype='NONE',
                           update=update_heat_map)

    heat_map_hot: FloatVectorProperty(name="Heat map hot",
                                      description='',
                                      size=3,
                                      min=0.0,
                                      max=1.0,
                                      default=(.8, 0, 0),
                                      subtype='COLOR')

    heat_map_cold: FloatVectorProperty(name="Heat map cold",
                                       description='',
                                       size=3,
                                       min=0.0,
                                       max=1.0,
                                       default=(1, 1, 1),
                                       subtype='COLOR')

    # Profiling settings
    profiling_sections = [
        ("NONE", "Disable", "Disable profiling", 0),
        ("MANUAL", "Marked methods only",
         "Profile only methods that are marked with @profile decorator", 1),
        ("UPDATE", "Node tree update",
         "Profile whole node tree update process", 2)
    ]

    profile_mode: EnumProperty(name="Profiling mode",
                               items=profiling_sections,
                               default="NONE",
                               description="Performance profiling mode")

    developer_mode: BoolProperty(
        name="Developer mode",
        description=
        "Show some additional panels or features useful for Sverchok developers only",
        default=False)

    #  theme settings

    sv_theme: EnumProperty(items=color_def.themes,
                           name="Theme preset",
                           description="Select a theme preset",
                           update=color_def.color_callback,
                           default="default_theme")

    auto_apply_theme: BoolProperty(name="Apply theme",
                                   description="Apply theme automaticlly",
                                   default=False)

    apply_theme_on_open: BoolProperty(name="Apply theme",
                                      description="Apply theme automaticlly",
                                      default=False)

    color_viz: FloatVectorProperty(name="Visualization",
                                   description='',
                                   size=3,
                                   min=0.0,
                                   max=1.0,
                                   default=(1, 0.3, 0),
                                   subtype='COLOR',
                                   update=update_theme)

    color_tex: FloatVectorProperty(name="Text",
                                   description='',
                                   size=3,
                                   min=0.0,
                                   max=1.0,
                                   default=(0.5, 0.5, 1),
                                   subtype='COLOR',
                                   update=update_theme)

    color_sce: FloatVectorProperty(name="Scene",
                                   description='',
                                   size=3,
                                   min=0.0,
                                   max=1.0,
                                   default=(0, 0.5, 0.2),
                                   subtype='COLOR',
                                   update=update_theme)

    color_lay: FloatVectorProperty(name="Layout",
                                   description='',
                                   size=3,
                                   min=0.0,
                                   max=1.0,
                                   default=(0.674, 0.242, 0.363),
                                   subtype='COLOR',
                                   update=update_theme)

    color_gen: FloatVectorProperty(name="Generator",
                                   description='',
                                   size=3,
                                   min=0.0,
                                   max=1.0,
                                   default=(0, 0.5, 0.5),
                                   subtype='COLOR',
                                   update=update_theme)

    #  frame change
    frame_change_modes = [
        ("PRE", "Pre", "Update Sverchok before frame change", 0),
        ("POST", "Post", "Update Sverchok after frame change", 1),
        ("NONE", "None", "Sverchok doesn't update on frame change", 2)
    ]

    frame_change_mode: EnumProperty(items=frame_change_modes,
                                    name="Frame change",
                                    description="Select frame change handler",
                                    default="POST",
                                    update=set_frame_change)

    #  ctrl+space settings

    show_icons: BoolProperty(name="Show icons in ctrl+space menu",
                             default=False,
                             description="Use icons in ctrl+space menu")

    over_sized_buttons: BoolProperty(default=False,
                                     name="Big buttons",
                                     description="Very big buttons")

    node_panel_modes = [("X", "Do not show", "Do not show node buttons", 0),
                        ("T", "T panel",
                         "Show node buttons under the T panel", 1),
                        ("N", "N panel", "Show node under the N panel", 2)]

    node_panels: EnumProperty(
        items=node_panel_modes,
        name="Display node buttons",
        description=
        "Where to show node insertion buttons. Restart Blender to apply changes.",
        default="X")

    node_panels_icons_only: BoolProperty(
        name="Display icons only",
        description=
        "Show node icon only when icon has an icon, otherwise show it's name",
        default=True)

    node_panels_columns: IntProperty(
        name="Columns",
        description="Number of icon panels per row",
        default=4,
        min=2,
        max=12)

    enable_live_objin: BoolProperty(
        description="Objects in edit mode will be updated in object-in Node")

    ##  BLF/BGL/GPU  scale and location props

    render_scale: FloatProperty(default=1.0,
                                min=0.01,
                                step=0.01,
                                description='default render scale')

    render_location_xy_multiplier: FloatProperty(
        default=1.0,
        min=0.01,
        step=0.01,
        description='default render location scale')

    stethoscope_view_scale: FloatProperty(
        default=1.0,
        min=0.01,
        step=0.01,
        description='default stethoscope scale')

    index_viewer_scale: FloatProperty(default=1.0,
                                      min=0.01,
                                      step=0.01,
                                      description='default index viewer scale')

    ##

    datafiles = os.path.join(
        bpy.utils.user_resource('DATAFILES', path='sverchok', create=True))
    defaults_location: StringProperty(
        default=datafiles,
        description='usually ..data_files\\sverchok\\defaults\\nodes.json')
    external_editor: StringProperty(
        description='which external app to invoke to view sources')
    real_sverchok_path: StringProperty(
        description='use with symlinked to get correct src->dst')

    # Logging settings

    def update_log_level(self, context):
        logging.info("Setting log level to %s", self.log_level)
        logging.setLevel(self.log_level)

    log_levels = [("DEBUG", "Debug", "Debug output", 0),
                  ("INFO", "Information", "Informational output", 1),
                  ("WARNING", "Warnings", "Show only warnings and errors", 2),
                  ("ERROR", "Errors", "Show errors only", 3)]

    log_level: EnumProperty(
        name="Logging level",
        description=
        "Minimum events severity level to output. All more severe messages will be logged as well.",
        items=log_levels,
        update=update_log_level,
        default="INFO")

    log_to_buffer: BoolProperty(
        name="Log to text buffer",
        description="Enable log output to internal Blender's text buffer",
        default=True)
    log_to_buffer_clean: BoolProperty(
        name="Clear buffer at startup",
        description="Clear text buffer at each Blender startup",
        default=False)
    log_to_file: BoolProperty(name="Log to file",
                              description="Enable log output to external file",
                              default=False)
    log_to_console: BoolProperty(
        name="Log to console",
        description=
        "Enable log output to console / terminal / standard output.",
        default=True)

    log_buffer_name: StringProperty(name="Buffer name", default="sverchok.log")
    log_file_name: StringProperty(name="File path",
                                  default=os.path.join(datafiles,
                                                       "sverchok.log"))

    # updating sverchok
    dload_archive_name: StringProperty(
        name="archive name",
        default="b28_prelease_master")  # default = "master"
    dload_archive_path: StringProperty(
        name="archive path",
        default="https://github.com/nortikin/sverchok/archive/")

    def draw(self, context):

        layout = self.layout
        layout.row().prop(self, 'selected_tab', expand=True)

        if self.selected_tab == "General":

            col = layout.row().column()
            col_split = col.split(factor=0.5)
            col1 = col_split.column()
            col1.label(text="UI:")
            col1.prop(self, "show_icons")

            toolbar_box = col1.box()
            toolbar_box.label(text="Node toolbars")
            toolbar_box.prop(self, "node_panels")
            if self.node_panels != "X":
                toolbar_box.prop(self, "node_panels_icons_only")
                if self.node_panels_icons_only:
                    toolbar_box.prop(self, "node_panels_columns")

            col1.prop(self, "over_sized_buttons")
            col1.prop(self, "enable_live_objin", text='Enable Live Object-In')
            col1.prop(self, "external_editor", text="Ext Editor")
            col1.prop(self, "real_sverchok_path", text="Src Directory")

            col2 = col_split.split().column()
            col2.label(text="Frame change handler:")
            col2.row().prop(self, "frame_change_mode", expand=True)
            col2.separator()

            col2box = col2.box()
            col2box.label(text="Debug:")
            col2box.prop(self, "profile_mode")
            col2box.prop(self, "show_debug")
            col2box.prop(self, "heat_map")
            col2box.prop(self, "developer_mode")

            log_box = col2.box()
            log_box.label(text="Logging:")
            log_box.prop(self, "log_level")

            buff_row = log_box.row()
            buff_row.prop(self, "log_to_buffer")
            if self.log_to_buffer:
                buff_row.prop(self, "log_buffer_name")
                log_box.prop(self, "log_to_buffer_clean")

            file_row = log_box.row()
            file_row.prop(self, "log_to_file")
            if self.log_to_file:
                file_row.prop(self, "log_file_name")

            log_box.prop(self, "log_to_console")

        if self.selected_tab == "Node Defaults":

            row = layout.row()
            col = row.column(align=True)
            row_sub1 = col.row().split(factor=0.5)
            box_sub1 = row_sub1.box()
            box_sub1_col = box_sub1.column(align=True)

            box_sub1_col.label(text='Render Scale & Location')
            box_sub1_col.prop(self,
                              'render_location_xy_multiplier',
                              text='xy multiplier')
            box_sub1_col.prop(self, 'render_scale', text='scale')

            box_sub1_col.label(text='Stethoscope')
            box_sub1_col.prop(self, 'stethoscope_view_scale', text='scale')

            box_sub1_col.label(text='Index Viewer')
            box_sub1_col.prop(self, 'index_viewer_scale', text='scale')

            col3 = row_sub1.split().column()
            col3.label(text='Location of custom defaults')
            col3.prop(self, 'defaults_location', text='')

        if self.selected_tab == "Theme":

            row = layout.row()
            col = row.column(align=True)
            split = col.row().split(factor=0.66)
            split2 = col.row().split(factor=0.66)
            left_split = split.row()
            right_split = split.row()

            split_viz_colors = left_split.column().split(factor=0.5,
                                                         align=True)

            if True:
                col1 = split_viz_colors.column()
                for name in ['color_viz', 'color_tex', 'color_sce']:
                    r = col1.row()
                    r.prop(self, name)

                col2 = split_viz_colors.column()
                for name in ['color_lay', 'color_gen']:
                    r = col2.row()
                    r.prop(self, name)

            split_extra_colors = split2.column().split()
            col_x1 = split_extra_colors.column()
            col_x1.label(text="Error colors: ( error / no data )")
            row_x1 = col_x1.row()
            row_x1.prop(self, "exception_color", text='')
            row_x1.prop(self, "no_data_color", text='')

            col_x2 = split_extra_colors.split().column()
            col_x2.label(text="Heat map colors: ( hot / cold )")
            row_x2 = col_x2.row()
            row_x2.active = self.heat_map
            row_x2.prop(self, "heat_map_hot", text='')
            row_x2.prop(self, "heat_map_cold", text='')

            col3 = right_split.column()
            col3.label(text='Theme:')
            col3.prop(self, 'sv_theme', text='')
            col3.separator()
            col3.prop(self,
                      'auto_apply_theme',
                      text="Auto apply theme changes")
            col3.prop(self,
                      'apply_theme_on_open',
                      text="Apply theme when opening file")
            col3.operator('node.sverchok_apply_theme',
                          text="Apply theme to layouts")

        # FOOTER

        row = layout.row()
        col = row.column(align=True)
        col.label(text="Links:")
        row1 = col.row(align=True)
        row1.scale_y = 2.0
        row1.operator('wm.url_open', text='Sverchok home page'
                      ).url = 'http://nikitron.cc.ua/blend_scripts.html'
        row1.operator('wm.url_open', text='Documentation'
                      ).url = 'http://nikitron.cc.ua/sverch/html/main.html'

        if context.scene.sv_new_version:
            row1.operator('node.sverchok_update_addon',
                          text='Upgrade Sverchok addon')
        else:
            row1.operator('node.sverchok_check_for_upgrades_wsha',
                          text='Check for new version')
Example #5
0
class SvLatheNode(bpy.types.Node, SverchCustomTreeNode):

    bl_idname = 'SvLatheNode'
    bl_label = 'Sv Lathe Node'
    bl_icon = 'OUTLINER_OB_EMPTY'

    remove_doubles = BoolProperty(name='merge',
                                  description='Remove doubles',
                                  update=updateNode)
    dist = FloatProperty(name="merge distance",
                         default=0.0001,
                         update=updateNode)
    Degrees = FloatProperty(name="Degrees", default=360.0, update=updateNode)
    Steps = IntProperty(name="Steps", default=20, min=0, update=updateNode)
    cent = FloatVectorProperty(name='cent', size=3, update=updateNode)
    dvec = FloatVectorProperty(name='dvec', size=3, update=updateNode)
    axis = FloatVectorProperty(name='axis',
                               size=3,
                               update=updateNode,
                               default=(0, 0, 1))

    def sv_init(self, context):
        self.inputs.new('VerticesSocket', 'Verts', 'Verts')
        self.inputs.new('StringsSocket', 'Edges', 'Edges')
        self.inputs.new('VerticesSocket', 'cent', 'cent').prop_name = 'cent'
        self.inputs.new('VerticesSocket', 'axis', 'axis').prop_name = 'axis'
        self.inputs.new('VerticesSocket', 'dvec', 'dvec').prop_name = 'dvec'
        self.inputs.new('StringsSocket', 'Degrees',
                        'Degrees').prop_name = 'Degrees'
        self.inputs.new('StringsSocket', 'Steps', 'Steps').prop_name = 'Steps'

        self.outputs.new('VerticesSocket', 'Verts', 'Verts')
        self.outputs.new('StringsSocket', 'Poly', 'Poly')

    def draw_buttons(self, context, layout):
        row = layout.row(align=True)
        row.prop(self, "remove_doubles", text="merge")

    def nothing_to_process(self):

        if not (self.inputs['Verts'].links and self.outputs['Verts'].links):
            return True

    def process(self):

        if self.nothing_to_process():
            return

        inputs = self.inputs

        def get_socket(x):
            r = inputs[x].sv_get()
            r = dataCorrect(r)
            return r

        socket_names = [
            'Verts', 'Edges', 'cent', 'axis', 'dvec', 'Degrees', 'Steps'
        ]
        data = list(map(get_socket, socket_names))
        mverts, medges, mcent, maxis, mdvec, mDegrees, mSteps = data

        verts_match_edges = medges and (len(medges) == len(mverts))

        verts_out, faces_out = [], []
        for idx, verts in enumerate(mverts):

            if not verts:
                continue

            # here we find defaults if the node gets incongruent input
            final_values = {
                'verts': verts,
                'edges': [],
                'cent': [0, 0, 0],
                'axis': [0, 0, 1],
                'dvec': [0, 0, 0],
                'angle': radians(self.Degrees),
                'steps': self.Steps
            }
            ''' [], or by idx, if idx present'''
            if medges:
                if verts_match_edges or (idx <= len(medges) - 1):
                    final_values['edges'] = medges[idx]
            ''' by idx, if idx present, else last. if none then default'''
            if mcent:
                idxr = idx if (idx <= len(mcent[0]) - 1) else -1
                final_values['cent'] = mcent[0][idxr]

            if maxis:
                idxr = idx if (idx <= len(maxis[0]) - 1) else -1
                final_values['axis'] = maxis[0][idxr]

            if mdvec:
                idxr = idx if (idx <= len(mdvec[0]) - 1) else -1
                final_values['dvec'] = mdvec[0][idxr]

            if mDegrees:
                if isinstance(mDegrees, list):
                    neatList = mDegrees[0][0]
                    idxr = min(len(neatList) - 1, idx)
                    angle = neatList[idxr]
                    final_values['angle'] = radians(float(angle))

            if mSteps:
                if isinstance(mSteps, list):
                    neatList = mSteps[0][0]
                    idxr = min(len(neatList) - 1, idx)
                    steps = neatList[idxr]
                    final_values['steps'] = max(0, int(steps))

            v, p = get_lathed_geometry(self, **final_values)
            verts_out.append(v)
            faces_out.append(p)

        SvSetSocketAnyType(self, 'Verts', verts_out)
        SvSetSocketAnyType(self, 'Poly', faces_out)
Example #6
0
class BGIS_PREFS(AddonPreferences):

    bl_idname = PKG

    ################
    #Predefinate Spatial Ref. Systems

    def listPredefCRS(self, context):
        return PredefCRS.getEnumItems()

    #store crs preset as json string into addon preferences
    predefCrsJson = StringProperty(default=json.dumps(PREDEF_CRS))

    predefCrs = EnumProperty(
        name="Predefinate CRS",
        description="Choose predefinite Coordinate Reference System",
        items=listPredefCRS)

    ################
    #proj engine

    def getProjEngineItems(self, context):
        items = [('AUTO', 'Auto detect',
                  'Auto select the best library for reprojection tasks')]
        if HAS_GDAL:
            items.append(('GDAL', 'GDAL', 'Force GDAL as reprojection engine'))
        if HAS_PYPROJ:
            items.append(
                ('PYPROJ', 'pyProj', 'Force pyProj as reprojection engine'))
        #if EPSGIO.ping(): #too slow
        #	items.append( ('EPSGIO', 'epsg.io', '') )
        items.append(
            ('EPSGIO', 'epsg.io', 'Force epsg.io as reprojection engine'))
        items.append(('BUILTIN', 'Built in',
                      'Force reprojection through built in Python functions'))
        return items

    def updateProjEngine(self, context):
        prefs = getSettings()
        prefs['proj_engine'] = self.projEngine
        setSettings(prefs)

    projEngine = EnumProperty(name="Projection engine",
                              description="Select projection engine",
                              items=getProjEngineItems,
                              update=updateProjEngine)

    ################
    #img engine

    def getImgEngineItems(self, context):
        items = [('AUTO', 'Auto detect',
                  'Auto select the best imaging library')]
        if HAS_GDAL:
            items.append(
                ('GDAL', 'GDAL', 'Force GDAL as image processing engine'))
        if HAS_IMGIO:
            items.append(('IMGIO', 'ImageIO',
                          'Force ImageIO as image processing  engine'))
        if HAS_PIL:
            items.append(
                ('PIL', 'PIL', 'Force PIL as image processing  engine'))
        return items

    def updateImgEngine(self, context):
        prefs = getSettings()
        prefs['img_engine'] = self.imgEngine
        setSettings(prefs)

    imgEngine = EnumProperty(name="Image processing engine",
                             description="Select image processing engine",
                             items=getImgEngineItems,
                             update=updateImgEngine)

    ################
    #OSM

    osmTagsJson = StringProperty(
        default=json.dumps(OSM_TAGS))  #just a serialized list of tags

    def listOsmTags(self, context):
        prefs = bpy.context.user_preferences.addons[PKG].preferences
        tags = json.loads(prefs.osmTagsJson)
        #put each item in a tuple (key, label, tooltip)
        return [(tag, tag, tag) for tag in tags]

    osmTags = EnumProperty(name="OSM tags",
                           description="List of registered OSM tags",
                           items=listOsmTags)

    ################
    #Basemaps

    cacheFolder = StringProperty(
        name="Cache folder",
        default="",
        description="Define a folder where to store Geopackage SQlite db",
        subtype='DIR_PATH')

    fontColor = FloatVectorProperty(name="Font color",
                                    subtype='COLOR',
                                    min=0,
                                    max=1,
                                    size=4,
                                    default=(0, 0, 0, 1))

    zoomToMouse = BoolProperty(
        name="Zoom to mouse",
        description='Zoom towards the mouse pointer position',
        default=True)

    lockOrigin = BoolProperty(
        name="Lock origin",
        description='Do not move scene origin when panning map',
        default=False)
    lockObj = BoolProperty(
        name="Lock objects",
        description='Retain objects geolocation when moving map origin',
        default=True)

    resamplAlg = EnumProperty(
        name="Resampling method",
        description="Choose GDAL's resampling method used for reprojection",
        items=[('NN', 'Nearest Neighboor', ''), ('BL', 'Bilinear', ''),
               ('CB', 'Cubic', ''), ('CBS', 'Cubic Spline', ''),
               ('LCZ', 'Lanczos', '')])

    ################
    #IO options
    mergeDoubles = BoolProperty(
        name="Merge duplicate vertices",
        description=
        'Merge shared vertices between features when importing vector data',
        default=False)
    adjust3Dview = BoolProperty(
        name="Adjust 3D view",
        description=
        "Update 3d view grid size and clip distances according to the new imported object's size",
        default=True)
    forceTexturedSolid = BoolProperty(
        name="Force textured solid shading",
        description="Update shading mode to display raster's texture",
        default=True)

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

        #SRS
        box = layout.box()
        box.label('Spatial Reference Systems')
        row = box.row().split(percentage=0.5)
        row.prop(self, "predefCrs", text='')
        row.operator("bgis.add_predef_crs", icon='ZOOMIN')
        row.operator("bgis.edit_predef_crs", icon='SCRIPTWIN')
        row.operator("bgis.rmv_predef_crs", icon='ZOOMOUT')
        row.operator("bgis.reset_predef_crs", icon='PLAY_REVERSE')
        box.prop(self, "projEngine")
        box.prop(self, "imgEngine")

        #Basemaps
        box = layout.box()
        box.label('Basemaps')
        box.prop(self, "cacheFolder")
        row = box.row()
        row.prop(self, "zoomToMouse")
        row.prop(self, "lockObj")
        row.prop(self, "lockOrigin")
        row.label('Font color:')
        row.prop(self, "fontColor", text='')
        row = box.row()
        row.prop(self, "resamplAlg")

        #IO
        box = layout.box()
        box.label('Import/Export')
        row = box.row().split(percentage=0.5)
        split = row.split(percentage=0.9, align=True)
        split.prop(self, "osmTags")
        split.operator(
            "wm.url_open", icon='INFO'
        ).url = "http://wiki.openstreetmap.org/wiki/Map_Features"
        row.operator("bgis.add_osm_tag", icon='ZOOMIN')
        row.operator("bgis.edit_osm_tag", icon='SCRIPTWIN')
        row.operator("bgis.rmv_osm_tag", icon='ZOOMOUT')
        row.operator("bgis.reset_osm_tags", icon='PLAY_REVERSE')
        row = box.row()
        row.prop(self, "mergeDoubles")
        row.prop(self, "adjust3Dview")
        row.prop(self, "forceTexturedSolid")
def define_property(class_name, property_name, property_definition,
                    hubs_context):
    property_type = property_definition['type']
    display_name = property_definition.get("label",
                                           camel_to_title(property_name))

    if property_type == 'int':
        return IntProperty(
            name=display_name,
            description=property_definition.get("description") or "",
            subtype=property_definition.get("subType") or "NONE",
        )
    elif property_type == 'float':
        return FloatProperty(
            name=display_name,
            description=property_definition.get("description") or "",
            subtype=property_definition.get("subType") or "NONE",
            unit=property_definition.get("unit") or "NONE",
            min=property_definition.get("min", float('-inf')),
            max=property_definition.get("max", float('inf')),
        )
    elif property_type == 'bool':
        return BoolProperty(name=display_name,
                            description=property_definition.get("description")
                            or "",
                            subtype=property_definition.get("subType")
                            or "NONE")
    elif property_type == 'string':
        return StringProperty(
            name=display_name,
            description=property_definition.get("description") or "",
            subtype=property_definition.get("subType") or "NONE")
    elif property_type == 'ivec2':
        return IntVectorProperty(
            name=display_name,
            description=property_definition.get("description") or "",
            subtype=property_definition.get("subType") or "NONE",
            size=2)
    elif property_type == 'ivec3':
        return IntVectorProperty(
            name=display_name,
            description=property_definition.get("description") or "",
            subtype=property_definition.get("subType") or "NONE",
            size=3)
    elif property_type == 'ivec4':
        return IntVectorProperty(
            name=display_name,
            description=property_definition.get("description") or "",
            subtype=property_definition.get("subType") or "NONE",
            size=4)
    elif property_type == 'vec2':
        return FloatVectorProperty(
            name=display_name,
            description=property_definition.get("description") or "",
            subtype=property_definition.get("subType") or "NONE",
            unit=property_definition.get("unit") or "NONE",
            size=2)
    elif property_type == 'vec3':
        return FloatVectorProperty(
            name=display_name,
            description=property_definition.get("description") or "",
            subtype=property_definition.get("subType") or "NONE",
            unit=property_definition.get("unit") or "NONE",
            size=3)
    elif property_type == 'vec4':
        return FloatVectorProperty(
            name=display_name,
            description=property_definition.get("description") or "",
            subtype=property_definition.get("subType") or "NONE",
            unit=property_definition.get("unit") or "NONE",
            size=4)
    elif property_type == 'enum':
        return EnumProperty(
            name=display_name,
            description=property_definition.get("description") or "",
            items=[tuple(i) for i in property_definition.get("items")])
    elif property_type == 'color':
        return FloatVectorProperty(
            name=display_name,
            description=property_definition.get("description") or "",
            subtype='COLOR',
            default=(1.0, 1.0, 1.0, 1.0),
            size=4,
            min=0,
            max=1)
    elif property_type == 'material':
        return PointerProperty(
            name=display_name,
            description=property_definition.get("description") or "",
            type=Material)
    elif property_type == 'nodeRef':
        required_components = property_definition.get("hasComponents") or []

        def filter_on_component(self, o):
            return components.has_components(o, required_components)

        return PointerProperty(
            name=display_name,
            description=property_definition.get("description") or "",
            type=Object,
            poll=filter_on_component)
    elif property_type == 'image' or property_type == 'texture':
        return PointerProperty(
            name=display_name,
            description=property_definition.get("description") or "",
            type=Image)
    elif property_type == 'collections':
        # collections come from the object's users_collection property
        # and don't have an associated Property
        return None
    elif property_type == 'array':
        if 'arrayType' not in property_definition:
            raise TypeError(
                'Hubs array property  \'%s\' does not specify an arrayType on %s'
                % (property_name, class_name))

        array_type = property_definition['arrayType']

        property_class = define_type(array_type, hubs_context)

        if not property_class:
            raise TypeError('Unsupported Hubs array type \'%s\' for %s on %s' %
                            (array_type, property_name, class_name))

        return CollectionProperty(
            name=display_name,
            description=property_definition.get("description") or "",
            type=property_class)
    else:
        property_class = define_type(property_type, hubs_context)

        if not property_class:
            raise TypeError(
                'Unsupported Hubs property type \'%s\' for %s on %s' %
                (property_type, property_name, class_name))

        return PointerProperty(
            name=display_name,
            description=property_definition.get("description") or "",
            type=property_class)
Example #8
0
    bl_idname = "object.replicate_object"
    bl_label = "選択オブジェクトの複製"
    bl_description = "選択中のオブジェクトを複製します"
    bl_options = {'REGISTER', 'UNDO'}

//! [enum_prop]
    location = EnumProperty(
        name="配置位置",
        description="複製したオブジェクトの配置位置",
        items=location_list_fn
    )
//! [enum_prop]
    scale = FloatVectorProperty(
        name="拡大率",
        description="複製したオブジェクトの拡大率を設定します",
        default=(1.0, 1.0, 1.0),
        subtype='XYZ',
        unit='LENGTH'
    )
    rotation = FloatVectorProperty(
        name="回転角度",
        description="複製したオブジェクトの回転角度を設定します",
        default=(0.0, 0.0, 0.0),
        subtype='AXISANGLE',
        unit='ROTATION'
    )
    offset = FloatVectorProperty(
        name="オフセット",
        description="複製したオブジェクトの配置位置からのオフセットを設定します",
        default=(0.0, 0.0, 0.0),
        subtype='TRANSLATION',
Example #9
0
class SvViewerDrawMk4(bpy.types.Node, SverchCustomTreeNode):
    """
    Triggers: vd geometry preview
    Tooltip: drawing preview on 3d scene, with experimental features

    """
    bl_idname = 'SvViewerDrawMk4'
    bl_label = 'Viewer Draw'
    bl_icon = 'GREASEPENCIL'
    sv_icon = 'SV_DRAW_VIEWER'

    node_dict = {}

    selected_draw_mode: EnumProperty(
        items=enum_item_5(
            ["flat", "facet", "smooth", "fragment"],
            ['SNAP_VOLUME', 'ALIASED', 'ANTIALIASED', 'SCRIPTPLUGINS']),
        description="pick how the node will draw faces",
        default="flat",
        update=updateNode)

    activate: BoolProperty(name='Show',
                           description='Activate drawing',
                           default=True,
                           update=updateNode)
    draw_gl_polygonoffset: BoolProperty(name="Draw gl polygon offset",
                                        default=True,
                                        update=updateNode)
    draw_gl_wireframe: BoolProperty(name="Draw gl wireframe",
                                    default=False,
                                    update=updateNode)
    vector_light: FloatVectorProperty(name='vector light',
                                      subtype='DIRECTION',
                                      min=0,
                                      max=1,
                                      size=3,
                                      default=(0.2, 0.6, 0.4),
                                      update=updateNode)
    extended_matrix: BoolProperty(
        default=False,
        description='Allows mesh.transform(matrix) operation, quite fast!')

    handle_concave_quads: BoolProperty(
        name='Handle Concave Quads',
        default=False,
        update=updateNode,
        description=
        'tessellate quads using geometry.tessellate_polygon, expect some speed impact'
    )

    point_size: IntProperty(min=1,
                            default=4,
                            name='Verts Size',
                            description='Point Size',
                            update=updateNode)
    line_width: IntProperty(min=1,
                            default=1,
                            name='Edge Width',
                            description='Edge Width',
                            update=updateNode)

    curve_samples: IntProperty(min=2,
                               default=25,
                               name='Samples',
                               description='Curve Resolution',
                               update=updateNode)
    vector_color: FloatVectorProperty(update=updateNode,
                                      name='Vertices Color',
                                      default=(.9, .9, .95, 1.0),
                                      size=4,
                                      min=0.0,
                                      max=1.0,
                                      subtype='COLOR')
    display_verts: BoolProperty(update=updateNode,
                                name='Display Vertices',
                                default=True)
    vector_random_colors: BoolProperty(update=updateNode,
                                       name='Random Vertices Color',
                                       default=False)
    random_seed: IntProperty(min=1,
                             default=1,
                             name='Random Seed',
                             description='Seed of random colors',
                             update=updateNode)
    color_per_point: BoolProperty(
        update=updateNode,
        name='Color per point',
        default=False,
        description='Toggle between color per point or per object')
    color_per_edge: BoolProperty(
        update=updateNode,
        name='Color per edge',
        default=False,
        description='Toggle between color per edge or per object')
    color_per_polygon: BoolProperty(
        update=updateNode,
        name='Color per polygon',
        default=False,
        description='Toggle between color per polygon or per object')
    polygon_use_vertex_color: BoolProperty(
        update=updateNode,
        name='Polys Vertex Color',
        default=False,
        description='Colorize polygons using vertices color')
    edges_use_vertex_color: BoolProperty(
        update=updateNode,
        name='Edges Vertex Color',
        default=False,
        description='Colorize edges using vertices color')

    edge_color: FloatVectorProperty(update=updateNode,
                                    name='Edges Color',
                                    default=(.9, .9, .35, 1.0),
                                    size=4,
                                    min=0.0,
                                    max=1.0,
                                    subtype='COLOR')
    display_edges: BoolProperty(update=updateNode,
                                name='Display Edges',
                                default=True)

    polygon_color: FloatVectorProperty(update=updateNode,
                                       name='Ploygons Color',
                                       default=(0.14, 0.54, 0.81, 1.0),
                                       size=4,
                                       min=0.0,
                                       max=1.0,
                                       subtype='COLOR')
    display_faces: BoolProperty(update=updateNode,
                                name='Display Polygons',
                                default=True)
    all_triangles: BoolProperty(
        update=updateNode,
        name='All Triangles',
        default=False,
        description=
        'Enable if all the incoming faces are Tris (makes node faster)')

    matrix_draw_scale: FloatProperty(default=1,
                                     min=0.0001,
                                     name="Drawing matrix scale",
                                     update=updateNode)

    # dashed line props
    use_dashed: BoolProperty(name='Dashes Edges', update=updateNode)
    u_dash_size: FloatProperty(default=0.12,
                               min=0.0001,
                               name="dash size",
                               update=updateNode)
    u_gap_size: FloatProperty(default=0.19,
                              min=0.0001,
                              name="gap size",
                              update=updateNode)
    u_resolution: FloatVectorProperty(default=(25.0, 18.0),
                                      size=2,
                                      min=0.01,
                                      name="resolution",
                                      update=updateNode)

    # custom shader props
    def populate_node_with_custom_shader_from_text(self):
        if self.custom_shader_location in bpy.data.texts:
            try:
                vertex_shader, fragment_shader, draw_fragment = get_shader_data(
                    named_shader=self.custom_shader_location)

                self.custom_vertex_shader = vertex_shader
                self.custom_fragment_shader = fragment_shader
                self.node_dict[hash(self)] = {'draw_fragment': draw_fragment}

            except Exception as err:
                print(err)

                # reset custom shader
                self.custom_vertex_shader = ''
                self.custom_fragment_shader = ''
                self.node_dict[hash(self)] = {}

    def wrapped_update(self, context=None):
        self.populate_node_with_custom_shader_from_text()
        if context:
            self.process_node(context)

    custom_vertex_shader: StringProperty(default=default_vertex_shader,
                                         name='vertex shader')
    custom_fragment_shader: StringProperty(default=default_fragment_shader,
                                           name='fragment shader')
    custom_shader_location: StringProperty(update=wrapped_update,
                                           name='custom shader location')

    # attributes socket props
    def configureAttrSocket(self, context):
        self.inputs['attrs'].hide_safe = not self.node_ui_show_attrs_socket

    node_ui_show_attrs_socket: BoolProperty(default=False,
                                            name='Show attributes socket',
                                            update=configureAttrSocket)

    def draw_buttons(self, context, layout):

        r0 = layout.row()
        r0.prop(self,
                "activate",
                text="",
                icon="HIDE_" + ("OFF" if self.activate else "ON"))
        r0.separator()
        r0.prop(self, "selected_draw_mode", expand=True, text='')
        if self.selected_draw_mode == 'fragment':
            layout.prop(self, "custom_shader_location", icon='TEXT', text='')

        row = layout.row(align=True)
        row.prop(self, "point_size")
        row.prop(self, "line_width")
        row = layout.row(align=True)
        row.scale_y = 4.0 if self.prefs_over_sized_buttons else 1
        self.wrapper_tracked_ui_draw_op(row,
                                        "node.sverchok_mesh_baker_mk3",
                                        icon='OUTLINER_OB_MESH',
                                        text="B A K E")
        row.separator()
        self.wrapper_tracked_ui_draw_op(row,
                                        "node.view3d_align_from",
                                        icon='CURSOR',
                                        text='')

    def draw_buttons_ext(self, context, layout):
        self.draw_buttons(context, layout)
        layout.label(text='Light Direction')
        layout.prop(self, 'vector_light', text='')
        self.draw_additional_props(context, layout)
        if self.use_dashed:
            layout.prop(self, "u_dash_size")
            layout.prop(self, "u_gap_size")
            layout.prop(self, "u_resolution")

    def draw_additional_props(self, context, layout):
        layout.prop(self, 'draw_gl_polygonoffset')
        layout.prop(self, 'draw_gl_wireframe')
        layout.prop(self, 'handle_concave_quads')
        layout.prop(self, 'node_ui_show_attrs_socket')
        layout.prop(self, 'matrix_draw_scale')
        layout.prop(self, "use_dashed")
        layout.prop(self, "all_triangles")

    def rclick_menu(self, context, layout):
        self.draw_additional_props(context, layout)

    def bake(self):
        with self.sv_throttle_tree_update():
            bpy.ops.node.sverchok_mesh_baker_mk3(idname=self.name,
                                                 idtree=self.id_data.name)

    def sv_init(self, context):
        new_input = self.inputs.new
        new_input('SvVerticesSocket', "Vertices")
        new_input('SvStringsSocket', "Edges")
        new_input('SvStringsSocket', "Polygons")
        new_input('SvMatrixSocket', 'Matrix')

        v_col = new_input('SvColorSocket', "Vector Color")
        v_col.prop_name = 'vector_color'
        v_col.custom_draw = 'draw_color_socket'
        e_col = new_input('SvColorSocket', "Edge Color")
        e_col.prop_name = 'edge_color'
        e_col.custom_draw = 'draw_color_socket'
        p_col = new_input('SvColorSocket', "Polygon Color")
        p_col.prop_name = 'polygon_color'
        p_col.custom_draw = 'draw_color_socket'

        attr_socket = new_input('SvStringsSocket', 'attrs')
        attr_socket.hide = True
        attr_socket.quick_link_to_node = "SvVDAttrsNodeMk2"

    def migrate_from(self, old_node):
        self.vector_color = old_node.vert_color
        self.polygon_color = old_node.face_color

    def draw_color_socket(self, socket, context, layout):
        socket_info = socket_dict[socket.prop_name]
        layout.prop(self, socket_info[0], text="", icon=socket_info[1])
        layout.prop(self, socket_info[2], text="", icon='COLOR')
        display_color = not socket.is_linked
        draw_name = True
        if len(socket_info) < 5:
            layout.prop(self, socket_info[3], text="", icon='VPAINT_HLT')

        else:
            layout.prop(self, socket_info[3], text="", icon='MOD_NOISE')
            if socket_info[3] in self and self[socket_info[3]]:
                layout.prop(self, socket_info[4], text="Seed")
                draw_name = False

        if socket_info[3] in self:
            display_color = display_color and not self[socket_info[3]]

        if display_color:
            layout.prop(self, socket.prop_name, text="")
        else:
            if draw_name:
                reduced_name = socket.name[:2] + ". Col"
                layout.label(text=reduced_name + '. ' +
                             SvGetSocketInfo(socket))

    def create_config(self):
        config = lambda: None
        inputs = self.inputs
        config.draw_verts = self.display_verts
        config.draw_edges = self.display_edges
        config.draw_polys = self.display_faces and inputs['Polygons'].is_linked
        config.point_size = self.point_size
        config.line_width = self.line_width
        config.random_colors = self.vector_random_colors
        config.color_per_point = self.color_per_point and (
            inputs['Vector Color'].is_linked or self.vector_random_colors)
        config.color_per_edge = self.color_per_edge and (
            inputs['Edge Color'].is_linked or self.edges_use_vertex_color)
        config.color_per_polygon = self.color_per_polygon and (
            inputs['Polygon Color'].is_linked or self.polygon_use_vertex_color)
        config.polygon_use_vertex_color = self.polygon_use_vertex_color
        config.edges_use_vertex_color = self.edges_use_vertex_color

        config.vector_light = Vector(self.vector_light)
        config.shade_mode = self.selected_draw_mode
        config.draw_gl_polygonoffset = self.draw_gl_polygonoffset
        config.draw_gl_wireframe = self.draw_gl_wireframe
        config.handle_concave_quads = self.handle_concave_quads
        config.all_triangles = self.all_triangles

        config.draw_dashed = self.use_dashed
        config.u_dash_size = self.u_dash_size
        config.u_gap_size = self.u_gap_size
        config.u_resolution = self.u_resolution[:]

        config.node = self

        return config

    def handle_attr_socket(self):
        """
        this socket expects input dictionary wrapped. once.

            [  {attr: attr_vale, attr2: attr2_value } ]

        """

        if self.node_ui_show_attrs_socket and not self.inputs[
                'attrs'].hide and self.inputs['attrs'].is_linked:
            socket_acquired_attrs = self.inputs['attrs'].sv_get(
                default=[{
                    'activate': False
                }])

            if socket_acquired_attrs:
                with self.id_data.throttle_update():  # avoiding recursion
                    try:
                        for k, new_value in socket_acquired_attrs[0].items():
                            print(f"setattr(node, {k}, {new_value})")
                            setattr(self, k, new_value
                                    )  # it will trigger process method again
                    except Exception as err:
                        print('error inside socket_acquired_attrs: ', err)

    def get_data(self):
        verts_socket, edges_socket, faces_socket, matrix_socket = self.inputs[:
                                                                              4]
        edge_indices = [[]]
        face_indices = [[]]

        propv = verts_socket.sv_get(deepcopy=False, default=[[]])
        coords = propv

        if edges_socket.is_linked:
            prope = edges_socket.sv_get(deepcopy=False, default=[[]])
            edge_indices = prope

        if faces_socket.is_linked:
            propf = faces_socket.sv_get(deepcopy=False, default=[[]])
            face_indices = propf

        if matrix_socket.is_linked:
            m = matrix_socket.sv_get(deepcopy=False, default=[Matrix()])
            verts, matrix = match_long_repeat([propv, m])
            coords = [
                multiply_vectors_deep(mx, v) for mx, v in zip(matrix, verts)
            ]
        else:
            matrix = [Matrix()]
            verts = coords
        return match_long_repeat(
            [coords, edge_indices, face_indices, verts, matrix])

    def process(self):
        if bpy.app.background:
            return
        self.handle_attr_socket()
        if not (self.id_data.sv_show and self.activate):
            callback_disable(node_id(self))
            return
        n_id = node_id(self)
        callback_disable(n_id)
        inputs = self.inputs
        # end early
        if not self.activate:
            return

        if not any([inputs['Vertices'].is_linked, inputs['Matrix'].is_linked]):
            return

        if inputs['Vertices'].is_linked:
            vecs = inputs['Vertices'].sv_get(deepcopy=False, default=[[]])
            total_verts = sum(map(len, vecs))
            if not total_verts:
                raise LookupError("Empty vertices list")
            edges = inputs['Edges'].sv_get(deepcopy=False, default=[[]])
            polygons = inputs['Polygons'].sv_get(deepcopy=False, default=[[]])
            matrix = inputs['Matrix'].sv_get(deepcopy=False, default=[[]])
            vector_color = inputs['Vector Color'].sv_get(
                deepcopy=False, default=[[self.vector_color]])
            edge_color = inputs['Edge Color'].sv_get(
                deepcopy=False, default=[[self.edge_color]])
            poly_color = inputs['Polygon Color'].sv_get(
                deepcopy=False, default=[[self.polygon_color]])
            seed_set(self.random_seed)
            config = self.create_config()

            config.vector_color = vector_color
            config.edge_color = edge_color
            config.poly_color = poly_color
            config.edges = edges

            if self.use_dashed:
                add_dashed_shader(config)

            config.polygons = polygons
            config.matrix = matrix
            if not inputs['Edges'].is_linked and self.display_edges:
                config.edges = polygons_to_edges_np(polygons,
                                                    unique_edges=True)

            geom = generate_mesh_geom(config, vecs)

            draw_data = {
                'tree_name': self.id_data.name[:],
                'custom_function': view_3d_geom,
                'args': (geom, config)
            }
            callback_enable(n_id, draw_data)

        elif inputs['Matrix'].is_linked:
            matrices = inputs['Matrix'].sv_get(deepcopy=False,
                                               default=[Matrix()])

            gl_instructions = {
                'tree_name': self.id_data.name[:],
                'custom_function': draw_matrix,
                'args': (matrices, self.matrix_draw_scale)
            }
            callback_enable(n_id, gl_instructions)

    def sv_free(self):
        callback_disable(node_id(self))

    def show_viewport(self, is_show: bool):
        """It should be called by node tree to show/hide objects"""
        if not self.activate:
            # just ignore request
            pass
        else:
            if is_show:
                self.process()
            else:
                callback_disable(node_id(self))
Example #10
0
class MUV_PackUV(bpy.types.Operator):
    """
    Operation class: Pack UV with same UV islands are integrated
    Island matching algorithm
     - Same center of UV island
     - Same size of UV island
     - Same number of UV
    """

    bl_idname = "uv.muv_packuv"
    bl_label = "Pack UV"
    bl_description = "Pack UV (Same UV Islands are integrated)"
    bl_options = {'REGISTER', 'UNDO'}

    rotate = BoolProperty(
        name="Rotate",
        description="Rotate option used by default pack UV function",
        default=False)
    margin = FloatProperty(
        name="Margin",
        description="Margin used by default pack UV function",
        min=0,
        max=1,
        default=0.001)
    allowable_center_deviation = FloatVectorProperty(
        name="Allowable Center Deviation",
        description="Allowable center deviation to judge same UV island",
        min=0.000001,
        max=0.1,
        default=(0.001, 0.001),
        size=2)
    allowable_size_deviation = FloatVectorProperty(
        name="Allowable Size Deviation",
        description="Allowable sizse deviation to judge same UV island",
        min=0.000001,
        max=0.1,
        default=(0.001, 0.001),
        size=2)

    def __init__(self):
        self.__face_to_verts = defaultdict(set)
        self.__vert_to_faces = defaultdict(set)

    def execute(self, _):
        obj = bpy.context.active_object
        bm = bmesh.from_edit_mesh(obj.data)
        if muv_common.check_version(2, 73, 0) >= 0:
            bm.faces.ensure_lookup_table()
        if not bm.loops.layers.uv:
            self.report({'WARNING'}, "Object must have more than one UV map")
            return {'CANCELLED'}
        uv_layer = bm.loops.layers.uv.verify()

        selected_faces = [f for f in bm.faces if f.select]

        # create mesh database
        for f in selected_faces:
            for l in f.loops:
                id_ = l[uv_layer].uv.to_tuple(5), l.vert.index
                self.__face_to_verts[f.index].add(id_)
                self.__vert_to_faces[id_].add(f.index)

        # Group island
        uv_island_lists = self.__get_island(bm)
        island_info = self.__get_island_info(uv_layer, uv_island_lists)
        num_group = self.__group_island(island_info)

        loop_lists = [l for f in bm.faces for l in f.loops]
        bpy.ops.mesh.select_all(action='DESELECT')

        # pack UV
        for gidx in range(num_group):
            group = list(
                filter(lambda i, idx=gidx: i['group'] == idx, island_info))
            for f in group[0]['faces']:
                f['face'].select = True
        bmesh.update_edit_mesh(obj.data)
        bpy.ops.uv.select_all(action='SELECT')
        bpy.ops.uv.pack_islands(rotate=self.rotate, margin=self.margin)

        # copy/paste UV among same islands
        for gidx in range(num_group):
            group = list(
                filter(lambda i, idx=gidx: i['group'] == idx, island_info))
            if len(group) <= 1:
                continue
            for g in group[1:]:
                for (src_face, dest_face) in zip(group[0]['sorted'],
                                                 g['sorted']):
                    for (src_loop, dest_loop) in zip(src_face['face'].loops,
                                                     dest_face['face'].loops):
                        loop_lists[dest_loop.index][uv_layer].uv = loop_lists[
                            src_loop.index][uv_layer].uv

        # restore face/UV selection
        bpy.ops.uv.select_all(action='DESELECT')
        bpy.ops.mesh.select_all(action='DESELECT')
        for f in selected_faces:
            f.select = True
        bpy.ops.uv.select_all(action='SELECT')

        bmesh.update_edit_mesh(obj.data)

        return {'FINISHED'}

    def __sort_island_faces(self, kd, uvs, isl1, isl2):
        """
        Sort faces in island
        """

        sorted_faces = []
        for f in isl1['sorted']:
            _, idx, _ = kd.find(Vector((f['ave_uv'].x, f['ave_uv'].y, 0.0)))
            sorted_faces.append(isl2['faces'][uvs[idx]['face_idx']])
        return sorted_faces

    def __group_island(self, island_info):
        """
        Group island
        """

        num_group = 0
        while True:
            # search islands which is not parsed yet
            isl_1 = None
            for isl_1 in island_info:
                if isl_1['group'] == -1:
                    break
            else:
                break  # all faces are parsed
            if isl_1 is None:
                break
            isl_1['group'] = num_group
            isl_1['sorted'] = isl_1['faces']

            # search same island
            for isl_2 in island_info:
                if isl_2['group'] == -1:
                    dcx = isl_2['center'].x - isl_1['center'].x
                    dcy = isl_2['center'].y - isl_1['center'].y
                    dsx = isl_2['size'].x - isl_1['size'].x
                    dsy = isl_2['size'].y - isl_1['size'].y
                    center_x_matched = (fabs(dcx) <
                                        self.allowable_center_deviation[0])
                    center_y_matched = (fabs(dcy) <
                                        self.allowable_center_deviation[1])
                    size_x_matched = (fabs(dsx) <
                                      self.allowable_size_deviation[0])
                    size_y_matched = (fabs(dsy) <
                                      self.allowable_size_deviation[1])
                    center_matched = center_x_matched and center_y_matched
                    size_matched = size_x_matched and size_y_matched
                    num_uv_matched = (isl_2['num_uv'] == isl_1['num_uv'])
                    # are islands have same?
                    if center_matched and size_matched and num_uv_matched:
                        isl_2['group'] = num_group
                        kd = mathutils.kdtree.KDTree(len(isl_2['faces']))
                        uvs = [{
                            'uv':
                            Vector((f['ave_uv'].x, f['ave_uv'].y, 0.0)),
                            'face_idx':
                            fidx
                        } for fidx, f in enumerate(isl_2['faces'])]
                        for i, uv in enumerate(uvs):
                            kd.insert(uv['uv'], i)
                        kd.balance()
                        # sort faces for copy/paste UV
                        isl_2['sorted'] = self.__sort_island_faces(
                            kd, uvs, isl_1, isl_2)
            num_group = num_group + 1

        return num_group

    def __get_island_info(self, uv_layer, islands):
        """
        get information about each island
        """

        island_info = []
        for isl in islands:
            info = {}
            max_uv = Vector((-10000000.0, -10000000.0))
            min_uv = Vector((10000000.0, 10000000.0))
            ave_uv = Vector((0.0, 0.0))
            num_uv = 0
            for face in isl:
                n = 0
                a = Vector((0.0, 0.0))
                for l in face['face'].loops:
                    uv = l[uv_layer].uv
                    if uv.x > max_uv.x:
                        max_uv.x = uv.x
                    if uv.y > max_uv.y:
                        max_uv.y = uv.y
                    if uv.x < min_uv.x:
                        min_uv.x = uv.x
                    if uv.y < min_uv.y:
                        min_uv.y = uv.y
                    a = a + uv
                    n = n + 1
                ave_uv = ave_uv + a
                num_uv = num_uv + n
                a = a / n
                face['ave_uv'] = a
            ave_uv = ave_uv / num_uv

            info['center'] = ave_uv
            info['size'] = max_uv - min_uv
            info['num_uv'] = num_uv
            info['group'] = -1
            info['faces'] = isl

            island_info.append(info)

        return island_info

    def __parse_island(self, bm, face_idx, faces_left, island):
        """
        Parse island
        """

        if face_idx in faces_left:
            faces_left.remove(face_idx)
            island.append({'face': bm.faces[face_idx]})
            for v in self.__face_to_verts[face_idx]:
                connected_faces = self.__vert_to_faces[v]
                if connected_faces:
                    for cf in connected_faces:
                        self.__parse_island(bm, cf, faces_left, island)

    def __get_island(self, bm):
        """
        Get island list
        """

        uv_island_lists = []
        faces_left = set(self.__face_to_verts.keys())
        while len(faces_left) > 0:
            current_island = []
            face_idx = list(faces_left)[0]
            self.__parse_island(bm, face_idx, faces_left, current_island)
            uv_island_lists.append(current_island)

        return uv_island_lists
Example #11
0
class PipelinePassDescription(bpy.types.PropertyGroup):
    name = bpy.props.StringProperty(name="Name",
                                    description="PipelinePassDescription Name")

    uuid = bpy.props.StringProperty(name="UUID")

    pass_type = bpy.props.EnumProperty(
        name="PassType",
        items=enum_pipeline_passes,
        description="PipelinePassDescription type")
    show_expanded = bpy.props.BoolProperty(
        name="Set pipelinepass expanded in the user interface", default=True)
    light_visibility_rasterization_mode = EnumProperty(
        name="RasterizationMode",
        description="rasterization mode",
        items=enum_light_visibility_rasterization_mode,
        default='AUTO',
    )
    light_visibility_tile_power = IntProperty(
        name="TilePower",
        description="tile power",
        min=0,
        max=7,
        default=2,
    )
    resolve_background_mode = EnumProperty(name="Background Mode",
                                           description="background mode",
                                           items=enum_resolve_background_mode,
                                           default='COLOR')
    resolve_background_color = FloatVectorProperty(
        name="Background Color",
        description="background color",
        min=0,
        max=1,
        default=(0.2, 0.2, 0.2),
        subtype='COLOR')
    resolve_background_texture = StringProperty(
        name="Background Texture",
        description="background texture",
        default="gua_default_texture")
    resolve_alternative_background_texture = StringProperty(
        name="Alternative Background Texture",
        description="alternative background texture",
        default="gua_default_texture")

    resolve_vignette_softness = FloatProperty(name="Vignette Softness",
                                              description="vignette softness",
                                              min=0.0,
                                              default=1.3)
    resolve_vignette_coverage = FloatProperty(name="Vignette Coverage",
                                              description="vignette coverage",
                                              min=0.0,
                                              default=1.3)
    resolve_vignette_color = FloatVectorProperty(
        name="Vignette Color",
        description="vignette color",
        min=0,
        max=1,
        #default=(0.05, 0.05, 0.05),
        #subtype='COLOR'
        size=4)

    resolve_environment_lighting_mode = EnumProperty(
        name="Environment Lighting Mode",
        description="environment lighting mode",
        items=enum_resolve_environment_lighting_mode,
        default='AMBIENT_COLOR')
    resolve_environment_lighting_color = FloatVectorProperty(
        name="Environment Lighting Color",
        description="environment lighting color",
        min=0,
        max=1,
        default=(0.05, 0.05, 0.05),
        subtype='COLOR')
    #resolve_environment_lighting_spheremap = StringProperty(
    #    name="Environment Lighting Spheremap",
    #    description="environment lighting spheremap",
    #    default="gua_default_texture"
    #    )
    #resolve_environment_lighting_cubemap = StringProperty(
    #    name="Environment Lighting Cubemap",
    #    description="environment lighting cubemap",
    #    default="gua_default_texture"
    #    )
    resolve_environment_lighting_texture = StringProperty(
        name="Environment Lighting Texture",
        description="environment lighting texture",
        default="gua_default_texture")
    resolve_alternative_environment_lighting_texture = StringProperty(
        name="Alternative Environment Lighting Texture",
        description="alternative environment lighting texture",
        default="gua_default_texture")
    resolve_horizon_fade = FloatProperty(name="Horizon Fade",
                                         description="horizon fade",
                                         min=0.0,
                                         default=1.3)
    resolve_ssao_enable = BoolProperty(name="SSAO enable",
                                       description="enable ssao",
                                       default=False)
    resolve_ssao_radius = FloatProperty(name="SSAO Radius",
                                        description="ssao radius",
                                        min=0.0,
                                        default=1.0)
    resolve_ssao_intensity = FloatProperty(name="SSAO Intensity",
                                           description="ssao intensity",
                                           min=0.0,
                                           default=1.0)
    resolve_ssao_falloff = FloatProperty(name="SSAO Falloff",
                                         description="ssao falloff",
                                         min=0.0,
                                         default=0.1)
    resolve_noise_tex = StringProperty(name="Noise Texture",
                                       description="noise texture",
                                       default="gua_default_texture")
    resolve_screen_space_shadows_enable = BoolProperty(
        name="Enable Screenspace Shadows",
        description="enable screenspace shadows",
        default=False)
    resolve_screen_space_shadows_radius = FloatProperty(
        name="Screen Space Shadows Radius",
        description="screen space shadows radius",
        min=0.0,
        default=1.0)
    resolve_screen_space_shadows_max_radius_px = FloatProperty(
        name="Screen Space Shadows Max Radius in Pixels",
        description="maximum radius in pixels",
        min=0.0,
        default=200.0)
    resolve_screen_space_shadows_intensity = FloatProperty(
        name="Screen Space Shadows Intensity",
        description="screen space shadows intensity",
        min=0.0,
        default=0.8)
    resolve_enable_fog = BoolProperty(name="Enable Fog",
                                      description="enable fog",
                                      default=False)
    resolve_fog_start = FloatProperty(name="Fog Start",
                                      description="fog start",
                                      min=0.0,
                                      default=10.0)
    resolve_fog_end = FloatProperty(name="Fog End",
                                    description="fog end",
                                    min=0.0,
                                    default=1000.0)
    resolve_tone_mapping_exposure = FloatProperty(name="Exposure",
                                                  description="exposure",
                                                  min=0.0,
                                                  default=1.0)
    resolve_tone_mapping_mode = EnumProperty(
        name="Tone Mapping Operator",
        description="used tone mapping operator",
        items=enum_resolve_tonemapping_mode,
        default='UNCHARTED')
    resolve_enable_debug_tiles = BoolProperty(name="Enable Debug Tiles",
                                              description="show debug tiles",
                                              default=False)
    skymap_output_texture_name = StringProperty(
        name="Output Texture Name",
        description="output texture name",
        default="day_skymap")
    #skymap_light_color # LightColor
    skymap_light_direction = FloatVectorProperty(
        name="Light Direction",
        description="light direction",
        #min=-1,
        #max=1,
        default=(0.00, 1.00, 0.00),
        subtype='DIRECTION')
    # LightBrightness
    skymap_ground_color = FloatVectorProperty(name="Ground Color",
                                              description="ground color",
                                              min=0,
                                              max=1,
                                              default=(0.05, 0.05, 0.05),
                                              subtype='COLOR')

    # RayleighFactor
    # MieFactor

    def to_dict(self):
        new_dict = {
            'type': self.pass_type,
            'name': self.name,
        }
        if self.pass_type == "RESOLVE_PASS":
            new_dict['background_mode'] = self.resolve_background_mode
            new_dict['background_color'] = [
                self.resolve_background_color.r,
                self.resolve_background_color.g,
                self.resolve_background_color.b
            ]
            new_dict['background_texture'] = self.resolve_background_texture
            new_dict['vignette_softness'] = self.resolve_vignette_softness
            new_dict['vignette_coverage'] = self.resolve_vignette_coverage
            new_dict['vignette_color'] = [
                self.resolve_vignette_color[0], self.resolve_vignette_color[1],
                self.resolve_vignette_color[2], self.resolve_vignette_color[3]
            ]

            new_dict['environment_lighting_mode'] = (
                self.resolve_environment_lighting_mode)
            new_dict['environment_lighting_color'] = [
                self.resolve_environment_lighting_color.r,
                self.resolve_environment_lighting_color.g,
                self.resolve_environment_lighting_color.b
            ]
            #new_dict['environment_lighting_cubemap'] = (
            #    self.resolve_environment_lighting_cubemap)
            #new_dict['environment_lighting_spheremap'] = (
            #    self.resolve_environment_lighting_spheremap)
            new_dict['environment_lighting_texture'] = (
                self.resolve_environment_lighting_texture)

            new_dict['horizon_fade'] = self.resolve_horizon_fade

            new_dict['ssao_enable'] = self.resolve_ssao_enable
            new_dict['ssao_radius'] = self.resolve_ssao_radius
            new_dict['ssao_intensity'] = self.resolve_ssao_intensity
            new_dict['ssao_falloff'] = self.resolve_ssao_falloff

            new_dict['noise_texture'] = self.resolve_noise_tex

            new_dict['screenspace_shadows_enable'] = (
                self.resolve_screen_space_shadows_enable)
            new_dict['screenspace_shadows_radius'] = (
                self.resolve_screen_space_shadows_radius)
            new_dict['screenspace_shadows_max_radius_px'] = (
                self.resolve_screen_space_shadows_max_radius_px)
            new_dict['screenspace_shadows_intensity'] = (
                self.resolve_screen_space_shadows_intensity)

            new_dict['fog_enable'] = self.resolve_enable_fog
            new_dict['fog_start'] = self.resolve_fog_start
            new_dict['fog_end'] = self.resolve_fog_end

            new_dict['tone_mapping_exposure'] = (
                self.resolve_tone_mapping_exposure)
            new_dict['tone_mapping_mode'] = self.resolve_tone_mapping_mode

            new_dict['debug_tiles_enable'] = self.resolve_enable_debug_tiles

        if self.pass_type == "LIGHT_VISIBILITY_PASS":
            new_dict['rasterization_mode'] = (
                self.light_visibility_rasterization_mode)
            new_dict['tile_power'] = self.light_visibility_tile_power

        if self.pass_type == "SKY_MAP_PASS":
            new_dict['output_texture_name'] = self.skymap_output_texture_name
            new_dict['light_direction'] = [
                self.skymap_light_direction[0],
                self.skymap_light_direction[1],
                self.skymap_light_direction[2],
            ]
            new_dict['ground_color'] = [
                self.skymap_ground_color[0],
                self.skymap_ground_color[1],
                self.skymap_ground_color[2],
            ]

        return new_dict
Example #12
0
class LowpolyTer(Operator):
    bl_idname = "add.add_lowpoly_terrain_object"
    bl_label = "Generate Low Poly Terrain Object"
    bl_options = {'REGISTER', 'UNDO', 'PRESET'}

    # --------------------------------------------------
    # Basic terrain properties

    terrain_scale: FloatVectorProperty(
        name="Scale",
        description="Scale terrain",
        size=3,
        min=0.0,
        max=10.0,
        default=(7.0, 7.0, 2.0),
    )

    sub_level: IntProperty(
        name="Subdivision count",
        description="A number of subdivisions applied on the terrain",
        min=1,
        max=5,
        default=5,
    )

    # --------------------------------------------------
    # Terrain deformation

    prop_smooth_up: IntProperty(
        name="Count",
        min=0,
        max=20,
        default=10,
        description=
        "Number of times a random vertex is moved up on Z-Axis (Prop. edit Smooth)"
    )

    prop_smooth_down: IntProperty(
        name="Count",
        min=0,
        max=20,
        default=5,
        description=
        "Number of times a random vertex is moved down on Z-Axis (Prop. edit Smooth)"
    )

    prop_random_up: IntProperty(
        name="Count",
        min=0,
        max=20,
        default=10,
        description=
        "Number of times a random vertex is moved up on Z-Axis (Prop. edit Random)"
    )

    prop_random_down: IntProperty(
        name="Count",
        min=0,
        max=20,
        default=5,
        description=
        "Number of times a random vertex is moved down on Z-Axis (Prop. edit Random)"
    )

    size_smooth_up: FloatProperty(name="Size",
                                  min=0.01,
                                  max=10.0,
                                  default=5.0,
                                  description="Terrain height")

    size_smooth_down: FloatProperty(name="Size",
                                    min=0.01,
                                    max=10.0,
                                    default=5.0,
                                    description="Terrain height")

    size_random_up: FloatProperty(name="Size",
                                  min=0.01,
                                  max=10.0,
                                  default=5.0,
                                  description="Terrain height")

    size_random_down: FloatProperty(name="Size",
                                    min=0.01,
                                    max=10.0,
                                    default=5.0,
                                    description="Terrain height")

    def execute(self, context):
        keywords = self.as_keywords()

        main(context, **keywords)

        return {'FINISHED'}

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

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

        box = layout.box()
        col = box.column()
        col.label(text="Basic Terrain Properties")
        rowsub = col.row()
        rowsub.prop(self, "terrain_scale")
        rowsub = col.row()
        rowsub.prop(self, "sub_level")

        box = layout.box()
        col = box.column()
        col.label(
            text="Terrain Deformation via Proportional edit (Z-axis only)")
        rowsub = col.row(align=True)
        rowsub.label(text="Smooth Falloff Up")
        rowsub.prop(self, "prop_smooth_up")
        rowsub.prop(self, "size_smooth_up")
        rowsub = col.row(align=True)
        rowsub.label(text="Smooth Falloff Down")
        rowsub.prop(self, "prop_smooth_down")
        rowsub.prop(self, "size_smooth_down")
        rowsub = col.row(align=True)
        rowsub.label(text="Random Falloff Up")
        rowsub.prop(self, "prop_random_up")
        rowsub.prop(self, "size_random_up")
        rowsub = col.row(align=True)
        rowsub.label(text="Random Falloff Down")
        rowsub.prop(self, "prop_random_down")
        rowsub.prop(self, "size_random_down")
Example #13
0
class EasyPBRBakeProp(PropertyGroup):
    DEFAULT_NAME = "bake"

    def update_names(self, context):
        if self.autonames:
            self.albedo_name = self.base_name + '_albedo'
            self.packed_name = self.base_name + '_packed'
            self.metallic_name = self.base_name + '_metallic'
            self.roughness_name = self.base_name + '_roughness'
            self.ao_name = self.base_name + '_ao'
            self.normal_name = self.base_name + '_normal'

    autonames = BoolProperty(
        name="Automatic Names",
        description="Automatically generate the names of the textures",
        default=True,
        update=update_names)

    dir_path = StringProperty(
        name="Directory Path",
        description="Directory where all the textures will be saved",
        default="//",
        subtype='DIR_PATH')

    base_name = StringProperty(
        name="Base Name",
        description="Base name for the textures when using automatic names",
        default=DEFAULT_NAME,
        update=update_names)

    x_res = IntProperty(name="Resolution X",
                        description="Texture resolution in horizontal axis",
                        default=1024,
                        subtype='PIXEL')

    y_res = IntProperty(name="Resolution Y",
                        description="Texture resolution in vertical axis",
                        default=1024,
                        subtype='PIXEL')

    margin = IntProperty(
        name="Margin",
        description="Extends the baked result as a post process filter",
        default=16,
        subtype='PIXEL',
        min=0,
        max=64)

    selected_to_active = BoolProperty(
        name='Selected to Active',
        description=
        'Bake shading on the surface of selected objects to the active object',
        default=False)

    use_cage = BoolProperty(
        name='Cage',
        description='Cast rays to active object from a cage',
        default=False)

    cage_extrusion = FloatProperty(
        name='Extrusion',
        description=
        'Distance to use for the inward ray cast when using selected to active',
        default=0.0,
        min=0.0,
        max=1.0)

    cage_object = StringProperty(
        name="Cage Object",
        description=
        "Object to use as cage instead of calculating the cage from the active object with cage extrusion",
        default="")

    ########### Albedo #######################
    enable_albedo = BoolProperty(name='Enable Albedo',
                                 description='Generate albedo texture',
                                 default=False)

    albedo_name = StringProperty(
        name="Texture Name",
        description="Name for the albedo texture file",
        default=DEFAULT_NAME + '_albedo')

    albedo_clear = BoolProperty(name="Clear Image",
                                description="Clear albedo image before baking",
                                default=True)

    albedo_clear_color = FloatVectorProperty(name='Clear Color',
                                             description='Albedo clear color',
                                             size=4,
                                             min=0.0,
                                             max=1.0,
                                             default=(0.0, 0.0, 0.0, 1.0),
                                             subtype='COLOR_GAMMA')

    ########### Packed #######################
    pack_channels = BoolProperty(
        name='Channel Packing',
        description=
        'Pack the metallic, roughness and ao bakes into a single image',
        default=False)

    packed_name = StringProperty(
        name="Texture Name",
        description="Name for the channel packed texture file",
        default=DEFAULT_NAME + '_packed')

    packed_clear = BoolProperty(name="Clear Image",
                                description="Clear packed image before baking",
                                default=True)

    packed_clear_color = FloatVectorProperty(
        name='Clear Color',
        description='Packed texture clear color',
        size=4,
        min=0.0,
        max=1.0,
        default=(0.0, 0.0, 0.0, 1.0),
        subtype='COLOR')

    ########### Metallic #######################
    enable_metallic = BoolProperty(name='Enable Metallic',
                                   description='Generate metallic texture',
                                   default=False)

    metallic_name = StringProperty(
        name="Texture Name",
        description="Name for the metallic texture file",
        default=DEFAULT_NAME + '_metallic')

    metallic_clear = BoolProperty(
        name="Clear Image",
        description="Clear metallic image before baking",
        default=True)

    metallic_clear_color = FloatVectorProperty(
        name='Clear Color',
        description='Metallic clear color',
        size=4,
        min=0.0,
        max=1.0,
        default=(0.0, 0.0, 0.0, 1.0),
        subtype='COLOR')

    ########### Roughness #######################
    enable_roughness = BoolProperty(name='Enable Roughness',
                                    description='Generate roughness texture',
                                    default=False)

    roughness_name = StringProperty(
        name="Texture Name",
        description="Name for the roughness texture file",
        default=DEFAULT_NAME + '_roughness')

    roughness_clear = BoolProperty(
        name="Clear Image",
        description="Clear roughness image before baking",
        default=True)

    roughness_clear_color = FloatVectorProperty(
        name='Clear Color',
        description='Roughness clear color',
        size=4,
        min=0.0,
        max=1.0,
        default=(0.0, 0.0, 0.0, 1.0),
        subtype='COLOR')

    ########### Ambient Occlusion #######################
    enable_ao = BoolProperty(name='Enable Ambient Occlusion',
                             description='Generate ambient occlusion texture',
                             default=False)

    ao_name = StringProperty(name="Texture Name",
                             description="Name for the AO texture file",
                             default=DEFAULT_NAME + '_ao')

    ao_clear = BoolProperty(name="Clear Image",
                            description="Clear AO image before baking",
                            default=True)

    ao_clear_color = FloatVectorProperty(name='Clear Color',
                                         description='AO clear color',
                                         size=4,
                                         min=0.0,
                                         max=1.0,
                                         default=(0.0, 0.0, 0.0, 1.0),
                                         subtype='COLOR')

    ao_samples = IntProperty(
        name="Samples",
        description="Number of rays to trace per shader evaluation",
        default=16,
        min=1,
        max=128)

    ao_distance = FloatProperty(
        name='Distance',
        description=
        'Length of rays, defines how far away other faces give occlusion effect',
        default=1.0,
        min=0.0,
    )

    ########### Normal Map #######################
    enable_normal = BoolProperty(name='Enable Normal',
                                 description='Generate normal map texture',
                                 default=False)

    normal_name = StringProperty(
        name='Texture Name',
        description='Name for the normal map texture file',
        default=DEFAULT_NAME + '_normal')

    normal_clear = BoolProperty(
        name='Clear Image',
        description='Clear normal map image before baking',
        default=True)

    normal_space = EnumProperty(items=[
        ('OBJECT', 'Object', 'Bake the normals in object space'),
        ('TANGENT', 'Tangent', 'Bake the normals in tangent space')
    ],
                                name='Normal Space',
                                description='Normal space used to bake',
                                default='TANGENT')
Example #14
0
class SvCastNode(bpy.types.Node, SverchCustomTreeNode):
    """
    Triggers: To Sphere, Prism, Cylinder
    Tooltip: Affect input verts/mesh with a scene texture. Mimics Blender Displace modifier

    """

    bl_idname = 'SvCastNode'
    bl_label = 'Cast'
    bl_icon = 'MOD_CAST'

    origin_modes = [
        ('AVERAGE', 'Average', 'Texture displacement along Vertex Normal', '',
         1),
        ('EXTERNAL', 'External', 'Texture displacement along X axis', '', 2),
    ]

    size_modes = [
        ('AVERAGE', 'Average', 'Input UV coordinates to evaluate texture', '',
         1),
        ('EXTERNAL', 'Defined',
         'Matrix to apply to verts before evaluating texture', '', 2),
    ]

    cast_modes = [(t, t.title(), t.title(), '', id)
                  for id, t in enumerate(CAST_FORMULAS)]

    @throttled
    def handle_size_socket(self, context):
        input_socket = self.inputs['Size']
        if self.size_mode == 'AVERAGE':
            if not input_socket.hide_safe:
                input_socket.hide_safe = True
        else:
            if input_socket.hide_safe:
                input_socket.hide_safe = False

    @throttled
    def handle_origin_socket(self, context):
        input_socket = self.inputs['Origin']
        if self.origin_mode == 'AVERAGE':
            if not input_socket.hide_safe:
                input_socket.hide_safe = True
        else:
            if input_socket.hide_safe:
                input_socket.hide_safe = False

    @throttled
    def handle_uv_sockets(self, context):
        u_socket = self.inputs['U']
        v_socket = self.inputs['V']
        if self.cast_mode == 'Sphere':
            u_socket.hide_safe = True
            v_socket.hide_safe = True
        elif self.cast_mode in ['Cylinder', 'Prism']:
            v_socket.hide_safe = True
            if u_socket.hide_safe:
                u_socket.hide_safe = False
        else:
            if u_socket.hide_safe:
                u_socket.hide_safe = False
            if v_socket.hide_safe:
                v_socket.hide_safe = False

    cast_mode: EnumProperty(name='Cast Type',
                            items=cast_modes,
                            default='Sphere',
                            description='Shape to cast',
                            update=handle_uv_sockets)

    origin_mode: EnumProperty(name='Origin',
                              items=origin_modes,
                              default='AVERAGE',
                              description='Origin of base mesh',
                              update=handle_origin_socket)

    size_mode: EnumProperty(name='Size_mode',
                            items=size_modes,
                            default='AVERAGE',
                            description="Size of base mesh",
                            update=handle_size_socket)

    origin: FloatVectorProperty(name='Origin',
                                description='Origin of the base mesh',
                                size=3,
                                default=(0, 0, 0),
                                update=updateNode)

    scale_out_v: FloatVectorProperty(name='Effect Scale',
                                     description='Scale of the added vector',
                                     size=3,
                                     default=(1, 1, 1),
                                     update=updateNode)

    sphere_axis_scale: FloatVectorProperty(name='Shape Scale',
                                           description='Scale base shape',
                                           size=3,
                                           default=(1, 1, 1),
                                           update=updateNode)

    strength: FloatProperty(name='Strength',
                            description='Stength of the effect',
                            default=1.0,
                            update=updateNode)

    size: FloatProperty(name='Size',
                        description='Size the sphere',
                        default=1.0,
                        update=updateNode)

    U_div: FloatProperty(
        name='Meridians',
        description='Meridians of the UV sphere. If less than 2 -> circular',
        default=4.0,
        update=updateNode)
    V_div: FloatProperty(
        name='Parallels',
        description='Paralels of the UV sphere. If less than 2 -> circular',
        default=4.0,
        update=updateNode)

    list_match: EnumProperty(name="List Match",
                             description="Behavior on different list lengths",
                             items=numpy_list_match_modes,
                             default="REPEAT",
                             update=updateNode)

    output_numpy: BoolProperty(name='Output NumPy',
                               description='Output NumPy arrays',
                               default=False,
                               update=updateNode)

    def sv_init(self, context):

        self.inputs.new('SvVerticesSocket', 'Vertices')
        self.inputs.new('SvVerticesSocket',
                        'Shape Scale').prop_name = 'sphere_axis_scale'
        self.inputs.new('SvVerticesSocket',
                        'Effect Scale').prop_name = 'scale_out_v'
        self.inputs.new('SvVerticesSocket', 'Origin').prop_name = 'origin'
        self.inputs.new('SvStringsSocket', 'Size').prop_name = 'size'
        self.inputs.new('SvStringsSocket', 'Strength').prop_name = 'strength'
        self.inputs.new('SvStringsSocket', 'U').prop_name = 'U_div'
        self.inputs.new('SvStringsSocket', 'V').prop_name = 'V_div'
        self.inputs['Origin'].hide_safe = True
        self.inputs['Size'].hide_safe = True
        self.inputs['U'].hide_safe = True
        self.inputs['V'].hide_safe = True

        self.outputs.new('SvVerticesSocket', 'Vertices')

    def draw_buttons(self, context, layout):
        layout.prop(self, 'cast_mode', expand=False, text='To')
        layout.prop(self, 'origin_mode', expand=False, text='Origin')
        layout.prop(self, 'size_mode', expand=False, text='Size')

    def draw_buttons_ext(self, context, layout):
        '''draw buttons on the N-panel'''
        self.draw_buttons(context, layout)
        layout.prop(self, 'output_numpy')
        layout.prop(self, 'list_match', expand=False)

    def rclick_menu(self, context, layout):
        layout.prop(self, 'output_numpy')
        layout.prop_menu_enum(self, "list_match", text="List Match")

    def draw_label(self):
        return self.label or self.name + ' to ' + self.cast_mode.title()

    def process(self):
        inputs, outputs = self.inputs, self.outputs

        if not outputs[0].is_linked:
            return

        result = []

        params = [si.sv_get(default=[[]], deepcopy=False) for si in inputs]

        matching_f = list_match_func[self.list_match]
        desired_levels = [3, 3, 3, 3, 2, 2, 2, 2]
        ops = [
            self.cast_mode, self.origin_mode, self.list_match, self.size_mode,
            self.output_numpy
        ]

        result = recurse_f_level_control(params, ops, cast_meshes, matching_f,
                                         desired_levels)

        self.outputs[0].sv_set(result)
Example #15
0
class SureUVWOperator(bpy.types.Operator):
    bl_idname = "object.sureuvw_operator"
    bl_label = "Sure UVW Map"
    bl_space_type = "PROPERTIES"
    bl_region_type = "WINDOW"
    bl_context = "data"

    bl_options = {'REGISTER', 'UNDO'}

    action = StringProperty()

    size = FloatProperty(name="Size", default=1.0)
    rot = FloatVectorProperty(name="XYZ Rotation")
    offset = FloatVectorProperty(name="XYZ offset")

    zrot = FloatProperty(name="Z rotation", default=0.0)
    xoffset = FloatProperty(name="X offset", default=0.0)
    yoffset = FloatProperty(name="Y offset", default=0.0)

    flag90 = BoolProperty()
    flag90ccw = BoolProperty()

    @classmethod
    def poll(cls, context):
        obj = context.active_object
        return (obj and obj.type == 'MESH')

    def execute(self, context):
        #print('** execute **')
        #print(self.action)
        global all_scale_def, x_offset_def, y_offset_def, z_offset_def, x_rot_def, y_rot_def, z_rot_def, xoffset_def, yoffset_def, zrot_def

        all_scale_def = self.size
        x_offset_def = self.offset[0]
        y_offset_def = self.offset[1]
        z_offset_def = self.offset[2]
        x_rot_def = self.rot[0]
        y_rot_def = self.rot[1]
        z_rot_def = self.rot[2]

        xoffset_def = self.xoffset
        yoffset_def = self.yoffset
        zrot_def = self.zrot

        if self.flag90:
            self.zrot += 90
            zrot_def += 90
            self.flag90 = False

        if self.flag90ccw:
            self.zrot += -90
            zrot_def += -90
            self.flag90ccw = False

        if self.action == 'bestplanar':
            best_planar_map()
        elif self.action == 'box':
            box_map()
        elif self.action == 'showtex':
            show_texture()
        elif self.action == 'doneplanar':
            best_planar_map()
        elif self.action == 'donebox':
            box_map()

        #print('finish execute')
        return {'FINISHED'}

    def invoke(self, context, event):
        #print('** invoke **')
        #print(self.action)
        global all_scale_def, x_offset_def, y_offset_def, z_offset_def, x_rot_def, y_rot_def, z_rot_def, xoffset_def, yoffset_def, zrot_def

        self.size = all_scale_def
        self.offset[0] = x_offset_def
        self.offset[1] = y_offset_def
        self.offset[2] = z_offset_def
        self.rot[0] = x_rot_def
        self.rot[1] = y_rot_def
        self.rot[2] = z_rot_def

        self.xoffset = xoffset_def
        self.yoffset = yoffset_def
        self.zrot = zrot_def

        if self.action == 'bestplanar':
            best_planar_map()
        elif self.action == 'box':
            box_map()
        elif self.action == 'showtex':
            show_texture()
        elif self.action == 'doneplanar':
            best_planar_map()
        elif self.action == 'donebox':
            box_map()

        #print('finish invoke')
        return {'FINISHED'}

    def draw(self, context):
        if self.action == 'bestplanar' or self.action == 'rotatecw' or self.action == 'rotateccw':
            self.action = 'bestplanar'
            layout = self.layout
            layout.label("Size - " + self.action)
            layout.prop(self, 'size', text="")
            layout.label("Z rotation")
            col = layout.column()
            col.prop(self, 'zrot', text="")
            row = layout.row()
            row.prop(self, 'flag90ccw', text="-90 (CCW)")
            row.prop(self, 'flag90', text="+90 (CW)")
            layout.label("XY offset")
            col = layout.column()
            col.prop(self, 'xoffset', text="")
            col.prop(self, 'yoffset', text="")

            #layout.prop(self,'preview_flag', text="Interactive Preview")
            #layout.operator("object.sureuvw_operator",text="Done").action='doneplanar'

        elif self.action == 'box':
            layout = self.layout
            layout.label("Size")
            layout.prop(self, 'size', text="")
            layout.label("XYZ rotation")
            col = layout.column()
            col.prop(self, 'rot', text="")
            layout.label("XYZ offset")
            col = layout.column()
            col.prop(self, 'offset', text="")
Example #16
0
class SvMatrixGenNodeMK2(bpy.types.Node, SverchCustomTreeNode):
    ''' MatrixGeneratorMK2 '''
    bl_idname = 'SvMatrixGenNodeMK2'
    bl_label = 'Matrix in'
    bl_icon = 'OUTLINER_OB_EMPTY'

    l_ = FloatVectorProperty(name='L',
                             default=(0.0, 0.0, 0.0),
                             description='Location',
                             precision=3,
                             update=updateNode)
    s_ = FloatVectorProperty(name='S',
                             default=(1.0, 1.0, 1.0),
                             description='Scale',
                             precision=3,
                             update=updateNode)
    r_ = FloatVectorProperty(name='R',
                             default=(0.0, 0.0, 1.0),
                             description='Rotation',
                             precision=3,
                             update=updateNode)
    a_ = FloatProperty(name='A',
                       description='Angle',
                       default=0.0,
                       precision=3,
                       update=updateNode)

    def sv_init(self, context):
        s = self.inputs.new('VerticesSocket', "Location")
        s.prop_name = 'l_'
        s = self.inputs.new('VerticesSocket', "Scale")
        s.prop_name = 's_'
        s = self.inputs.new('VerticesSocket', "Rotation")
        s.prop_name = 'r_'
        s = self.inputs.new('StringsSocket', "Angle")
        s.prop_name = 'a_'
        self.outputs.new('MatrixSocket', "Matrix")

    def migrate_from(self, old_node):
        if old_node.bl_idname == 'MatrixGenNode':
            self.l_ = old_node.inputs['Location'].prop
            self.s_ = old_node.inputs['Scale'].prop
            self.r_ = old_node.inputs['Rotation'].prop

    def process(self):
        L, S, R, A = self.inputs
        Ma = self.outputs[0]
        if not Ma.is_linked:
            return
        loc = Vector_generate(L.sv_get())
        scale = Vector_generate(S.sv_get())
        rot = Vector_generate(R.sv_get())
        rotA, angle = [[]], [[0.0]]
        # ability to add vector & vector difference instead of only rotation values
        if A.is_linked:
            if A.links[0].from_socket.bl_idname == 'VerticesSocket':
                rotA = Vector_generate(A.sv_get())
                angle = [[]]
            elif A.links[0].from_socket.bl_idname == 'StringsSocket':
                angle = A.sv_get()
                rotA = [[]]
        else:
            angle = A.sv_get()
            rotA = [[]]

        max_l = max(len(loc[0]), len(scale[0]), len(rot[0]), len(angle[0]),
                    len(rotA[0]))
        orig = []
        for l in range(max_l):
            M = mathutils.Matrix()
            orig.append(M)
        matrixes_ = matrixdef(orig, loc, scale, rot, angle, rotA)
        matrixes = Matrix_listing(matrixes_)
        Ma.sv_set(matrixes)
Example #17
0
class OBJECT_OT_add_object(Operator, AddObjectHelper):
    """plantFEM soil object"""
    bl_idname = "mesh.add_object"
    bl_label = "Add Mesh Object"
    bl_options = {'REGISTER', 'UNDO'}


    scale: FloatVectorProperty(
        name="scale",
        default=(1.0, 1.0, 1.0),
        subtype='TRANSLATION',
        description="scaling",
    )

    def execute(self, context):
        
        #add_object(self, context)
        #bpy.ops.mesh.primitive_cube_add(enter_editmode=False, location=(0, 0, 0))
        verts = [
        Vector((-1.0, -1.0, 1.0)), 
        Vector(( 1.0, -1.0, 1.0)),
        Vector(( 1.0,  1.0, 1.0)),
        Vector((-1.0,  1.0, 1.0)),
        Vector((-1.0, -1.0,-1.0)),
        Vector(( 1.0, -1.0,-1.0)),
        Vector(( 1.0,  1.0,-1.0)),
        Vector((-1.0,  1.0,-1.0))
        ]
        faces = [ [0,1,2,3],[0,4,5,1],[1,5,6,2],[2,6,7,3],[0,3,7,4],[4,7,6,5]]
        mesh = bpy.data.meshes.new(name="SoilMesh_")
        mesh.from_pydata(verts, [], faces)
        mesh.update
        obj = bpy.data.objects.new(name="Soil_",object_data=mesh)
        scene = bpy.context.scene
        scene.collection.objects.link(obj)
        
        obj.data.name = "Soil_"
        obj["x_num"]=int(10)        
        obj["y_num"]=int(10)
        obj["z_num"]=int(10)
        obj["YoungsModulus"]=float(100)
        obj["PoissonRatio"]=float(0.3)
        obj["Permiability"]=float(0.0000001)
        obj["a_Psi"]=float(20)
        obj["a_P"]=float(40)
        obj["theta_eq"]=float(1)
        obj["Psi_eq"]=float(20)
        obj["a_E"]=float(0)
        obj["a_v"]=float(0)
        obj["E_eq"]=float(100)
        obj["v_eq"]=float(0.3)
        
        for obj in bpy.context.selected_objects:
            obj.name = "Soil_"
            obj.data.name = "Soil_"
            obj["x_num"]=int(10)        
            obj["y_num"]=int(10)
            obj["z_num"]=int(10)
            obj["YoungsModulus"]=float(100)
            obj["PoissonRatio"]=float(0.3)
            obj["Permiability"]=float(0.0000001)
            obj["a_Psi"]=float(20)
            obj["a_P"]=float(40)
            obj["theta_eq"]=float(1)
            obj["Psi_eq"]=float(20)
            obj["a_E"]=float(0)
            obj["a_v"]=float(0)
            obj["E_eq"]=float(100)
            obj["v_eq"]=float(0.3)
            #bpy.ops.object.mode_set(mode = "EDIT")
            for vt in mesh.vertices:
                print(vt.index)
        
        
        

        return {'FINISHED'}
class AddPlaygroundStructure(bpy.types.Operator):
    """Add a simple playground structure"""
    bl_idname = "mesh.playground_structure_add"
    bl_label = "Add Playground Structure"
    bl_options = {'REGISTER', 'UNDO'}

    length = FloatProperty(
            name="Length",
            description="How long the structure is",
            min=0.01,
            default=1.0,
            )
    width = FloatProperty(
            name="Width",
            description="How wide the structure is",
            min=0.01,
            default=1.0,
            )
    roof_height = FloatProperty(
            name="Roof Height",
            description="How tall the roof is",
            min=0.01,
            default=0.5,
            )
    roof_thick = FloatProperty(
            name="Roof Thickness",
            description="Thickness of the roof",
            min=0.0,
            default=0.125,
            )
    roof_x = FloatProperty(
            name="Roof Scale X",
            description="Grows/Shrinks the top of the roof along the x-axis",
            min=0.0,
            default=0.5,
            )
    roof_y = FloatProperty(
            name="Roof Scale Y",
            description="Grows/Shrinks the top of the roof along the y-axis",
            min=0.0,
            default=0.5,
            )
    roof_str = FloatProperty(
            name="Roof Bevel Offset",
            description="How strong the roof bevel is",
            min=0.0,
            default=0.0125,
            )
    roof_seg = IntProperty(
            name="Roof Bevel Segments",
            description="How many segments make up the roof bevel",
            min=0,
            default=2,
            )
    platform_h = FloatProperty(
            name="Platform Height",
            description="How high off the ground the platform is",
            min=0.01,
            default=2.0,
            )
    platform_t = FloatProperty(
            name="Platform Thickness",
            description="How thick the platform is",
            min=0.01,
            default=0.05,
            )
    platform_str = FloatProperty(
            name="Platform Bevel Offset",
            description="How strong the platform bevel is",
            min=0.0,
            default=0.0125,
            )
    platform_seg = IntProperty(
            name="Roof Bevel Segments",
            description="How many segments make up the platform bevel",
            min=0,
            default=2,
            )
    supports_seg = IntProperty(
            name="Supports Segments",
            description="How many segments make up the cylinders for the supports",
            min=3,
            default=16,
            )
    supports_rad = FloatProperty(
            name="Supports Radius",
            description="How thick the supports are",
            min=0.001,
            default=0.0675,
            )
    supports_h = FloatProperty(
            name="Supports Height",
            description="How tall the supports are",
            min=0.01,
            default=4.0,
            )
    supports_shift = FloatProperty(
            name="Supports Shift",
            description="Moves the supports away from the edge",
            default=0.0125,
            )
    location = FloatVectorProperty(
            name="Location",
            subtype='TRANSLATION',
            )
    rotation = FloatVectorProperty(
            name="Rotation",
            subtype='EULER',
            )
            
    def draw(self, context):
        layout = self.layout
        
        box = layout.box()
        col = box.column()
        col.label(text="General", icon="NOCURVE")
        col.prop(self, "length")
        col.prop(self, "width")
        col.prop(self, "location")
        col.prop(self, "rotation")
        
        box = layout.box()
        col = box.column()
        col.label(text="Roof", icon="LINCURVE")
        col.prop(self, "roof_height")
        col.prop(self, "roof_thick")
        col.prop(self, "roof_x")
        col.prop(self, "roof_y")
        col.prop(self, "roof_str")
        col.prop(self, "roof_seg")
        
        box = layout.box()
        col = box.column()
        col.label(text="Supports", icon="PAUSE")
        col.prop(self, "supports_rad")
        col.prop(self, "supports_h")
        col.prop(self, "supports_shift")
        col.prop(self, "supports_seg")
        
        box = layout.box()
        col = box.column()
        col.label(text="Platform", icon="ZOOMOUT")
        col.prop(self, "platform_t")
        col.prop(self, "platform_h")
        col.prop(self, "platform_str")
        col.prop(self, "platform_seg")

    def execute(self, context):
        #Rename the variables
        #to something simpler
        l = self.length
        w = self.width
        rh = self.roof_height
        rt = self.roof_thick
        rx = self.roof_x
        ry = self.roof_y
        rstr = self.roof_str
        rseg = self.roof_seg
        ph = self.platform_h
        pt = self.platform_t
        pstr = self.platform_str
        pseg = self.platform_seg
        sr = self.supports_rad
        sh = self.supports_h
        ss = self.supports_seg
        sshift = self.supports_shift
        pos = self.location
        rotate = self.rotation
        
        #Basic roof geometry:
        verts= [(-l * rx, -w * ry, rh + sh),
                (-l * rx, w * ry, rh + sh),
                (l * rx, -w * ry, rh + sh),
                (l * rx, w * ry, rh + sh),
                (-l, w, sh),
                (-l, -w , sh),
                (l, w, sh),
                (l, -w, sh),
                ]
        
        faces= [(5, 0, 1, 4),
                (4, 1, 3, 6),
                (6, 3, 2, 7),
                (7, 2, 0, 5),
                (3, 1, 0, 2),
                ]
        
        #Make the roof:
        r_mesh = bpy.data.meshes.new("roof")
        roof_obj = bpy.data.objects.new("Roof_Obj", r_mesh)

        scene = bpy.context.scene
        scene.objects.link(roof_obj)
        bm = bmesh.new()
        
        #Add verts, then faces:
        for v_co in verts:
            bm.verts.new(v_co)

        bm.verts.ensure_lookup_table()
        for f_idx in faces:
            bm.faces.new([bm.verts[i] for i in f_idx])
        
        #Smooth it:
        for f in bm.faces:
            f.smooth = True
        
        
        
        #Finalize changes:
        bm.to_mesh(r_mesh)
        bm.free()
        r_mesh.update()
        
        #Apply solidify modifier:
        bpy.context.scene.objects.active = roof_obj
        thick_mod = roof_obj.modifiers.new("thick_mod", type='SOLIDIFY')
        thick_mod.thickness = rt
        bpy.ops.object.modifier_apply(apply_as='DATA', modifier=thick_mod.name)
        
        
        bm = bmesh.new()
        bm.from_mesh(r_mesh)
        
        #Now fix the bottom verts:
        for v in bm.verts:
            if v.co.z < sh:
                v.co.z = sh
        
        if rseg > 0 and rstr > 0.0:
            #Now bevel it:
            bmesh.ops.bevel(bm, 
                            geom=bm.verts[:] + bm.edges[:], 
                            offset=rstr, 
                            offset_type=0, 
                            segments=rseg, 
                            profile=0.5, 
                            clamp_overlap=True,)
        
        #Finalize changes:
        bm.to_mesh(r_mesh)
        bm.free()
        r_mesh.update()
        
        #Make the platform:
        p_mesh = bpy.data.meshes.new("platform")
        platform_obj = bpy.data.objects.new("Platform_Obj", p_mesh)

        scene = bpy.context.scene
        scene.objects.link(platform_obj)
        bm = bmesh.new()
        
        #Make the box:
        bmesh.ops.create_cube(bm, size=2.0,)
        
        #And resize it:
        loc = mathutils.Matrix.Translation((0.0, 0.0, 0.0))
        scl = (l, w, pt)
        bmesh.ops.scale(bm, 
                        vec=scl, 
                        space=loc, 
                        verts=bm.verts)
        
        #Move it up to the proper height:
        bmesh.ops.translate(bm, 
                            vec=(0.0, 0.0, ph), 
                            verts=bm.verts)
        
        if pstr > 0.0 and pseg > 0:
            #And bevel it:
            new_geom = bmesh.ops.bevel(bm, 
                                       geom=bm.verts[:] + bm.edges[:], 
                                       offset=pstr, 
                                       offset_type=0, 
                                       segments=pseg, 
                                       profile=0.5, 
                                       clamp_overlap=True,)
            
            for f in new_geom["faces"]:
                f.smooth = True
        
        #Finalize changes:
        bm.to_mesh(p_mesh)
        bm.free()
        p_mesh.update()
        
        #Make the supports:
        s_mesh = bpy.data.meshes.new("supports")
        supports_obj = bpy.data.objects.new("Supports_Obj", s_mesh)

        scene = bpy.context.scene
        scene.objects.link(supports_obj)
        bm = bmesh.new()
        
        #Positions for the supports:
        loc = [(l - sr - sshift, w - sr - sshift, sh / 2.0),
               (-(l - sr - sshift), w - sr - sshift, sh / 2.0),
               (l - sr - sshift, -(w - sr - sshift), sh / 2.0),
               (-(l - sr - sshift), -(w - sr - sshift), sh / 2.0),]
        
        #Make 4 supports:
        #Add the cylinder:
        for i in range(0, 4):
            new_geom = bmesh.ops.create_cone(bm, 
                                             cap_ends=False,
                                             segments=ss, 
                                             diameter1=sr, 
                                             diameter2=sr, 
                                             depth=sh,)
            
            #Move it:
            bmesh.ops.translate(bm,
                                verts=new_geom["verts"],
                                vec=loc[i])
            
            del new_geom
        
        #Smooth it:
        for f in bm.faces:
            f.smooth = True
        
        #Finalize changes:
        bm.to_mesh(s_mesh)
        bm.free()
        s_mesh.update()
        
        #Combine the objects:
        bpy.ops.object.select_all(action='DESELECT')
        roof_obj.select = True
        bpy.context.scene.objects.active = roof_obj
        platform_obj.select = True
        supports_obj.select = True
        bpy.ops.object.join()
        context.active_object.name = 'Playground_Structure'
        
        #Move and rotate it:
        roof_obj.rotation_euler = rotate
        roof_obj.location = pos
        
        bpy.ops.object.transform_apply(location=True, 
                                       rotation=True, 
                                       scale=True)
        

        return {'FINISHED'}
Example #19
0
class CreateRCD111Waveguide(bpy.types.Operator):
  bl_idname = "object.create_rcd111_waveguide"
  bl_label = "Create RCD111 waveguide"
  bl_options = {'REGISTER', 'UNDO', 'PRESET'}
  
  (preset_vectors , preset_vectors_groups) = bfdtd.RCD.RCD111_waveguide_vector_dictionary()
  direction = EnumProperty(items = (("three_arrays","Use 3 arrays","Avoids overlapping objects, but the origin and location of the original are modified. Uses less memory."), ("six_arrays","Use 6 arrays","Can lead to overlapping objects. Preserves origin and location of the original. Easy to change periods later. Memory intensive.")), default='three_arrays', name = "Method:")
  
  array_X_positive = BoolProperty(name="Array along +X", default=True)
  array_X_positive_size = IntProperty(name="number of periods in +X", default = 2, min=1)
  array_Y_positive = BoolProperty(name="Array along +Y", default=True)
  array_Y_positive_size = IntProperty(name="number of periods in +Y", default = 3, min=1)
  array_Z_positive = BoolProperty(name="Array along +Z", default=True)
  array_Z_positive_size = IntProperty(name="number of periods in +Z", default = 4, min=1)
  
  array_X_negative = BoolProperty(name="Array along -X", default=False)
  array_X_negative_size = IntProperty(name="number of periods in -X", default = 2, min=1)
  array_Y_negative = BoolProperty(name="Array along -Y", default=False)
  array_Y_negative_size = IntProperty(name="number of periods in -Y", default = 3, min=1)
  array_Z_negative = BoolProperty(name="Array along -Z", default=False)
  array_Z_negative_size = IntProperty(name="number of periods in -Z", default = 4, min=1)
  
  e1_vec3 = FloatVectorProperty(name="e1_vec3", default=Vector((1,0,0)))
  e2_vec3 = FloatVectorProperty(name="e2_vec3", default=Vector((0,1,0)))
  e3_vec3 = FloatVectorProperty(name="e3_vec3", default=Vector((0,0,1)))
  
  use_scale = BoolProperty(name="Use object scale", default=False) # TODO: Take scale into account?
  apply_scale = BoolProperty(name="Apply scale first", default=False) # TODO: Take scale into account?
  
  def draw(self, context):
    layout = self.layout
    box = layout.box()
    box.prop(self, 'method')
    
    if self.method == 'three_arrays':
      box.prop(self, 'array_X_positive')
      if self.array_X_positive:
        box.prop(self, 'array_X_positive_size')
        box.prop(self, 'array_X_negative_size')
      box.prop(self, 'array_Y_positive')
      if self.array_Y_positive:
        box.prop(self, 'array_Y_positive_size')
        box.prop(self, 'array_Y_negative_size')
      box.prop(self, 'array_Z_positive')
      if self.array_Z_positive:
        box.prop(self, 'array_Z_positive_size')
        box.prop(self, 'array_Z_negative_size')
      
    else:
      box.prop(self, 'array_X_positive')
      if self.array_X_positive:
        box.prop(self, 'array_X_positive_size')
      box.prop(self, 'array_Y_positive')
      if self.array_Y_positive:
        box.prop(self, 'array_Y_positive_size')
      box.prop(self, 'array_Z_positive')
      if self.array_Z_positive:
        box.prop(self, 'array_Z_positive_size')
      
      box.prop(self, 'array_X_negative')
      if self.array_X_negative:
        box.prop(self, 'array_X_negative_size')
      box.prop(self, 'array_Y_negative')
      if self.array_Y_negative:
        box.prop(self, 'array_Y_negative_size')
      box.prop(self, 'array_Z_negative')
      if self.array_Z_negative:
        box.prop(self, 'array_Z_negative_size')
    
    box.prop(self, 'e1_vec3')
    box.prop(self, 'e2_vec3')
    box.prop(self, 'e3_vec3')
    
    box.prop(self, 'use_scale')
    box.prop(self, 'apply_scale')

  def execute(self, context):
    return {'FINISHED'}
    
    obj = context.active_object
    obj_location_original = obj.location.copy()
    
    if self.apply_scale:
      bpy.ops.object.transform_apply(location=False, rotation=False, scale=True)
    
    if self.use_scale:
      e1_vec3 = Vector(self.e1_vec3)
      e2_vec3 = Vector(self.e2_vec3)
      e3_vec3 = Vector(self.e3_vec3)
    else:
      e1_vec3 = scale_vector_divide(obj.scale, self.e1_vec3)
      e2_vec3 = scale_vector_divide(obj.scale, self.e2_vec3)
      e3_vec3 = scale_vector_divide(obj.scale, self.e3_vec3)
        
    if self.method == 'three_arrays':
      if self.use_scale:
        if self.array_X_positive:
          obj.location = obj.location - (self.array_X_negative_size - 1) * scale_vector_multiply(obj.scale, self.e1_vec3)
        if self.array_Y_positive:
          obj.location = obj.location - (self.array_Y_negative_size - 1) * scale_vector_multiply(obj.scale, self.e2_vec3)
        if self.array_Z_positive:
          obj.location = obj.location - (self.array_Z_negative_size - 1) * scale_vector_multiply(obj.scale, self.e3_vec3)
      else:
        if self.array_X_positive:
          obj.location = obj.location - (self.array_X_negative_size - 1) * Vector(self.e1_vec3)
        if self.array_Y_positive:
          obj.location = obj.location - (self.array_Y_negative_size - 1) * Vector(self.e2_vec3)
        if self.array_Z_positive:
          obj.location = obj.location - (self.array_Z_negative_size - 1) * Vector(self.e3_vec3)
      
      setOrigin(obj, obj_location_original)
      
      if self.array_X_positive:
        add_array_modifier(obj, 'array X', self.array_X_positive_size + self.array_X_negative_size - 1, e1_vec3)
      if self.array_Y_positive:
        add_array_modifier(obj, 'array Y', self.array_Y_positive_size + self.array_Y_negative_size - 1, e2_vec3)
      if self.array_Z_positive:
        add_array_modifier(obj, 'array Z', self.array_Z_positive_size + self.array_Z_negative_size - 1, e3_vec3)
      
    else:
      if self.array_X_positive:
        add_array_modifier(obj, 'array +X', self.array_X_positive_size, e1_vec3)
      if self.array_Y_positive:
        add_array_modifier(obj, 'array +Y', self.array_Y_positive_size, e2_vec3)
      if self.array_Z_positive:
        add_array_modifier(obj, 'array +Z', self.array_Z_positive_size, e3_vec3)
      if self.array_X_negative:
        add_array_modifier(obj, 'array -X', self.array_X_negative_size, -e1_vec3)
      if self.array_Y_negative:
        add_array_modifier(obj, 'array -Y', self.array_Y_negative_size, -e2_vec3)
      if self.array_Z_negative:
        add_array_modifier(obj, 'array -Z', self.array_Z_negative_size, -e3_vec3)
    
    return {'FINISHED'}
Example #20
0
class Simple(Operator, object_utils.AddObjectHelper):
    bl_idname = "curve.simple"
    bl_label = "Simple Curve"
    bl_description = "Construct a Simple Curve"
    bl_options = {'REGISTER', 'UNDO', 'PRESET'}

    # change properties
    Simple: BoolProperty(name="Simple",
                         default=True,
                         description="Simple Curve")
    Simple_Change: BoolProperty(name="Change",
                                default=False,
                                description="Change Simple Curve")
    Simple_Delete: StringProperty(name="Delete",
                                  description="Delete Simple Curve")
    # general properties
    Types = [('Point', "Point", "Construct a Point"),
             ('Line', "Line", "Construct a Line"),
             ('Distance', "Distance", "Construct a two point Distance"),
             ('Angle', "Angle", "Construct an Angle"),
             ('Circle', "Circle", "Construct a Circle"),
             ('Ellipse', "Ellipse", "Construct an Ellipse"),
             ('Arc', "Arc", "Construct an Arc"),
             ('Sector', "Sector", "Construct a Sector"),
             ('Segment', "Segment", "Construct a Segment"),
             ('Rectangle', "Rectangle", "Construct a Rectangle"),
             ('Rhomb', "Rhomb", "Construct a Rhomb"),
             ('Polygon', "Polygon", "Construct a Polygon"),
             ('Polygon_ab', "Polygon ab", "Construct a Polygon ab"),
             ('Trapezoid', "Trapezoid", "Construct a Trapezoid")]
    Simple_Type: EnumProperty(name="Type",
                              description="Form of Curve to create",
                              items=Types)
    # Line properties
    Simple_endlocation: FloatVectorProperty(name="",
                                            description="End location",
                                            default=(2.0, 2.0, 2.0),
                                            subtype='TRANSLATION')
    # Trapezoid properties
    Simple_a: FloatProperty(name="Side a",
                            default=2.0,
                            min=0.0,
                            soft_min=0.0,
                            unit='LENGTH',
                            description="a side Value")
    Simple_b: FloatProperty(name="Side b",
                            default=1.0,
                            min=0.0,
                            soft_min=0.0,
                            unit='LENGTH',
                            description="b side Value")
    Simple_h: FloatProperty(
        name="Height",
        default=1.0,
        unit='LENGTH',
        description="Height of the Trapezoid - distance between a and b")
    Simple_angle: FloatProperty(name="Angle",
                                default=45.0,
                                description="Angle")
    Simple_startangle: FloatProperty(name="Start angle",
                                     default=0.0,
                                     min=-360.0,
                                     soft_min=-360.0,
                                     max=360.0,
                                     soft_max=360.0,
                                     description="Start angle")
    Simple_endangle: FloatProperty(name="End angle",
                                   default=45.0,
                                   min=-360.0,
                                   soft_min=-360.0,
                                   max=360.0,
                                   soft_max=360.0,
                                   description="End angle")
    Simple_sides: IntProperty(name="Sides",
                              default=3,
                              min=0,
                              soft_min=0,
                              description="Sides")
    Simple_radius: FloatProperty(name="Radius",
                                 default=1.0,
                                 min=0.0,
                                 soft_min=0.0,
                                 unit='LENGTH',
                                 description="Radius")
    Simple_center: BoolProperty(name="Length center",
                                default=True,
                                description="Length center")

    Angle_types = [('Degrees', "Degrees", "Use Degrees"),
                   ('Radians', "Radians", "Use Radians")]
    Simple_degrees_or_radians: EnumProperty(name="Degrees or radians",
                                            description="Degrees or radians",
                                            items=Angle_types)
    # Rectangle properties
    Simple_width: FloatProperty(name="Width",
                                default=2.0,
                                min=0.0,
                                soft_min=0,
                                unit='LENGTH',
                                description="Width")
    Simple_length: FloatProperty(name="Length",
                                 default=2.0,
                                 min=0.0,
                                 soft_min=0.0,
                                 unit='LENGTH',
                                 description="Length")
    Simple_rounded: FloatProperty(name="Rounded",
                                  default=0.0,
                                  min=0.0,
                                  soft_min=0.0,
                                  unit='LENGTH',
                                  description="Rounded corners")
    # Curve Options
    shapeItems = [('2D', "2D", "2D shape Curve"),
                  ('3D', "3D", "3D shape Curve")]
    shape: EnumProperty(name="2D / 3D",
                        items=shapeItems,
                        description="2D or 3D Curve")
    outputType: EnumProperty(name="Output splines",
                             description="Type of splines to output",
                             items=[('POLY', "Poly", "Poly Spline type"),
                                    ('NURBS', "Nurbs", "Nurbs Spline type"),
                                    ('BEZIER', "Bezier", "Bezier Spline type")
                                    ],
                             default='BEZIER')
    use_cyclic_u: BoolProperty(name="Cyclic",
                               default=True,
                               description="make curve closed")
    endp_u: BoolProperty(name="Use endpoint u",
                         default=True,
                         description="stretch to endpoints")
    order_u: IntProperty(name="Order u",
                         default=4,
                         min=2,
                         soft_min=2,
                         max=6,
                         soft_max=6,
                         description="Order of nurbs spline")
    handleType: EnumProperty(name="Handle type",
                             default='VECTOR',
                             description="Bezier handles type",
                             items=[('VECTOR', "Vector",
                                     "Vector type Bezier handles"),
                                    ('AUTO', "Auto",
                                     "Automatic type Bezier handles")])
    edit_mode: BoolProperty(name="Show in edit mode",
                            default=True,
                            description="Show in edit mode")

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

        # general options
        col = layout.column()
        col.prop(self, "Simple_Type")

        l = 0
        s = 0

        if self.Simple_Type == 'Line':
            box = layout.box()
            col = box.column(align=True)
            col.label(text=self.Simple_Type + " Options:")
            col.prop(self, "Simple_endlocation")
            v = Vector(self.Simple_endlocation) - Vector(self.location)
            l = v.length

        if self.Simple_Type == 'Distance':
            box = layout.box()
            col = box.column(align=True)
            col.label(text=self.Simple_Type + " Options:")
            col.prop(self, "Simple_length")
            col.prop(self, "Simple_center")
            l = self.Simple_length

        if self.Simple_Type == 'Angle':
            box = layout.box()
            col = box.column(align=True)
            col.label(text=self.Simple_Type + " Options:")
            col.prop(self, "Simple_length")
            col.prop(self, "Simple_angle")

        if self.Simple_Type == 'Circle':
            box = layout.box()
            col = box.column(align=True)
            col.label(text=self.Simple_Type + " Options:")
            col.prop(self, "Simple_sides")
            col.prop(self, "Simple_radius")

            l = 2 * pi * abs(self.Simple_radius)
            s = pi * self.Simple_radius * self.Simple_radius

        if self.Simple_Type == 'Ellipse':
            box = layout.box()
            col = box.column(align=True)
            col.label(text=self.Simple_Type + " Options:")
            col.prop(self, "Simple_a", text="Radius a")
            col.prop(self, "Simple_b", text="Radius b")

            l = pi * (3 * (self.Simple_a + self.Simple_b) - sqrt(
                (3 * self.Simple_a + self.Simple_b) *
                (self.Simple_a + 3 * self.Simple_b)))

            s = pi * abs(self.Simple_b) * abs(self.Simple_a)

        if self.Simple_Type == 'Arc':
            box = layout.box()
            col = box.column(align=True)
            col.label(text=self.Simple_Type + " Options:")
            col.prop(self, "Simple_sides")
            col.prop(self, "Simple_radius")

            col = box.column(align=True)
            col.prop(self, "Simple_startangle")
            col.prop(self, "Simple_endangle")
            #row = layout.row()
            #row.prop(self, "Simple_degrees_or_radians", expand=True)

            l = abs(pi * self.Simple_radius *
                    (self.Simple_endangle - self.Simple_startangle) / 180)

        if self.Simple_Type == 'Sector':
            box = layout.box()
            col = box.column(align=True)
            col.label(text=self.Simple_Type + " Options:")
            col.prop(self, "Simple_sides")
            col.prop(self, "Simple_radius")

            col = box.column(align=True)
            col.prop(self, "Simple_startangle")
            col.prop(self, "Simple_endangle")
            #row = layout.row()
            #row.prop(self, "Simple_degrees_or_radians", expand=True)

            l = abs(pi * self.Simple_radius *
                    (self.Simple_endangle - self.Simple_startangle) /
                    180) + self.Simple_radius * 2

            s = pi * self.Simple_radius * self.Simple_radius * \
                abs(self.Simple_endangle - self.Simple_startangle) / 360

        if self.Simple_Type == 'Segment':
            box = layout.box()
            col = box.column(align=True)
            col.label(text=self.Simple_Type + " Options:")
            col.prop(self, "Simple_sides")
            col.prop(self, "Simple_a", text="Radius a")
            col.prop(self, "Simple_b", text="Radius b")

            col = box.column(align=True)
            col.prop(self, "Simple_startangle")
            col.prop(self, "Simple_endangle")

            #row = layout.row()
            #row.prop(self, "Simple_degrees_or_radians", expand=True)

            la = abs(pi * self.Simple_a *
                     (self.Simple_endangle - self.Simple_startangle) / 180)
            lb = abs(pi * self.Simple_b *
                     (self.Simple_endangle - self.Simple_startangle) / 180)
            l = abs(self.Simple_a - self.Simple_b) * 2 + la + lb

            sa = pi * self.Simple_a * self.Simple_a * \
                abs(self.Simple_endangle - self.Simple_startangle) / 360

            sb = pi * self.Simple_b * self.Simple_b * \
                abs(self.Simple_endangle - self.Simple_startangle) / 360

            s = abs(sa - sb)

        if self.Simple_Type == 'Rectangle':
            box = layout.box()
            col = box.column(align=True)
            col.label(text=self.Simple_Type + " Options:")
            col.prop(self, "Simple_width")
            col.prop(self, "Simple_length")
            col.prop(self, "Simple_rounded")

            box.prop(self, "Simple_center")
            l = 2 * abs(self.Simple_width) + 2 * abs(self.Simple_length)
            s = abs(self.Simple_width) * abs(self.Simple_length)

        if self.Simple_Type == 'Rhomb':
            box = layout.box()
            col = box.column(align=True)
            col.label(text=self.Simple_Type + " Options:")
            col.prop(self, "Simple_width")
            col.prop(self, "Simple_length")
            col.prop(self, "Simple_center")

            g = hypot(self.Simple_width / 2, self.Simple_length / 2)
            l = 4 * g
            s = self.Simple_width * self.Simple_length / 2

        if self.Simple_Type == 'Polygon':
            box = layout.box()
            col = box.column(align=True)
            col.label(text=self.Simple_Type + " Options:")
            col.prop(self, "Simple_sides")
            col.prop(self, "Simple_radius")

        if self.Simple_Type == 'Polygon_ab':
            box = layout.box()
            col = box.column(align=True)
            col.label(text="Polygon ab Options:")
            col.prop(self, "Simple_sides")
            col.prop(self, "Simple_a")
            col.prop(self, "Simple_b")

        if self.Simple_Type == 'Trapezoid':
            box = layout.box()
            col = box.column(align=True)
            col.label(text=self.Simple_Type + " Options:")
            col.prop(self, "Simple_a")
            col.prop(self, "Simple_b")
            col.prop(self, "Simple_h")

            box.prop(self, "Simple_center")
            g = hypot(self.Simple_h, (self.Simple_a - self.Simple_b) / 2)
            l = self.Simple_a + self.Simple_b + g * 2
            s = (abs(self.Simple_a) + abs(self.Simple_b)) / 2 * self.Simple_h

        row = layout.row()
        row.prop(self, "shape", expand=True)

        # output options
        col = layout.column()
        col.label(text="Output Curve Type:")
        col.row().prop(self, "outputType", expand=True)

        if self.outputType == 'NURBS':
            col.prop(self, "order_u")
        elif self.outputType == 'BEZIER':
            col.row().prop(self, 'handleType', expand=True)

        col = layout.column()
        col.row().prop(self, "use_cyclic_u", expand=True)

        col = layout.column()
        col.row().prop(self, "edit_mode", expand=True)

        col = layout.column()
        # AddObjectHelper props
        col.prop(self, "align")
        col.prop(self, "location")
        col.prop(self, "rotation")

        if l != 0 or s != 0:
            box = layout.box()
            box.label(text="Statistics:", icon="INFO")
        if l != 0:
            l_str = str(round(l, 4))
            box.label(text="Length: " + l_str)
        if s != 0:
            s_str = str(round(s, 4))
            box.label(text="Area: " + s_str)

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

    def execute(self, context):

        # turn off 'Enter Edit Mode'
        use_enter_edit_mode = bpy.context.preferences.edit.use_enter_edit_mode
        bpy.context.preferences.edit.use_enter_edit_mode = False

        # main function
        main(context, self, use_enter_edit_mode)

        if use_enter_edit_mode:
            bpy.ops.object.mode_set(mode='EDIT')

        # restore pre operator state
        bpy.context.preferences.edit.use_enter_edit_mode = use_enter_edit_mode

        if self.edit_mode:
            bpy.ops.object.mode_set(mode='EDIT')
        else:
            bpy.ops.object.mode_set(mode='OBJECT')

        return {'FINISHED'}

    def invoke(self, context, event):

        self.execute(context)

        return {'FINISHED'}
class IvyProperties(PropertyGroup):
    has_collider = BoolProperty(name='has valid collider',
                                default=False,
                                options={'HIDDEN'},
                                description='__internal__')
    added_as_ivy = BoolProperty(name='Added as Ivy',
                                default=False,
                                options={'HIDDEN'},
                                description='__internal__')

    # GENERAL PROPERTIES
    use_as_ivy = BoolProperty(
        name='Ivy',
        default=False,
        update=update_func,
        description='Update Ivy on frame change and when tweaking settings.\n'
        'Turn off when no updates are needed ot save CPU-cycles.\n'
        'WARNING: Destroys/Re-Creates Curve Geometry.')
    num_roots = IntProperty(
        name='Root Count',
        default=3,
        min=1,
        soft_min=1,
        update=update_func,
        # set=update_on_set, #no good implementation found
        description='Number of root branches to grow')
    root_area = FloatVectorProperty(
        name='Root Area',
        size=3,
        subtype='XYZ',
        default=(0.0, 0.0, 0.0),
        min=0,
        update=update_func,
        description='X-Y-Z radius of sphere from where the branches start')
    scale = FloatProperty(name='Scale',
                          default=0.05,
                          precision=3,
                          min=0.00001,
                          soft_min=0.00001,
                          update=update_func,
                          description='Ivy scale.\n'
                          'The desired distance between curve points.')
    seed = IntProperty(name='Seed',
                       default=1,
                       min=0,
                       soft_min=0,
                       update=update_func,
                       description='Random Seed')

    # COLLIDER
    collider = StringProperty(
        name='Collider',
        default='',
        update=update_func,
        description='Mesh Collider object Name.\n'
        'IMPORTANT: Apply Rotation of collider to work reliably.\n')
    collision_margin = FloatProperty(
        name='Collision Margin',
        default=0.03,
        min=0,
        soft_min=0,
        update=update_func,
        description='Distance to Colidder after Collision')

    # GROWTH VECTOR PROPS
    scale_random = FloatProperty(name='Random',
                                 default=0.40,
                                 min=0,
                                 soft_min=0,
                                 update=update_func,
                                 description='Random ivy scale.\n'
                                 'More random --> more random :)')
    scale_gravity = FloatProperty(name='Gravity',
                                  default=0.10,
                                  min=0,
                                  soft_min=0,
                                  update=update_func,
                                  description='Gravity influence.\n'
                                  'Zero disables gravity.')
    stiffness_gravity = FloatProperty(
        name='Gravity stiffness',
        default=0.5,
        min=0,
        soft_min=0,
        update=update_func,
        description=
        'Free floating distance until gravity is at full influence.\n'
        'Zero disables gravity.')
    scale_up = FloatProperty(
        name='Up',
        default=0.2,
        min=0,
        soft_min=0,
        update=update_func,
        description='Scale of up-vector force (in ivy-local-space)')
    stiffness_up = FloatProperty(
        name='Up stiffness',
        default=0,
        min=0,
        soft_min=0,
        update=update_func,
        description=
        'Free floating distance until Up-Force is at full influence.\n'
        'Zero disables stiffnes (uniform up force over all).')
    scale_straight = FloatProperty(name='Straight',
                                   default=1,
                                   min=0,
                                   soft_min=0,
                                   update=update_func,
                                   description='Straight ivy scale.\n'
                                   'The "straighter" the less wiggly.')

    # ADHESION
    scale_adhesion = FloatProperty(
        name='Adhesion Strength',
        default=1,
        min=0,
        soft_min=0,
        # max=1,
        update=update_func,
        description='Adhesion scale.\n'
        'The adhesion Properties can be very dependent on the\n'
        'character of the mesh (sharp corners, non.manifold, ...)')
    adhesion_angle_influence = FloatProperty(
        name='Adhesion angle',
        default=1,
        # min=0, soft_min=0,
        # max=1, soft_max=1,
        update=update_func,
        description='Deals mainly with corners and open collider mesh edges.\n'
        'At negative values adhesion is inverted on sharp corners/open boundaries.\n'
        'With positive values the branch is "pulled" around the corner.\n'
        'Still backfacing faces never apply adhesion to the branch.')
    adhesion_floating_influence = FloatProperty(
        name='Adhesion floating Influence',
        default=1,
        # min=-1, soft_min=-1,
        # max=1, soft_max=1,
        update=update_func,
        description='Above zero: increase adhesion at small floating length.\n'
        'Below zero: invert adhesion at small floating length (push from surface).\n'
        'zero: disabled\n'
        'Adhesion is scaled towards zero at Adhesion floating length')
    adhesion_floating_length = FloatProperty(
        name='Adhesion floating length',
        default=1,
        min=0,
        soft_min=0,
        # max=1, soft_max=1,
        update=update_func,
        description='Length setting for Adhesion floating Influence.\n'
        'The length of a branch from either the root or the last collision.')
    max_dist_adhesion = FloatProperty(
        name='Adhesion Max Distance',
        default=1,
        min=0,
        soft_min=0,
        update=update_func,
        description='Adhesion Max Distance. 0 disables.\n'
        'The maximum distance to the collider mesh where adhesion applies force.'
    )

    # ANIMATION
    animated = BoolProperty(name='Animated',
                            default=False,
                            update=update_func,
                            description='Use start-end for animation of ivy.')
    steps = IntProperty(name='Steps',
                        default=1,
                        min=1,
                        soft_min=1,
                        update=update_func,
                        description='Steps per Branch')
    start = IntProperty(
        name='Start Frame',
        default=1,
        # min=1, soft_min=0,
        update=update_func,
        description='Start Frame of Ivy growth')
    end = IntProperty(
        name='End Frame',
        default=100,
        # min=1, soft_min=0,
        update=update_func_endframe,
        description='End Frame of Ivy growth')

    # BRANCHPROPERTIES
    fixed_steps = IntProperty(
        name='Fixed Steps',
        default=100,
        min=1,
        soft_min=1,
        # update=update_func,
        update=non_animated_update,
        description='Steps of Ivy growth')
    steps_random_cutoff = FloatProperty(
        name='Random Cutoff',
        subtype='FACTOR',
        default=1,
        min=0,
        soft_min=0,
        max=1,
        soft_max=1,
        update=update_func,
        description='Probability of branches to reach final step-length.')
    cutoffamount = FloatProperty(name='Cutoff Amount',
                                 subtype='FACTOR',
                                 default=0.5,
                                 min=0,
                                 soft_min=0,
                                 max=1,
                                 soft_max=1,
                                 update=update_func,
                                 description='Factor of cutoff.')
Example #22
0
class SvProfileNodeMK2(bpy.types.Node, SverchCustomTreeNode):
    '''
    Triggers: svg-like 2d profiles
    Tooltip: Generate multiple parameteric 2d profiles using SVG like syntax

    SvProfileNode generates one or more profiles / elevation segments using;
    assignments, variables, and a string descriptor similar to SVG.

    This node expects simple input, or vectorized input.
    - sockets with no input are automatically 0, not None
    - The longest input array will be used to extend the shorter ones, using last value repeat.
    '''

    bl_idname = 'SvProfileNodeMK2'
    bl_label = 'Profile Parametric'
    bl_icon = 'SYNTAX_ON'

    SvLists = bpy.props.CollectionProperty(type=SvListGroup)
    SvSubLists = bpy.props.CollectionProperty(type=SvSublistGroup)

    def mode_change(self, context):
        if not (self.selected_axis == self.current_axis):
            self.label = self.selected_axis
            self.current_axis = self.selected_axis
            updateNode(self, context)

    x = BoolProperty(default=True)
    y = BoolProperty(default=True)

    axis_options = [("X", "X", "", 0), ("Y", "Y", "", 1), ("Z", "Z", "", 2)]

    current_axis = StringProperty(default='Z')

    knotsnames = StringProperty(name='knotsnames', default='')
    selected_axis = EnumProperty(
        items=axis_options,
        update=mode_change,
        name="Type of axis",
        description="offers basic axis output vectors X|Y|Z",
        default="Z")

    profile_file = StringProperty(default="", update=updateNode)
    filename = StringProperty(default="", update=updateNode)
    posxy = FloatVectorProperty(default=(0.0, 0.0), size=2)
    extended_parsing = BoolProperty(default=False)

    precision = IntProperty(
        name="Precision",
        min=0,
        max=10,
        default=8,
        update=updateNode,
        description=
        "decimal precision of coordinates when generating profile from selection"
    )

    curve_points_count = IntProperty(
        name="Curve points count",
        min=1,
        max=100,
        default=20,
        update=updateNode,
        description="Default number of points on curve segment")

    def draw_buttons(self, context, layout):
        col = layout.column(align=True)
        row = col.row()
        do_text = row.operator('node.sverchok_profilizer',
                               text='from selection')
        do_text.nodename = self.name
        do_text.treename = self.id_data.name
        do_text.x = self.x
        do_text.y = self.y
        row = col.row()
        row.prop(self, 'selected_axis', expand=True)
        row = col.row(align=True)
        # row.prop(self, "profile_file", text="")
        row.prop_search(self,
                        'filename',
                        bpy.data,
                        'texts',
                        text='',
                        icon='TEXT')

    def draw_buttons_ext(self, context, layout):
        row = layout.row(align=True)
        row.prop(self, "extended_parsing", text="extended parsing")
        layout.label("Profile Generator settings")
        layout.prop(self, "precision")
        layout.prop(self, "curve_points_count")
        row = layout.row(align=True)
        row.prop(self, "x", text='x-affect', expand=True)
        row.prop(self, "y", text='y-affect', expand=True)

    def sv_init(self, context):
        self.inputs.new('StringsSocket', "a", "a")
        self.inputs.new('StringsSocket', "b", "b")

        self.outputs.new('VerticesSocket', "Verts", "Verts")
        self.outputs.new('StringsSocket', "Edges", "Edges")
        self.outputs.new('VerticesSocket', "Knots", "Knots")
        self.outputs.new('StringsSocket', "KnotsNames", "KnotsNames")

    def adjust_inputs(self):
        '''
        takes care of adding new inputs until reaching 26,
        '''
        inputs = self.inputs
        if inputs[-1].is_linked:
            new_index = len(inputs)
            new_letter = idx_map.get(new_index, None)
            if new_letter:
                inputs.new('StringsSocket', new_letter, new_letter)
            else:
                print(
                    'this implementation goes up to 26 chars only, use SN or EK'
                )
                print('- or contact Dealga')
        elif not inputs[-2].is_linked:
            inputs.remove(inputs[-1])

    def update(self):
        '''
        update analyzes the state of the node and returns if the criteria to start processing
        are not met.
        '''

        # keeping the file internal for now.
        if not (self.filename in bpy.data.texts):
            return

        if not ('KnotsNames' in self.outputs):
            return

        elif len([1 for inputs in self.inputs if inputs.is_linked]) == 0:
            ''' must have at least one input... '''
            return

        self.adjust_inputs()

    def homogenize_input(self, segments, longest):
        '''
        edit segments in place, extend all to match length of longest
        '''
        for letter, letter_dict in segments.items():
            if letter_dict['length'] < longest:
                fullList(letter_dict['data'], longest)

    def meta_get(self, s_name, fallback, level):
        '''
        private function for the get_input function, accepts level 0..2
        - if socket has no links, then return fallback value
        - s_name can be an index instead of socket name
        '''
        inputs = self.inputs
        if inputs[s_name].is_linked:
            socket_in = inputs[s_name].sv_get()
            if level == 1:
                data = dataCorrect(socket_in)[0]
            elif level == 2:
                data = dataCorrect(socket_in)[0][0]
            else:
                data = dataCorrect(socket_in)
            return data
        else:
            return fallback

    def get_input(self):
        '''
        collect all input socket data, and track the longest sequence.
        '''
        segments = {}
        longest = 0
        for i, input_ in enumerate(self.inputs):
            letter = idx_map[i]
            ''' get socket data, or use a fallback '''
            data = self.meta_get(i, [0], 2)

            num_datapoints = len(data)
            segments[letter] = {'length': num_datapoints, 'data': data}

            if num_datapoints > longest:
                longest = num_datapoints

        return segments, longest

    def process(self):

        if not self.outputs[0].is_linked:
            return

        segments, longest = self.get_input()

        if longest < 1:
            print('logic error, longest < 1')
            return

        self.homogenize_input(segments, longest)
        full_result_verts = []
        full_result_edges = []

        for idx in range(longest):
            path_object = PathParser(self, segments, idx)
            vertices, edges = path_object.get_geometry()

            axis_fill = {
                'X': lambda coords: (0, coords[0], coords[1]),
                'Y': lambda coords: (coords[0], 0, coords[1]),
                'Z': lambda coords: (coords[0], coords[1], 0)
            }.get(self.current_axis)

            vertices = list(map(axis_fill, vertices))
            full_result_verts.append(vertices)
            full_result_edges.append(edges)

        if full_result_verts:
            outputs = self.outputs
            outputs['Verts'].sv_set(full_result_verts)

            if outputs['Edges'].is_linked:
                outputs['Edges'].sv_set(full_result_edges)
        try:
            knots = []
            for knot in self.SvLists['knots'].SvSubLists:
                knots.append([knot.SvX, knot.SvY, knot.SvZ])
            #print('test',knots)
            outputs[2].sv_set([knots])
        except:
            outputs[2].sv_set([])
        try:
            names = []
            for i, knot in enumerate(self.SvLists['knotsnames'].SvSubLists):
                names.append([knot.SvName])
            outputs[3].sv_set([names])
        except:
            outputs[3].sv_set([])

    def storage_set_data(self, storage):

        self.id_data.freeze(hard=True)
        self.SvLists.clear()

        strings_json = storage['profile_sublist_storage']

        out_points = json.loads(strings_json)['knots']
        self.SvLists.add().name = 'knots'
        for k in out_points:
            item = self.SvLists['knots'].SvSubLists.add()
            item.SvX, item.SvY, item.SvZ = k

        out_names = json.loads(strings_json)['knotsnames']
        self.SvLists.add().name = 'knotsnames'
        for k in out_names:
            item = self.SvLists['knotsnames'].SvSubLists.add()
            item.SvName = k

        self.id_data.unfreeze(hard=True)

    def storage_get_data(self, node_dict):
        local_storage = {'knots': [], 'knotsnames': []}

        for knot in self.SvLists['knots'].SvSubLists:
            local_storage['knots'].append([knot.SvX, knot.SvY, knot.SvZ])

        for outname in self.SvLists['knotsnames'].SvSubLists:
            local_storage['knotsnames'].append(outname.SvName)

        node_dict['profile_sublist_storage'] = json.dumps(local_storage,
                                                          sort_keys=True)
        node_dict['path_file'] = bpy.data.texts[self.filename].as_string()
class AddTerrainDiamondSquare(bpy.types.Operator):
    """Add a simple box mesh"""
    bl_idname = "mesh.terrain_diamond_square_add"
    bl_label = "Add Terrain (Diamond Square)"
    bl_options = {'REGISTER', 'UNDO'}

    width = FloatProperty(
            name="Width",
            description="Terrain Width",
            min=0.01, max=100.0,
            default=1.0,
            )
    height = FloatProperty(
            name="Height",
            description="Terrain Height",
            min=0.01, max=100.0,
            default=1.0,
            )
    depth = FloatProperty(
            name="Depth",
            description="Terrain Depth",
            min=0.01, max=100.0,
            default=1.0,
            )
    orderLevel = IntProperty(
            name="Order",
            description="Terrain Order",
            min=1, max=16,
            default=5,
            )
    seamless = BoolProperty(
            name="Seamless",
            description="Seamless Edges",
            default=False,
            )
    layers = BoolVectorProperty(
            name="Layers",
            description="Object Layers",
            size=20,
            options={'HIDDEN', 'SKIP_SAVE'},
            )

    # generic transform props
    view_align = BoolProperty(
            name="Align to View",
            default=False,
            )
    location = FloatVectorProperty(
            name="Location",
            subtype='TRANSLATION',
            )
    rotation = FloatVectorProperty(
            name="Rotation",
            subtype='EULER',
            )

    def execute(self, context):
        #self.report({'INFO'}, self.orderLevel)
        order = self.orderLevel
        size = 2**order+1

        verts = []
        for j in range(size):
            for i in range(size):
                verts.append([i*1.0/size,j*1.0/size,0.0])

        faces = []
        for j in range(size-1):
            for i in range(size-1):
                faces.append((j*size+i, j*size+i+1, (j+1)*size+i+1, (j+1)*size+i))

        if not self.seamless:
            for j in range(2):
                for i in range(2):
                    verts[j*(size-1)*size+i*(size-1)][2] = random.random()-0.5
        for k in range(order):
            step = 2**(order-k)
            halfstep = 2**(order-k-1)
            n = 2**k
            factor = 1.0/(2*n)
            self.report({'INFO'}, 'Iteration {0}, step: {1}, halfstep: {2}, n: {3}, factor: {4}'.format(k, step, halfstep, n, factor))
            for j in range(n):
                for i in range(n):
                    #self.report({'INFO'}, '\tVertex ({0}, {1})'.format(i, j))
                    r = 0
                    for J in range(2):
                        for I in range(2):
                            r += verts[(j+J)*step*size+(i+I)*step][2]
                    #self.report({'INFO'}, '\tVertex ({0}, {1})'.format(i, j))
                    r /= 4
                    r += (random.random()-0.5) * factor
                    verts[(j*step+halfstep)*size+i*step+halfstep][2] = r
            l = 1
            if self.seamless:
                l = 0
            for j in range(n+l):
                for i in range(n):
                    r = 0
                    N = 2
                    r += verts[j*step*size+i*step][2]
                    r += verts[j*step*size+(i+1)*step][2]
                    if j > 0:
                        r += verts[(j*step-halfstep)*size+i*step+halfstep][2]
                        N+=1
                    if j < n:
                        r += verts[(j*step+halfstep)*size+i*step+halfstep][2]
                        N+=1
                    r /= N
                    r += (random.random()-0.5) * factor
                    verts[j*step*size+i*step+halfstep][2] = r
            if self.seamless:
                for i in range(n):
                    verts[n*step*size+i*step+halfstep][2] = verts[i*step+halfstep][2]
            for j in range(n):
                for i in range(n+l):
                    r = 0
                    N = 2
                    r += verts[j*step*size+i*step][2]
                    r += verts[(j+1)*step*size+i*step][2]
                    if i > 0:
                        r += verts[(j*step+halfstep)*size+i*step-halfstep][2]
                        N+=1
                    if i < n:
                        r += verts[(j*step+halfstep)*size+i*step+halfstep][2]
                        N+=1
                    r /= N
                    r += (random.random()-0.5) * factor
                    verts[(j*step+halfstep)*size+i*step][2] = r
            if self.seamless:
                for j in range(n):
                    verts[(j*step+halfstep)*size+n*step][2] = verts[(j*step+halfstep)*size][2]

        # apply size
        for i, v in enumerate(verts):
            verts[i] = v[0] * self.width, v[1] * self.depth, v[2] * self.height

        mesh = bpy.data.meshes.new("Terrain")

        bm = bmesh.new()

        for v_co in verts:
            bm.verts.new(v_co)

        bm.verts.ensure_lookup_table()
        for f_idx in faces:
            bm.faces.new([bm.verts[i] for i in f_idx])

        bm.to_mesh(mesh)
        mesh.update()

        # add the mesh as an object into the scene with this utility module
        from bpy_extras import object_utils
        object_utils.object_data_add(context, mesh, operator=self)

        return {'FINISHED'}
class Properties(PropertyGroup):
    """
    Property group of the addon. Contanains all GUI controllers.
    """
    # Scene panel properties:
    scene_dimension: IntProperty(
        name="Scene dimension",
        description=
        "Scene is a 3D cube where the objects will apears. This can be used to normalize objects",
        default=1,
        min=1)

    # Model properties:
    input_model: StringProperty(name="Input file",
                                description="Choose a 3D model to import",
                                default="*.obj",
                                maxlen=1024,
                                subtype='FILE_PATH')

    normalize: BoolProperty(
        name="Normalize",
        description=
        "If checked, this will scale the model to fit into the scene cube, and will translate the object into center",
        default=True,
    )

    # Light properties:
    light_kind: EnumProperty(
        name="Kind",
        description="Choose the kind of light for the generation",
        items=
        [(Light.Kind.STATIC_LIGHT, 'Static Light',
          """Generate a static light at location specified in "Light location" property and with the color specified in "Light color" property""",
          '', 0),
         (Light.Kind.DYNAMIC_LIGHT, 'Dynamic Light',
          """Generate a dynamic light with random location but with the specified color in "Light color" property""",
          '', 1),
         (Light.Kind.RAINBOW_STATIC_LIGHT, 'Rainbow Static Light',
          """Generate a static light at location specified in "Light location" property and with random color""",
          '', 2),
         (Light.Kind.RAINBOW_DYNAMIC_LIGHT, 'Rainbow Dynamic Light',
          """Generate a dynamic light at random location and with random color""",
          '', 3)],
        default=Light.Kind.DYNAMIC_LIGHT)

    light_color: IntVectorProperty(
        name="Fixed color",
        description=
        "Specify a fixed light RGB color, with values from 0 to 255.",
        default=[0, 0, 0],
        min=0,
        max=255)

    light_range_location: FloatProperty(
        name="Range Location",
        description=
        """Max range for the generation of the location of light source. For example, if you choose 5 the light coordinates will be generated from -5 to 5""",
        default=5,
        min=0)

    light_energy: IntProperty(
        name="Max energy",
        description=
        """Max range for the generation of the energy of light source. For example, if you choose 5 the light energy will be generated from 0 to 5""",
        default=5,
        min=0)

    light_location: FloatVectorProperty(
        name="Location",
        description=
        """Specify fixed light location. If "Fixed Location" is not checked this will not apply""",
        default=[0.0, 0.0, 0.0],
        min=0.0)

    # Camera settings:
    camera_kind: EnumProperty(
        name="Kind",
        description="Choose the kind of light for the generation",
        items=[
            (Viewpoint.Kind.STATIC_CAMERA, 'Static',
             'Generate the camera in a fixed location', '', 0),
            (Viewpoint.Kind.DYNAMIC_CAMERA, 'Dynamic',
             'Generate the camera at random location', '', 1),
            (Viewpoint.Kind.OBJECT_PATH, 'Spheric path',
             'Generate the camera to follow the vertices produced in a sphere',
             '', 2)
        ],
        default=Viewpoint.Kind.DYNAMIC_CAMERA)

    camera_location: FloatVectorProperty(
        name="Camera Location",
        description="""Specify fixed camera location.""",
        default=[0.0, 0.0, 0.0],
        min=0.0)

    camera_range_location: FloatProperty(
        name="Range Location",
        description=
        """Max range for the generation of the location of the camera. For example, if you choose 5 the camera coordinates will be generated from -5 to 5""",
        default=5,
        min=0)

    amount_shoots: IntProperty(
        name="Shoots",
        description=
        """Amount of shoots to make for rendering. 100 means this camara will render
        100 images for each style selected in 'RenderManager Settings'. In case "Spheric path"
        was selected, this number will be equal the "Vertical Segments" times the 
        "Horizontal Segments" """,
        default=100,
        min=0,
    )

    camera_size: FloatProperty(
        name="Sphere size",
        description=
        """Set a value to the diameter in case "Spheric path" was selected""",
        default=2,
        min=0)

    camera_v_segments: IntProperty(
        name="Vertical segments",
        description="Amount of vertical divisions of the sphere",
        default=10,
        min=0)

    camera_h_segments: IntProperty(
        name="Horizontal segments",
        description="Amount of horizontal divisions of the sphere",
        default=10,
        min=0)

    render_resolution_x: IntProperty(
        name="Width",
        description="Sets the width of the output images in pixels",
        default=128,
        min=0)

    render_resolution_y: IntProperty(
        name="Height",
        description="Sets the height of the output images in pixels",
        default=128,
        min=0)

    render_output_folder_path: StringProperty(
        name="Output directory",
        description="Choose a directory where output will appears",
        default="",
        maxlen=1024,
        subtype='DIR_PATH')

    # Json file input
    input_presets_file: StringProperty(
        name="Input config file",
        description="Configuration file for scene creation and customization",
        default="*.json",
        maxlen=1024,
        subtype='FILE_PATH')

    # Generator panel settings
    choice_render: EnumProperty(
        name="Config from",
        description=
        "Choose the generator input, if you choose GUI the generator will take the established properties, if you choose FILE, the generator will take the properties of a file in *.json format",
        items=[('GUI', 'Gui', '', '', 0), ('FILE', 'File', '', '', 1)],
        default='GUI')
class archipack_reference_point(PropertyGroup):
    location_2d = FloatVectorProperty(
        subtype='XYZ',
        name="position 2d",
        default=Vector((0, 0, 0))
        )
    location_3d = FloatVectorProperty(
        subtype='XYZ',
        name="position 3d",
        default=Vector((0, 0, 0))
        )
    symbol_scale = FloatProperty(
        name="Screen scale",
        default=1,
        min=0.01,
        update=update)

    @classmethod
    def filter(cls, o):
        """
            Filter object with this class in data
            return
            True when object contains this datablock
            False otherwhise
            usage:
            class_name.filter(object) from outside world
            self.__class__.filter(object) from instance
        """
        try:
            return cls.__name__ in o
        except:
            pass
        return False

    @classmethod
    def datablock(cls, o):
        """
            Retrieve datablock from base object
            return
                datablock when found
                None when not found
            usage:
                class_name.datablock(object) from outside world
                self.__class__.datablock(object) from instance
        """
        try:
            return getattr(o, cls.__name__)[0]
        except:
            pass
        return None

    def update(self, context):

        o = context.active_object

        if self.datablock(o) != self:
            return

        s = self.symbol_scale
        verts = [(s * x, s * y, s * z) for x, y, z in [
            (-0.25, 0.25, 0.0), (0.25, 0.25, 0.0), (-0.25, -0.25, 0.0), (0.25, -0.25, 0.0),
            (0.0, 0.0, 0.487), (-0.107, 0.107, 0.216), (0.108, 0.107, 0.216), (-0.107, -0.107, 0.216),
            (0.108, -0.107, 0.216), (-0.05, 0.05, 0.5), (0.05, 0.05, 0.5), (0.05, -0.05, 0.5),
            (-0.05, -0.05, 0.5), (-0.193, 0.193, 0.0), (0.193, 0.193, 0.0), (0.193, -0.193, 0.0),
            (-0.193, -0.193, 0.0), (0.0, 0.0, 0.8), (0.0, 0.8, -0.0), (0.0, 0.0, -0.0),
            (0.0, 0.0, 0.0), (0.05, 0.05, 0.674), (-0.05, 0.674, -0.05), (0.0, 0.8, -0.0),
            (-0.05, -0.05, 0.674), (-0.05, 0.674, 0.05), (0.05, 0.674, -0.05), (-0.129, 0.129, 0.162),
            (0.129, 0.129, 0.162), (-0.129, -0.129, 0.162), (0.129, -0.129, 0.162), (0.0, 0.0, 0.8),
            (-0.05, 0.05, 0.674), (0.05, -0.05, 0.674), (0.05, 0.674, 0.05), (0.8, -0.0, -0.0),
            (0.0, -0.0, -0.0), (0.674, 0.05, -0.05), (0.8, -0.0, -0.0), (0.674, 0.05, 0.05),
            (0.674, -0.05, -0.05), (0.674, -0.05, 0.05)]]

        edges = [(1, 0), (0, 9), (9, 10), (10, 1), (3, 1), (10, 11),
            (11, 3), (2, 3), (11, 12), (12, 2), (0, 2), (12, 9),
            (6, 5), (8, 6), (7, 8), (5, 7), (17, 24), (17, 20),
            (18, 25), (18, 19), (13, 14), (14, 15), (15, 16), (16, 13),
            (4, 6), (15, 30), (17, 21), (26, 22), (23, 22), (23, 34),
            (18, 26), (28, 27), (30, 28), (29, 30), (27, 29), (14, 28),
            (13, 27), (16, 29), (4, 7), (4, 8), (4, 5), (31, 33),
            (31, 32), (21, 32), (24, 32), (24, 33), (21, 33), (25, 22),
            (25, 34), (26, 34), (35, 39), (35, 36), (40, 37), (38, 37),
            (38, 41), (35, 40), (39, 37), (39, 41), (40, 41)]

        bm = bmed._start(context, o)
        bm.clear()
        for v in verts:
            bm.verts.new(v)
        bm.verts.ensure_lookup_table()
        for ed in edges:
            bm.edges.new((bm.verts[ed[0]], bm.verts[ed[1]]))
        bmed._end(bm, o)
class AddOctahedron(bpy.types.Operator):
    """Add a subdivided octahedron mesh"""
    bl_idname = "mesh.primitive_octahedron_add"
    bl_label = "Add Octahedron"
    bl_options = {'REGISTER', 'UNDO'}

    subdivisions: IntProperty(
        name="Subdivisions",
        description="Number of subdivisions",
        min=2,
        max=32,
        default=8,
    )
    spherize: BoolProperty(
        name="Spherize",
        description="Normalize point positions using L2 norm",
        default=False)

    # generic transform props
    align_items = (('WORLD', "World", "Align the new object to the world"),
                   ('VIEW', "View", "Align the new object to the view"),
                   ('CURSOR', "3D Cursor",
                    "Use the 3D cursor orientation for the new object"))
    align: EnumProperty(
        name="Align",
        items=align_items,
        default='WORLD',
        update=AddObjectHelper.align_update_callback,
    )
    location: FloatVectorProperty(
        name="Location",
        subtype='TRANSLATION',
    )
    rotation: FloatVectorProperty(
        name="Rotation",
        subtype='EULER',
    )

    def execute(self, context):

        verts_loc, faces = add_box(
            self.subdivisions,
            self.spherize,
        )

        mesh = bpy.data.meshes.new("Octahedron")

        bm = bmesh.new()

        for v_co in verts_loc:
            bm.verts.new(v_co)

        bm.verts.ensure_lookup_table()
        for f_idx in faces:
            bm.faces.new([bm.verts[i] for i in f_idx])

        bm.to_mesh(mesh)
        mesh.update()

        # add the mesh as an object into the scene with this utility module
        from bpy_extras import object_utils
        object_utils.object_data_add(context, mesh, operator=self)

        return {'FINISHED'}
Example #27
0
class SvScriptNodeLite(bpy.types.Node, SverchCustomTreeNode, SvAnimatableNode):
    ''' snl SN Lite /// a lite version of SN '''

    bl_idname = 'SvScriptNodeLite'
    bl_label = 'Scripted Node Lite'
    bl_icon = 'SCRIPTPLUGINS'

    def custom_enum_func(self, context):
        ND = self.node_dict.get(hash(self))
        if ND:
            enum_list = ND['sockets']['custom_enum']
            if enum_list:
                return [(ce, ce, '', idx) for idx, ce in enumerate(enum_list)]

        return [("A", "A", '', 0), ("B", "B", '', 1)]

    def custom_callback(self, context, operator):
        ND = self.node_dict.get(hash(self))
        if ND:
            ND['sockets']['callbacks'][operator.cb_name](self, context)

    def make_operator(self, new_func_name, force=False):
        ND = self.node_dict.get(hash(self))
        if ND:
            callbacks = ND['sockets']['callbacks']
            if not (new_func_name in callbacks) or force:
                # here node refers to an ast node (a syntax tree node), not a node tree node
                ast_node = self.get_node_from_function_name(new_func_name)
                slice_begin, slice_end = ast_node.body[
                    0].lineno - 1, ast_node.body[-1].lineno
                code = '\n'.join(
                    self.script_str.split('\n')[slice_begin - 1:slice_end + 1])

                exec(code, locals(), locals())
                callbacks[new_func_name] = locals()[new_func_name]

    script_name: StringProperty()
    script_str: StringProperty()
    node_dict = {}

    halt_updates: BoolProperty(name="snlite halting token")

    def updateNode2(self, context):
        if not self.halt_updates:
            updateNode(self, context)

    int_list: IntVectorProperty(name='int_list',
                                description="Integer list",
                                default=defaults,
                                size=32,
                                update=updateNode2)

    float_list: FloatVectorProperty(name='float_list',
                                    description="Float list",
                                    default=defaults,
                                    size=32,
                                    update=updateNode2)

    mode_options = [
        ("To_TextBlok", "To TextBlok", "", 0),
        ("To_Node", "To Node", "", 1),
    ]

    selected_mode: bpy.props.EnumProperty(
        items=mode_options,
        description=
        "load the template directly to the node or add to textblocks",
        default="To_Node",
        update=updateNode)

    inject_params: BoolProperty()
    injected_state: BoolProperty(default=False)
    user_filename: StringProperty(update=updateNode)
    n_id: StringProperty(default='')

    custom_enum: bpy.props.EnumProperty(items=custom_enum_func,
                                        description="custom enum",
                                        update=updateNode)

    snlite_raise_exception: BoolProperty(name="raise exception")

    def draw_label(self):
        if self.script_name:
            return 'SN: ' + self.script_name
        else:
            return self.bl_label

    def add_or_update_sockets(self, k, v):
        '''
        'sockets' are either 'self.inputs' or 'self.outputs'
        '''
        sockets = getattr(self, k)

        for idx, (socket_description) in enumerate(v):
            if socket_description is UNPARSABLE:
                print(socket_description, idx, 'was unparsable')
                return

            if len(sockets) > 0 and idx in set(range(len(sockets))):
                if not are_matched(sockets[idx], socket_description):
                    sockets[idx].replace_socket(*socket_description[:2])
            else:
                sockets.new(*socket_description[:2])

        return True

    def add_props_to_sockets(self, socket_info):

        self.id_data.freeze(hard=True)
        try:
            self.halt_updates = True

            for idx, (socket_description) in enumerate(socket_info['inputs']):
                dval = socket_description[2]
                print(idx, socket_description)

                s = self.inputs[idx]

                if isinstance(dval, float):
                    s.prop_type = "float_list"
                    s.prop_index = idx
                    self.float_list[idx] = self.float_list[
                        idx] or dval  # pick up current if not zero

                elif isinstance(dval, int):
                    s.prop_type = "int_list"
                    s.prop_index = idx
                    self.int_list[idx] = self.int_list[idx] or dval
        except:
            print('some failure in the add_props_to_sockets function. ouch.')

        self.halt_updates = False
        self.id_data.unfreeze(hard=True)

    def flush_excess_sockets(self, k, v):
        sockets = getattr(self, k)
        if len(sockets) > len(v):
            num_to_remove = (len(sockets) - len(v))
            for _ in range(num_to_remove):
                sockets.remove(sockets[-1])

    def update_sockets(self):
        socket_info = parse_sockets(self)
        if not socket_info['inputs']:
            return

        for k, v in socket_info.items():
            if not (k in {'inputs', 'outputs'}):
                continue

            if not self.add_or_update_sockets(k, v):
                print('failed to load sockets for ', k)
                return

            self.flush_excess_sockets(k, v)

        self.add_props_to_sockets(socket_info)

        self.node_dict[hash(self)] = {}
        self.node_dict[hash(self)]['sockets'] = socket_info

        return True

    def sv_init(self, context):
        self.use_custom_color = False

    def load(self):
        if not self.script_name:
            return

        text = self.get_bpy_data_from_name(self.script_name, bpy.data.texts)
        if text:
            self.script_str = text.as_string()
        else:
            print(
                f'bpy.data.texts not read yet, self.script_name="{self.script_name}"'
            )
            if self.script_str:
                print('but script loaded locally anyway.')

        if self.update_sockets():
            self.injected_state = False
            self.process()

    def nuke_me(self):
        self.script_str = ''
        self.script_name = ''
        self.node_dict[hash(self)] = {}
        for socket_set in [self.inputs, self.outputs]:
            socket_set.clear()

    def sv_copy(self, node):
        self.node_dict[hash(self)] = {}
        self.load()

    def process(self):
        if not all([self.script_name, self.script_str]):
            return
        self.process_script()

    def make_new_locals(self):

        # make .blend reload event work, without this the self.node_dict is empty.
        if not self.node_dict:
            # self.load()
            self.injected_state = False
            self.update_sockets()

        # make inputs local, do function with inputs, return outputs if present
        ND = self.node_dict.get(hash(self))
        if not ND:
            print('hash invalidated')
            self.injected_state = False
            self.update_sockets()
            ND = self.node_dict.get(hash(self))
            self.load()

        socket_info = ND['sockets']
        local_dict = {}
        for idx, s in enumerate(self.inputs):
            sock_desc = socket_info['inputs'][idx]

            if s.is_linked:
                val = s.sv_get(default=[[]])
                if sock_desc[3]:
                    val = {0: val, 1: val[0], 2: val[0][0]}.get(sock_desc[3])
            else:
                val = sock_desc[2]
                if isinstance(val, (int, float)):
                    # extra pussyfooting for the load sequence.
                    t = s.sv_get()
                    if t and t[0] and len(t[0]) > 0:
                        val = t[0][0]

            local_dict[s.name] = val

        return local_dict

    def get_node_from_function_name(self, func_name):
        """
        this seems to get enough info for a snlite stateful setup function.

        """
        tree = ast.parse(self.script_str)
        for node in tree.body:
            if isinstance(node, ast.FunctionDef) and node.name == func_name:
                return node

    def get_setup_code(self):
        ast_node = self.get_node_from_function_name('setup')
        if ast_node:
            begin_setup = ast_node.body[0].lineno - 1
            end_setup = ast_node.body[-1].lineno
            code = '\n'.join(
                self.script_str.split('\n')[begin_setup:end_setup])
            return 'def setup():\n\n' + code + '\n    return locals()\n'

    def get_ui_code(self):
        ast_node = self.get_node_from_function_name('ui')
        if ast_node:
            begin_setup = ast_node.body[0].lineno - 1
            end_setup = ast_node.body[-1].lineno
            code = '\n'.join(
                self.script_str.split('\n')[begin_setup:end_setup])
            return 'def ui(self, context, layout):\n\n' + code + '\n\n'

    def inject_state(self, local_variables):
        setup_result = self.get_setup_code()
        if setup_result:
            exec(setup_result, local_variables, local_variables)
            setup_locals = local_variables.get('setup')()
            local_variables.update(setup_locals)
            local_variables['socket_info']['setup_state'] = setup_locals
            self.injected_state = True

    def inject_draw_buttons(self, local_variables):
        draw_ui_result = self.get_ui_code()
        if draw_ui_result:
            exec(draw_ui_result, local_variables, local_variables)
            ui_func = local_variables.get('ui')
            local_variables['socket_info']['drawfunc'] = ui_func

    def process_script(self):
        __local__dict__ = self.make_new_locals()
        locals().update(__local__dict__)
        locals().update({
            'vectorize': vectorize,
            'bpy': bpy,
            'ddir': ddir,
            'bmesh_from_pydata': bmesh_from_pydata,
            'pydata_from_bmesh': pydata_from_bmesh
        })

        for output in self.outputs:
            locals().update({output.name: []})

        try:
            socket_info = self.node_dict[hash(self)]['sockets']

            # inject once!
            if not self.injected_state:
                self.inject_state(locals())
                self.inject_draw_buttons(locals())
            else:
                locals().update(socket_info['setup_state'])

            if self.inject_params:
                locals().update({
                    'parameters':
                    [__local__dict__.get(s.name) for s in self.inputs]
                })

            exec(self.script_str, locals(), locals())

            for idx, _socket in enumerate(self.outputs):
                vals = locals()[_socket.name]
                self.outputs[idx].sv_set(vals)

            set_autocolor(self, True, READY_COLOR)

        except Exception as err:

            print("Unexpected error:", sys.exc_info()[0])
            exc_type, exc_value, exc_traceback = sys.exc_info()
            lineno = traceback.extract_tb(exc_traceback)[-1][1]
            print('on line: ', lineno)
            show = traceback.print_exception
            show(exc_type, exc_value, exc_traceback, limit=2, file=sys.stdout)
            if hasattr(
                    self,
                    "snlite_raise_exception") and self.snlite_raise_exception:
                raise  #   SNLITE_EXCEPTION(sys.exc_info()[2]) from err

    def custom_draw(self, context, layout):
        tk = self.node_dict.get(hash(self))
        if not tk or not tk.get('sockets'):
            return

        snlite_info = tk['sockets']
        if snlite_info:

            # snlite supplied custom file handler solution
            fh = snlite_info.get('display_file_handler')
            if fh:
                layout.prop_search(self,
                                   'user_filename',
                                   bpy.data,
                                   'texts',
                                   text='filename')

            # user supplied custom draw function
            f = snlite_info.get('drawfunc')
            if f:
                f(self, context, layout)

    def draw_buttons(self, context, layout):
        sn_callback = 'node.scriptlite_ui_callback'

        if not self.script_str:
            col = layout.column(align=True)
            row = col.row()
            row.prop_search(self,
                            'script_name',
                            bpy.data,
                            'texts',
                            text='',
                            icon='TEXT')
            row.operator(sn_callback, text='', icon='PLUGIN').fn_name = 'load'
        else:
            self.draw_animatable_buttons(layout, icon_only=True)
            col = layout.column(align=True)
            row = col.row()
            row.operator(sn_callback, text='Reload').fn_name = 'load'
            row.operator(sn_callback, text='Clear').fn_name = 'nuke_me'

        self.custom_draw(context, layout)

    def draw_buttons_ext(self, _, layout):
        row = layout.row()
        row.prop(self, 'selected_mode', expand=True)
        col = layout.column()
        col.menu(SV_MT_ScriptNodeLitePyMenu.bl_idname)

        box = layout.box()
        r = box.row()
        r.label(text="extra snlite features")
        if hasattr(self, "snlite_raise_exception"):
            r = box.row()
            r.prop(self,
                   "snlite_raise_exception",
                   toggle=True,
                   text="raise errors to tree level")

    # ---- IO Json storage is handled in this node locally ----

    def storage_set_data(self, node_ref):

        texts = bpy.data.texts

        data_list = node_ref.get('snlite_ui')
        if data_list:
            # self.node_dict[hash(self)]['sockets']['snlite_ui'] = ui_elements
            for data_json_str in data_list:
                data_dict = json.loads(data_json_str)
                if data_dict['bl_idname'] == 'ShaderNodeRGBCurve':
                    set_rgb_curve(data_dict)

        includes = node_ref.get('includes')
        if includes:
            for include_name, include_content in includes.items():
                new_text = texts.new(include_name)
                new_text.from_string(include_content)

                if include_name == new_text.name:
                    continue

                print('| in', node_ref.name, 'the importer encountered')
                print('| an include called', include_name, '. While trying')
                print('| to write this file to bpy.data.texts another file')
                print('| with the same name was encountered. The importer')
                print('| automatically made a datablock called', new_text.name)

    def storage_get_data(self, node_dict):

        # this check and function call is needed to allow loading node trees directly
        # from a .blend in order to export them via create_dict_of_tree
        if not self.node_dict or not self.node_dict.get(hash(self)):
            self.make_new_locals()

        storage = self.node_dict[hash(self)]['sockets']

        ui_info = storage['snlite_ui']
        node_dict['snlite_ui'] = []
        print(ui_info)
        for _, info in enumerate(ui_info):
            mat_name = info['mat_name']
            node_name = info['node_name']
            bl_idname = info['bl_idname']
            if bl_idname == 'ShaderNodeRGBCurve':
                data = get_rgb_curve(mat_name, node_name)
                print(data)
                data_json_str = json.dumps(data)
                node_dict['snlite_ui'].append(data_json_str)

        includes = storage['includes']
        if includes:
            node_dict['includes'] = {}
            for k, v in includes.items():
                node_dict['includes'][k] = v
Example #28
0
class ScArrayMod(Node, ScModifierNode):
    bl_idname = "ScArrayMod"
    bl_label = "Array Modifier"

    in_fit_type: EnumProperty(items=[("FIXED_COUNT", "Fixed Count", ""),
                                     ("FIT_LENGTH", "Fit Length", ""),
                                     ("FIT_CURVE", "Fit Curve", "")],
                              default="FIXED_COUNT",
                              update=ScNode.update_value)
    in_count: IntProperty(default=2,
                          min=1,
                          max=1000,
                          update=ScNode.update_value)
    in_fit_length: FloatProperty(default=0.0,
                                 min=0.0,
                                 update=ScNode.update_value)
    in_curve: PointerProperty(type=bpy.types.Object,
                              update=ScNode.update_value)
    in_use_constant_offset: BoolProperty(update=ScNode.update_value)
    in_constant_offset_displace: FloatVectorProperty(
        update=ScNode.update_value)
    in_use_merge_vertices: BoolProperty(name="Merge",
                                        update=ScNode.update_value)
    in_use_merge_vertices_cap: BoolProperty(update=ScNode.update_value)
    in_merge_threshold: FloatProperty(default=0.01,
                                      min=0.0,
                                      max=1.0,
                                      update=ScNode.update_value)
    in_use_relative_offset: BoolProperty(default=True,
                                         update=ScNode.update_value)
    in_relative_offset_displace: FloatVectorProperty(
        default=(1.0, 0.0, 0.0), update=ScNode.update_value)
    in_use_object_offset: BoolProperty(update=ScNode.update_value)
    in_offset_object: PointerProperty(type=bpy.types.Object,
                                      update=ScNode.update_value)
    in_offset_u: FloatProperty(default=0.0,
                               min=-1,
                               max=1,
                               update=ScNode.update_value)
    in_offset_v: FloatProperty(default=0.0,
                               min=-1,
                               max=1,
                               update=ScNode.update_value)
    in_start_cap: PointerProperty(type=bpy.types.Object,
                                  update=ScNode.update_value)
    in_end_cap: PointerProperty(type=bpy.types.Object,
                                update=ScNode.update_value)

    def init(self, context):
        super().init(context)
        self.prop_mod_type = "ARRAY"
        self.inputs.new("ScNodeSocketString",
                        "Fit Type").init("in_fit_type", True)
        self.inputs.new("ScNodeSocketNumber", "Count").init("in_count", True)
        self.inputs.new("ScNodeSocketNumber",
                        "Length").init("in_fit_length", True)
        self.inputs.new("ScNodeSocketObject", "Curve").init("in_curve")
        self.inputs.new("ScNodeSocketBool",
                        "Use Constant Offset").init("in_use_constant_offset")
        self.inputs.new("ScNodeSocketVector",
                        "Constant Offset").init("in_constant_offset_displace")
        self.inputs.new("ScNodeSocketBool",
                        "Use Relative Offset").init("in_use_relative_offset")
        self.inputs.new("ScNodeSocketVector",
                        "Relative Offset").init("in_relative_offset_displace",
                                                True)
        self.inputs.new("ScNodeSocketBool",
                        "Use Object Offset").init("in_use_object_offset")
        self.inputs.new("ScNodeSocketObject",
                        "Object Offset").init("in_offset_object")
        self.inputs.new("ScNodeSocketBool",
                        "Merge").init("in_use_merge_vertices")
        self.inputs.new("ScNodeSocketBool",
                        "First Last").init("in_use_merge_vertices_cap")
        self.inputs.new("ScNodeSocketNumber",
                        "Distance").init("in_merge_threshold")
        self.inputs.new("ScNodeSocketNumber", "U Offset").init("in_offset_u")
        self.inputs.new("ScNodeSocketNumber", "V Offset").init("in_offset_v")
        self.inputs.new("ScNodeSocketObject", "End Cap").init("in_start_cap")
        self.inputs.new("ScNodeSocketObject", "Start Cap").init("in_end_cap")

    def error_condition(self):
        return (super().error_condition()
                or (not self.inputs["Fit Type"].default_value
                    in ["FIXED_COUNT", "FIT_LENGTH", "FIT_CURVE"])
                or (int(self.inputs["Count"].default_value) < 1
                    or int(self.inputs["Count"].default_value) > 1000)
                or self.inputs["Length"].default_value < 0.0
                or (self.inputs["Distance"].default_value < 0.0
                    or self.inputs["Distance"].default_value > 1.0)
                or (self.inputs["U Offset"].default_value < -1.0
                    or self.inputs["U Offset"].default_value > 1.0)
                or (self.inputs["V Offset"].default_value < -1.0
                    or self.inputs["V Offset"].default_value > 1.0))

    def functionality(self):
        bpy.context.object.modifiers[
            self.
            prop_mod_name].fit_type = self.inputs["Fit Type"].default_value
        bpy.context.object.modifiers[self.prop_mod_name].count = int(
            self.inputs["Count"].default_value)
        bpy.context.object.modifiers[
            self.
            prop_mod_name].fit_length = self.inputs["Length"].default_value
        bpy.context.object.modifiers[
            self.prop_mod_name].curve = self.inputs["Curve"].default_value
        bpy.context.object.modifiers[
            self.prop_mod_name].use_constant_offset = self.inputs[
                "Use Constant Offset"].default_value
        bpy.context.object.modifiers[
            self.prop_mod_name].constant_offset_displace = self.inputs[
                "Constant Offset"].default_value
        bpy.context.object.modifiers[
            self.prop_mod_name].use_merge_vertices = self.inputs[
                "Merge"].default_value
        bpy.context.object.modifiers[
            self.prop_mod_name].use_merge_vertices_cap = self.inputs[
                "First Last"].default_value
        bpy.context.object.modifiers[
            self.prop_mod_name].merge_threshold = self.inputs[
                "Distance"].default_value
        bpy.context.object.modifiers[
            self.prop_mod_name].use_relative_offset = self.inputs[
                "Use Relative Offset"].default_value
        bpy.context.object.modifiers[
            self.prop_mod_name].relative_offset_displace = self.inputs[
                "Relative Offset"].default_value
        bpy.context.object.modifiers[
            self.prop_mod_name].use_object_offset = self.inputs[
                "Use Object Offset"].default_value
        bpy.context.object.modifiers[
            self.prop_mod_name].offset_object = self.inputs[
                "Object Offset"].default_value
        bpy.context.object.modifiers[
            self.
            prop_mod_name].offset_u = self.inputs["U Offset"].default_value
        bpy.context.object.modifiers[
            self.
            prop_mod_name].offset_v = self.inputs["V Offset"].default_value
        bpy.context.object.modifiers[
            self.
            prop_mod_name].start_cap = self.inputs["End Cap"].default_value
        bpy.context.object.modifiers[self.prop_mod_name].end_cap = self.inputs[
            "Start Cap"].default_value
class OBJECT_OT_add_wire_skin_mirrored(Operator, AddObjectHelper):
    """Create a new Mesh Object"""
    bl_idname = "mesh.add_wire_skin_mirrored"
    bl_label = "Add Wire Skin Mirrored"
    bl_options = {'REGISTER', 'UNDO'}

    scale: FloatVectorProperty(
        name="scale",
        default=(1.0, 1.0, 1.0),
        subtype='TRANSLATION',
        description="scaling",
    )

    def execute(self, context):

        #add_object(self, context)
        bpy.ops.mesh.primitive_vert_add()
        bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
        bpy.ops.object.select_all(action='DESELECT')
        ob = bpy.context.view_layer.objects.active
        ob.select_set(state=True)
        bpy.context.view_layer.objects.active = ob
        skin_mod = ob.modifiers.new(name='Skin', type='SKIN')
        mirror_mod = ob.modifiers.new(name='Mirror', type='MIRROR')
        mirror_mod.use_bisect_axis[0] = True
        mirror_mod.use_clip = False
        mirror_mod.use_mirror_merge = True
        bpy.context.object.modifiers["Mirror"].use_mirror_merge = True

        bpy.ops.object.mode_set(mode='EDIT', toggle=False)
        bpy.ops.mesh.select_mode(use_extend=False,
                                 use_expand=False,
                                 type='VERT')
        bpy.ops.mesh.select_all(action='DESELECT')
        bpy.ops.mesh.select_all(action='SELECT')
        bpy.ops.mesh.extrude_region_move(MESH_OT_extrude_region={
            "use_normal_flip": False,
            "mirror": False
        },
                                         TRANSFORM_OT_translate={
                                             "value": (0, 0, 1),
                                             "orient_type":
                                             'LOCAL',
                                             "orient_matrix":
                                             ((1, 0, 0), (0, 1, 0), (0, 0, 1)),
                                             "orient_matrix_type":
                                             'LOCAL',
                                             "constraint_axis":
                                             (False, False, True),
                                             "mirror":
                                             False,
                                             "use_proportional_edit":
                                             False,
                                             "proportional_edit_falloff":
                                             'INVERSE_SQUARE',
                                             "proportional_size":
                                             1.21542,
                                             "use_proportional_connected":
                                             False,
                                             "use_proportional_projected":
                                             False,
                                             "snap":
                                             False,
                                             "snap_target":
                                             'CLOSEST',
                                             "snap_point": (0, 0, 0),
                                             "snap_align":
                                             False,
                                             "snap_normal": (0, 0, 0),
                                             "gpencil_strokes":
                                             False,
                                             "cursor_transform":
                                             False,
                                             "texture_space":
                                             False,
                                             "remove_on_cancel":
                                             False,
                                             "release_confirm":
                                             False,
                                             "use_accurate":
                                             False
                                         })

        my_areas = bpy.context.workspace.screens[0].areas
        for area in my_areas:
            for space in area.spaces:
                if space.type == 'VIEW_3D':
                    space.shading.type = 'SOLID'

                    space.shading.type = 'SOLID'
                    space.shading.show_xray = True
                    space.shading.xray_alpha = 1
        bpy.context.space_data.overlay.show_wireframes = False
        layer = bpy.context.view_layer
        layer.update()

        return {'FINISHED'}
Example #30
0
class FSimProps(bpy.types.PropertyGroup):

    #State Variables
    sVelocity = FloatVectorProperty(name="Velocity",
                                    description="Speed",
                                    subtype='XYZ',
                                    default=(0.0, 0.0, 0.0),
                                    min=-5.0,
                                    max=5.0)
    sEffort = FloatProperty(name="Effort",
                            description="The effort going into swimming",
                            default=1.0,
                            min=0)
    sTurn = FloatProperty(
        name="Turn",
        description="The intent to go left of right (positive is right)",
        default=0.0)
    sRise = FloatProperty(
        name="Rise",
        description="The intent to go up or down (positive is up",
        default=0.0)
    sFreq = FloatProperty(
        name="Frequency",
        description="Current frequency of tail movement in frames per cycle",
        default=0.0)
    sTailAngle = FloatProperty(name="Tail Angle",
                               description="Current max tail angle in degrees",
                               default=0.0)
    sTailAngleOffset = FloatProperty(
        name="Tail Angle Offset",
        description="Offset angle for turning in degrees",
        default=0.0)

    #Property declaration
    pMass = FloatProperty(name="Mass",
                          description="Total Mass",
                          default=30.0,
                          min=0,
                          max=3000.0)
    pDrag = FloatProperty(name="Drag",
                          description="Total Drag",
                          default=8.0,
                          min=0,
                          max=3000.0)
    pPower = FloatProperty(
        name="Power",
        description="Forward force for given tail fin speed and angle",
        default=1.0,
        min=0)
    pMaxFreq = FloatProperty(
        name="Stroke Period",
        description="Maximum frequency of tail movement in frames per cycle",
        default=15.0)
    pEffortGain = FloatProperty(
        name="Effort Gain",
        description=
        "The amount of effort required for a change in distance to target",
        default=0.5,
        min=0.0)
    pEffortIntegral = FloatProperty(
        name="Effort Integral",
        description=
        "The amount of effort required for a continuing distance to target",
        default=0.5,
        min=0.0)
    pEffortRamp = FloatProperty(
        name="Effort Ramp",
        description="First Order factor for ramping up effort",
        default=0.2,
        min=0.0,
        max=0.6)
    pAngularDrag = FloatProperty(
        name="AngularDrag",
        description="Resistance to changing direction",
        default=1.0,
        min=0)
    pTurnAssist = FloatProperty(name="TurnAssist",
                                description="Fake Turning effect (0 - 10)",
                                default=3.0,
                                min=0)
    pMaxTailAngle = FloatProperty(name="Max Tail Angle",
                                  description="Max tail angle",
                                  default=15.0,
                                  min=0,
                                  max=30.0)
    pMaxSteeringAngle = FloatProperty(name="Max Steering Angle",
                                      description="Max steering tail angle",
                                      default=15.0,
                                      min=0,
                                      max=40.0)
    pMaxVerticalAngle = FloatProperty(
        name="Max Vertical Angle",
        description="Max steering angle for vertical",
        default=0.1,
        min=0,
        max=40.0)
    pMaxTailFinAngle = FloatProperty(name="Max Tail Fin Angle",
                                     description="Max tail fin angle",
                                     default=15.0,
                                     min=0,
                                     max=30.0)
    pTailFinPhase = FloatProperty(
        name="Tail Fin Phase",
        description="Tail Fin phase offset from tail movement in degrees",
        default=90.0,
        min=45.0,
        max=135.0)
    pTailFinStiffness = FloatProperty(name="Tail Fin Stiffness",
                                      description="Tail Fin Stiffness",
                                      default=1.0,
                                      min=0,
                                      max=2.0)
    pTailFinStubRatio = FloatProperty(
        name="Tail Fin Stub Ratio",
        description="Ratio for the bottom part of the tail",
        default=0.3,
        min=0,
        max=3.0)
    pMaxSideFinAngle = FloatProperty(name="Max Side Fin Angle",
                                     description="Max side fin angle",
                                     default=5.0,
                                     min=0,
                                     max=60.0)
    pSideFinPhase = FloatProperty(
        name="Side Fin Phase",
        description="Side Fin phase offset from tail movement in degrees",
        default=90.0,
        min=45.0,
        max=135.0)
    # pSideFinStiffness = FloatProperty(name="Side Fin Stiffness", description="Side Fin Stiffness", default=0.2, min=0, max=10.0)
    pChestRatio = FloatProperty(
        name="Chest Ratio",
        description="Ratio of the front of the fish to the rear",
        default=0.5,
        min=0,
        max=2.0)
    pChestRaise = FloatProperty(name="Chest Raise Factor",
                                description="Chest raises during turning",
                                default=1.0,
                                min=0,
                                max=20.0)
    pLeanIntoTurn = FloatProperty(name="LeanIntoTurn",
                                  description="Amount it leans into the turns",
                                  default=1.0,
                                  min=0,
                                  max=20.0)
    pRandom = FloatProperty(name="Random",
                            description="Random amount",
                            default=0.25,
                            min=0,
                            max=1.0)

    #Pectoral Fin Properties
    pPecEffortGain = FloatProperty(
        name="Pectoral Effort Gain",
        description=
        "Amount of effort to maintain position with 1.0 trying very hard to maintain",
        default=0.25,
        min=0,
        max=1.0)
    pPecTurnAssist = FloatProperty(
        name="Pectoral Turn Assist",
        description="Turning Speed while hovering 5 is fast, .2 is slow",
        default=1.0,
        min=0,
        max=20.0)

    pMaxPecFreq = FloatProperty(
        name="Pectoral Stroke Period",
        description=
        "Maximum frequency of pectoral fin movement in frames per cycle",
        default=15.0,
        min=0)
    pMaxPecAngle = FloatProperty(name="Max Pec Fin Angle",
                                 description="Max Pectoral Fin Angle",
                                 default=20.0,
                                 min=0,
                                 max=80)
    pPecPhase = FloatProperty(
        name="Pec Fin Tip Phase",
        description=
        "How far the fin tip lags behind the main movement in degrees",
        default=90.0,
        min=0,
        max=180)
    pPecStubRatio = FloatProperty(
        name="Pectoral Stub Ratio",
        description="Ratio for the bottom part of the pectoral fin",
        default=0.7,
        min=0,
        max=2)
    pPecStiffness = FloatProperty(
        name="Pec Fin Stiffness",
        description="Pectoral fin stiffness, with 1.0 being very stiff",
        default=0.7,
        min=0,
        max=2)
    pHTransTime = FloatProperty(
        name="Hover Transition Time",
        description="Speed of transition between swim and hover in seconds",
        default=0.5,
        min=0,
        max=2)
    pSTransTime = FloatProperty(
        name="Swim Transition Time",
        description="Speed of transition between hover and swim in seconds",
        default=0.2,
        min=0,
        max=2)
    pPecOffset = FloatProperty(
        name="Pectoral Offset",
        description=
        "Adjustment to allow for different rest pose angles of the fins",
        default=20.0,
        min=-90.0,
        max=90.0)
    pHoverDist = FloatProperty(
        name="Hover Distance",
        description=
        "Distance from Target to begin Hover in lengths of the target box. A value of 0 will disable hovering, and the action will be similar to the shark rig.",
        default=1.0,
        min=-1.0,
        max=10.0)
    pHoverTailFrc = FloatProperty(
        name="Hover Tail Fraction",
        description=
        "During Hover, the amount of swimming tail movement to retain. 1.0 is full movment, 0 is none",
        default=0.2,
        min=0.0,
        max=5.0)
    pHoverMaxForce = FloatProperty(
        name="Hover Max Force",
        description=
        "The maximum force the fins can apply in Hover Mode. 1.0 is quite fast",
        default=0.2,
        min=0.0,
        max=10.0)
    pHoverDerate = FloatProperty(
        name="Hover Derate",
        description=
        "In hover, the fish can't go backwards or sideways as fast. This parameter determines how much slower. 1.0 is the same.",
        default=0.2,
        min=-0.0,
        max=1.0)
    pHoverTilt = FloatProperty(
        name="Hover Tilt",
        description=
        "The amount of forward/backward tilt in hover as the fish powers forward and backward. in Degrees and based on Max Hover Force",
        default=4.0,
        min=-0.0,
        max=40.0)
    pPecDuration = FloatProperty(
        name="Pec Duration",
        description=
        "The amount of hovering the fish can do before a rest. Duration in frames",
        default=50.0,
        min=-5.0)
    pPecDuty = FloatProperty(
        name="Pec Duty Cycle",
        description=
        "The amount of rest time compared to active time. 1.0 is 50/50, 0.0 is no rest",
        default=0.8,
        min=0.0)
    pPecTransition = FloatProperty(
        name="Pec Transition to rest speed",
        description=
        "The speed that the pecs change between rest and flap - 1 is instant, 0.05 is fairly slow",
        default=0.05,
        min=0.0,
        max=1.0)
    pHoverTwitch = FloatProperty(
        name="Hover Twitch",
        description="The size of twitching while in hover mode in degrees",
        default=4.0,
        min=0.0,
        max=60.0)
    pHoverTwitchTime = FloatProperty(
        name="Hover Twitch Time",
        description="The time between twitching while in hover mode in frames",
        default=40.0,
        min=0.0)
    pPecSynch = BoolProperty(
        name="Pec Synch",
        description=
        "If true then fins beat together, otherwise fins act out of phase",
        default=False)