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'}
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')
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)
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)
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',
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))
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
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
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")
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')
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)
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="")
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)
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'}
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'}
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.')
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'}
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
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'}
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)