class ImportGLTF2(Operator, ImportHelper): """Load a glTF 2.0 file""" bl_idname = 'import_scene.gltf' bl_label = 'Import glTF 2.0' filter_glob = StringProperty(default="*.glb;*.gltf", options={'HIDDEN'}) loglevel = IntProperty( name='Log Level', description="Log Level") import_pack_images = BoolProperty( name='Pack images', description='Pack all images into .blend file', default=True ) import_shading = EnumProperty( name="Shading", items=(("NORMALS", "Use Normal Data", ""), ("FLAT", "Flat Shading", ""), ("SMOOTH", "Smooth Shading", "")), description="How normals are computed during import", default="NORMALS") def draw(self, context): layout = self.layout layout.prop(self, 'import_pack_images') layout.prop(self, 'import_shading') def execute(self, context): return self.import_gltf2(context) def import_gltf2(self, context): import time from .io.imp.gltf2_io_gltf import glTFImporter from .blender.imp.gltf2_blender_gltf import BlenderGlTF self.set_debug_log() import_settings = self.as_keywords() self.gltf_importer = glTFImporter(self.filepath, import_settings) success, txt = self.gltf_importer.read() if not success: self.report({'ERROR'}, txt) return {'CANCELLED'} success, txt = self.gltf_importer.checks() if not success: self.report({'ERROR'}, txt) return {'CANCELLED'} self.gltf_importer.log.critical("Data are loaded, start creating Blender stuff") start_time = time.time() BlenderGlTF.create(self.gltf_importer) elapsed_s = "{:.2f}s".format(time.time() - start_time) self.gltf_importer.log.critical("glTF import finished in " + elapsed_s) self.gltf_importer.log.removeHandler(self.gltf_importer.log_handler) return {'FINISHED'} def set_debug_log(self): import logging if bpy.app.debug_value == 0: self.loglevel = logging.CRITICAL elif bpy.app.debug_value == 1: self.loglevel = logging.ERROR elif bpy.app.debug_value == 2: self.loglevel = logging.WARNING elif bpy.app.debug_value == 3: self.loglevel = logging.INFO else: self.loglevel = logging.NOTSET
class ScTorus(Node, ScInputNode): bl_idname = "ScTorus" bl_label = "Torus" in_mode: EnumProperty(items=[("MAJOR_MINOR", "Major/Minor", ""), ("EXT_INT", "Exterior/Interior", "")], default="MAJOR_MINOR", update=ScNode.update_value) in_major_segment: IntProperty(default=48, min=3, max=256, update=ScNode.update_value) in_minor_segment: IntProperty(default=12, min=3, max=256, update=ScNode.update_value) in_major_radius: FloatProperty(default=1.0, min=0.01, max=100, update=ScNode.update_value) in_minor_radius: FloatProperty(default=0.25, min=0.01, max=100, update=ScNode.update_value) in_abs_major_radius: FloatProperty(default=1.25, min=0.01, max=100, update=ScNode.update_value) in_abs_minor_radius: FloatProperty(default=0.75, min=0.01, max=100, update=ScNode.update_value) def init(self, context): super().init(context) self.inputs.new("ScNodeSocketNumber", "Major Segments").init("in_major_segment", True) self.inputs.new("ScNodeSocketNumber", "Minor Segments").init("in_minor_segment", True) self.inputs.new("ScNodeSocketString", "Torus Dimensions").init("in_mode") self.inputs.new("ScNodeSocketNumber", "Major Radius").init("in_major_radius", True) self.inputs.new("ScNodeSocketNumber", "Minor Radius").init("in_minor_radius", True) self.inputs.new("ScNodeSocketNumber", "Exterior Radius").init("in_abs_major_radius") self.inputs.new("ScNodeSocketNumber", "Interior Radius").init("in_abs_minor_radius") def error_condition(self): return (super().error_condition() or (not self.inputs["Torus Dimensions"].default_value in ["MAJOR_MINOR", "EXT_INT"]) or (self.inputs["Major Segments"].default_value < 3 or self.inputs["Major Segments"].default_value > 256) or (self.inputs["Minor Segments"].default_value < 3 or self.inputs["Minor Segments"].default_value > 256) or (self.inputs["Major Radius"].default_value < 0 or self.inputs["Major Radius"].default_value > 100) or (self.inputs["Minor Radius"].default_value < 0 or self.inputs["Minor Radius"].default_value > 100) or (self.inputs["Exterior Radius"].default_value < 0 or self.inputs["Exterior Radius"].default_value > 100) or (self.inputs["Interior Radius"].default_value < 0 or self.inputs["Interior Radius"].default_value > 100)) def functionality(self): bpy.ops.mesh.primitive_torus_add( major_segments=int(self.inputs["Major Segments"].default_value), minor_segments=int(self.inputs["Minor Segments"].default_value), mode=self.inputs["Torus Dimensions"].default_value, major_radius=self.inputs["Major Radius"].default_value, minor_radius=self.inputs["Minor Radius"].default_value, abso_major_rad=self.inputs["Exterior Radius"].default_value, abso_minor_rad=self.inputs["Interior Radius"].default_value, generate_uvs=self.inputs["Generate UVs"].default_value)
class UploadOperator(Operator): """Tooltip""" bl_idname = "object.blenderkit_upload" bl_description = "Upload or re-upload asset + thumbnail + metadata" bl_label = "BlenderKit asset upload" bl_options = {'REGISTER', 'UNDO', 'INTERNAL'} # type of upload - model, material, textures, e.t.c. asset_type: EnumProperty( name="Type", items=asset_types, description="Type of upload", default="MODEL", ) reupload: BoolProperty( name="reupload", description="reupload but also draw so that it asks what to reupload", default=False, options={'SKIP_SAVE'}) metadata: BoolProperty(name="metadata", default=True, options={'SKIP_SAVE'}) thumbnail: BoolProperty(name="thumbnail", default=False, options={'SKIP_SAVE'}) main_file: BoolProperty(name="main file", default=False, options={'SKIP_SAVE'}) @classmethod def poll(cls, context): return bpy.context.view_layer.objects.active is not None def execute(self, context): bpy.ops.object.blenderkit_auto_tags() props = utils.get_upload_props() # in case of name change, we have to reupload everything, since the name is stored in blender file, # and is used for linking to scene if props.name_changed: # TODO: this needs to be replaced with new double naming scheme (metadata vs blend data) # print('has to reupload whole data, name has changed.') self.main_file = True props.name_changed = False upload_set = [] if not self.reupload: upload_set = ['METADATA', 'THUMBNAIL', 'MAINFILE'] else: if self.metadata: upload_set.append('METADATA') if self.thumbnail: upload_set.append('THUMBNAIL') if self.main_file: upload_set.append('MAINFILE') result = start_upload(self, context, self.asset_type, self.reupload, upload_set) return result def draw(self, context): props = utils.get_upload_props() layout = self.layout if self.reupload: # layout.prop(self, 'metadata') layout.prop(self, 'main_file') layout.prop(self, 'thumbnail') if props.asset_base_id != '' and not self.reupload: layout.label(text="Really upload as new? ") layout.label( text="Do this only when you create a new asset from an old one." ) layout.label( text="For updates of thumbnail or model use reupload.") if props.is_private == 'PUBLIC': ui_panels.label_multiline( layout, text='public assets are validated several hours' ' or days after upload. ', width=300) def invoke(self, context, event): props = utils.get_upload_props() if props.is_private == 'PUBLIC': return context.window_manager.invoke_props_dialog(self) else: return self.execute(context)
class CGRUProperties(bpy.types.PropertyGroup): # General: jobname = StringProperty(name='Job Name', description='Job Name, scene name if empty', maxlen=512, default='') fpertask = IntProperty(name='Per Task', description='Frames Per One Task', min=1, default=1) sequential = IntProperty(name='Sequential', description='Solve task with this step at first', default=1) pause = BoolProperty(name='Start Job Paused', description='Send job in offline state', default=0) packLinkedObjects = BoolProperty( name='Pack Linked Objects', description='Make Local All linked Groups and Objects', default=0) relativePaths = BoolProperty( name='Relative Paths', description='Set Relative Paths for all Textures and Objects', default=0) packTextures = BoolProperty( name='Pack Textures', description='Pack all Textures into the Blend File', default=0) splitRenderLayers_description = "Split Render layer in blocks. " + \ "Warning: this option disable post-processing passes " + \ "(compositing nor seqeuncer are execute)" splitRenderLayers = BoolProperty(name='Split Render Layers', description=splitRenderLayers_description, default=0) previewPendingApproval = BoolProperty(name='Preview Pending Approval', default=False) # Render Settings: filepath = StringProperty( name='File Path', description='Set File Path. You can use ### to set number of frames', maxlen=512, default='') # Paramerets: priority = IntProperty(name='Priority', description='Job order in user jobs list', min=-1, max=250, default=-1) maxruntasks = IntProperty(name='Max Run Tasks', description='Maximum number of running tasks', min=-1, max=9999, default=-1) dependmask = StringProperty(name='Depend Mask', description='Jobs to wait pattern', maxlen=512, default='') dependmaskglobal = StringProperty( name='Global Depend', description='All users jobs wait pattern', maxlen=512, default='') hostsmask = StringProperty(name='Hosts Mask', description='Hosts to run pattern', maxlen=512, default='') hostsmaskexclude = StringProperty(name='Exclude Hosts', description='Hosts to ignore pattern', maxlen=512, default='') adv_options = BoolProperty(name="More options", default=False) make_movie = BoolProperty(name='Make movie', default=False) mov_name = StringProperty(name='Movie Name', maxlen=512, default='', subtype="FILE_PATH") mov_width = IntProperty(name='Movie width', default=1280) mov_height = IntProperty(name='Movie height', default=720) mov_codecs = EnumProperty(name="Movie codec", items=utils.get_movie_codecs)
def __init__(self): # Holds the current selected kinematics model (armature) name self.model_name = PropertyHandler(StringProperty(name='Name', update=self.name_update)) self.old_name = PropertyHandler(StringProperty(name='Name')) # Holds the name of the currently selected segment (Bone) self.segment_name = PropertyHandler(StringProperty(update=self.updateBoneName)) # Holds the name of the currently selected geometry (Mesh object) self.mesh_name = PropertyHandler(StringProperty(update=self.update_geometry_name)) # Holds the name of the currently selected physics frame (Empty object) self.camera_sensor_name = PropertyHandler(StringProperty()) # Used to realize the main tab in the GUI self.gui_tab = PropertyHandler(EnumProperty( items=[('armatures', 'Robot', 'Modify the Robot'), ('bones', 'Segments', 'Modify segements'), ('meshes', 'Geometries', 'Assign meshes to segments'), ('sensors', 'Sensors', 'Assign sensors to the robot'), ('muscles', 'Muscles', 'Assign muscles to the robot'), # ('markers', 'Markers', 'Assign markers to bones'), # ('controller', 'Controller', 'Modify controller parameter'), ('tools', 'Tools', 'Tools'), ('files', 'Files', 'Export Armature')], )) # Holds the selection to operate on colission geometries OR visual geometries self.mesh_type = PropertyHandler(EnumProperty( items=[('DEFAULT', 'Visual geometries', 'Edit visual geometries'), ('COLLISION', 'Collision geometries', 'Edit collision geometries')] )) self.sensor_type = PropertyHandler(EnumProperty( items=[('CAMERA_SENSOR','Cameras', 'Edit camera sensors'), ('LASER_SENSOR', 'Laser scanners', 'Edit laser scanners')] # ('POSITION', 'Position sensors', 'Edit position sensors')] )) self.physics_type = PropertyHandler(EnumProperty(items=[('PHYSICS_FRAME', 'Mass object', 'Mass object')])) self.display_physics_selection = PropertyHandler(BoolProperty(name="Show Physics Frames", description="Show or hide physics frames", default=True, update=self.display_physics)) # Holds the selection to list connected or unassigned meshes in dropdown menus self.list_meshes = PropertyHandler(EnumProperty( items=[("all", 'List all', 'Show all meshes in menu', 'RESTRICT_VIEW_OFF', 1), ("connected", 'List connected', 'Show only connected meshes in menu', 'OUTLINER_OB_ARMATURE', 2), ('disconnected', 'List disconnected', 'Show only disconnected meshes in menu', 'ARMATURE_DATA', 3)])) self.assign_collision = PropertyHandler(BoolProperty(name="Assign as Collision Mesh", description="Adds a collision tag to the mesh", default=False)) # Holds the selection of wheter do hide/display connected/unassigned meshes in the 3D viewport self.display_mesh_selection = PropertyHandler(EnumProperty( items=[('all', 'All', 'Show all objects in viewport'), ('collision', 'Collision', 'Show only connected collision models'), ('visual', 'Visual', 'Show only connected visual models'), ('none', "None", "Show no connected model")], update=self.display_geometries)) # Holds the selection to list connected or unassigned segments in dropdown menus self.list_segments = PropertyHandler(EnumProperty( items=[("all", 'List all', 'Show all bones in menu', 'RESTRICT_VIEW_OFF', 1), ("connected", 'List connected', 'Show only bones with connected meshes in menu', 'OUTLINER_OB_ARMATURE', 2,), ('disconnected', 'List disconnected', 'List only bones without connected meshes in menu', 'ARMATURE_DATA', 3)])) self.storage_mode = PropertyHandler(EnumProperty(items=[('temporary', 'Non-persistant GIT', 'Stores/retrieves files from GIT temporary' + ' repository'), ('git', 'Persitant GIT', 'Stores/retrieves files from persistent GIT repository'), ('local', 'Local', 'Stores/retrieves from local hard disk')])) self.git_url = PropertyHandler(StringProperty(name='GIT URL')) self.git_repository = PropertyHandler(StringProperty(name='GIT Repository')) self.segment_tab = PropertyHandler(EnumProperty( items=[('kinematics', 'Kinematics', 'Edit kinematic properties'), ('dynamics', 'Dynamics', 'Edit Dynamic properties'), ('controller', 'Controller', 'Edit Controller properties')], name="asdf")) self.bone_length = PropertyHandler(FloatProperty(name="Global bone length", default=1, min=0.001, update=self.updateGlobals)) self.do_kinematic_update = PropertyHandler(BoolProperty(name="Import Update", default=True)) self.gazebo_tags = PropertyHandler(StringProperty(name="Gazebo tags", default="")) self.operator_debug_level = PropertyHandler(EnumProperty( items=[('debug', 'Debug', 'Log everything including debug messages (verbose)'), ('info', 'Info', 'Log information'), ('warning', 'Warning', 'Log only warnings'), ('error', 'Error', 'Log only errors')], update=self.debug_level_callback)) self.active_muscle = PropertyHandler(StringProperty(name="Active Muscle", default="")) self.display_muscle_selection = PropertyHandler(EnumProperty( items=[('all', 'All', 'Show all muscles'), # ('MYOROBOTICS', 'Myorobotics', 'Show only Myorobotics Muscles'), ('MILLARD_EQUIL', 'Millard Equilibrium 2012', 'Show only Millard Equilibrium 2012 Muscles'), ('MILLARD_ACCEL', 'Millard Acceleration 2012', 'Show only Millard Acceleration 2012 Muscles'), ('THELEN', 'Thelen 2003', 'Show only Thelen 2003 Muscles'), ('RIGID_TENDON', 'Rigid Tendon', 'Show only Rigid Tendon Muscles'), ('none', "None", "Show no muscles")], update=self.display_muscles)) self.muscle_dim = PropertyHandler(FloatProperty(name="Muscle Dimension:", default=0.05, update=self.muscle_dim_update))
class SvListModifierNode(bpy.types.Node, SverchCustomTreeNode): ''' List Modifier''' bl_idname = 'SvListModifierNode' bl_label = 'List Modifier' bl_icon = 'MODIFIER' mode_items = [(name, name, "", idx) for _, idx, name, _ in node_item_list] func_: EnumProperty(name="Modes", description="Mode Choices", default=SET, items=mode_items, update=updateNode) listify: BoolProperty(default=True, description='Output lists or proper sets', update=updateNode) help_url: StringProperty(default='list_main/list_modifier') def draw_buttons(self, context, layout): layout.prop(self, "func_", text='') layout.prop(self, "listify", text='output as list') def sv_init(self, context): self.inputs.new('SvStringsSocket', "Data1") self.inputs.new('SvStringsSocket', "Data2") self.outputs.new('SvStringsSocket', "Result") def draw_label(self): return self.func_ def process(self): inputs = self.inputs outputs = self.outputs if not outputs[0].is_linked: return unary = (num_inputs[self.func_] == 1) f = self.get_f(unary) if unary: if inputs['Data1'].is_linked: data1 = inputs['Data1'].sv_get() elif inputs['Data2'].is_linked: data1 = inputs['Data2'].sv_get() else: return out = f(data1) else: data1 = inputs['Data1'].sv_get() data2 = inputs['Data2'].sv_get() out = f(data1, data2) # params = match_long_repeat([data1, data2]) # out = f(*params) outputs[0].sv_set(out) def get_f(self, unary): operation = func_dict[self.func_] do_post = (self.func_ in SET_OPS) and self.listify post_process = list if do_post else lambda x: x # identity function if unary: def f(d): if isinstance(d[0], (int, float)): return post_process(operation(d)) else: return [f(x) for x in d] else: def f(a, b): if isinstance(a[0], (int, float)): return post_process(operation(a, b)) else: return [f(*_) for _ in zip(a, b)] return f
class SvUVtextureNode(bpy.types.Node, SverchCustomTreeNode): ''' UV texture node ''' bl_idname = 'SvUVtextureNode' bl_label = 'UVtextures' bl_icon = 'MATERIAL' def sv_init(self, context): self.inputs.new('SvObjectSocket', "Object") self.outputs.new('VerticesSocket', "Verts") self.outputs.new('StringsSocket', "Pols") def avail_objects(self, context): items = [('', '', '')] if self.inputs and self.inputs[0].is_linked: objects = self.inputs[0].sv_get() items = [(obj.name, obj.name, '') for obj in objects] return items def avail_uvs(self, context): items = [('', '', '')] if self.inputs and self.inputs[0].is_linked: obj = bpy.data.objects[self.objects] if obj.data.uv_layers: items = [(p.name, p.name, "") for p in obj.data.uv_layers] return items objects: EnumProperty(items=avail_objects, name="Objects", description="Choose Objects", update=updateNode) uv: EnumProperty(items=avail_uvs, name="UV", description="Choose UV to load", update=updateNode) def draw_buttons(self, context, layout): layout.prop(self, 'uv', text='uv') def update(self): pass def UV(self, object, uv): # makes UV from layout texture area to sverchok vertices and polygons. mesh = object.data bm = bmesh.new() bm.from_mesh(mesh) uv_layer = bm.loops.layers.uv[uv] nFaces = len(bm.faces) bm.verts.ensure_lookup_table() bm.faces.ensure_lookup_table() vertices_dict = {} polygons_new = [] areas = [] for fi in range(nFaces): polygons_new_pol = [] areas.append(bm.faces[fi].calc_area()) for loop in bm.faces[fi].loops: li = loop.index polygons_new_pol.append(li) vertices_dict[li] = list(loop[uv_layer].uv[:]) + [0] polygons_new.append(polygons_new_pol) vertices_new = [i for i in vertices_dict.values()] bm_roll = bmesh_from_pydata(verts=vertices_new, edges=[], faces=polygons_new) bm_roll.verts.ensure_lookup_table() bm_roll.faces.ensure_lookup_table() areas_roll = [] for fi in range(nFaces): areas_roll.append(bm_roll.faces[fi].calc_area()) np_area_origin = np.array(areas).mean() np_area_roll = np.array(areas_roll).mean() mult = np.sqrt(np_area_origin / np_area_roll) np_ver = np.array(vertices_new) #(print(np_area_origin,np_area_roll,mult,'плориг, плразв, множитель')) vertices_new = (np_ver * mult).tolist() bm.clear() del bm bm_roll.clear() del bm_roll return [vertices_new], [polygons_new] def process(self): if self.inputs and self.inputs[0].is_linked: obj = bpy.data.objects[self.objects] if not self.uv: print('!!! for node:', self.name, '!!! object', self.objects, 'have no UV') if self.outputs and self.outputs[0].is_linked: self.outputs[0].sv_set([[]]) return uv = self.uv v, p = self.UV(obj, uv) if self.outputs and self.outputs[0].is_linked: self.outputs[0].sv_set(v) if self.outputs and self.outputs[1].is_linked: self.outputs[1].sv_set(p)
class CM_ND_MidiFloatAnimNode(bpy.types.Node, CM_ND_BaseNode): bl_idname = "cm_audio.midi_float_anim_node" bl_label = "MIDI Float Object Animate" bl_width_default = 150 """Animate One Object from MIDI Float Data""" factors: FloatVectorProperty(name="", subtype="XYZ", default=(1, 1, 1)) anim_type: EnumProperty( items=( ("loc", "Location", "Animate Location"), ("rot", "Rotation", "Animate Rotation"), ("scl", "Scale", "Animate Scale"), ), name="Animate", default="loc", description="Animation Type", ) midi_type: EnumProperty( items=( ("key", "Keys", "Use MIDI Keys"), ("con", "Controls", "Use MIDI Controls"), ), name="MIDI", default="key", description="MIDI Type", ) use_bones: BoolProperty(name="Use Bones", default=False) def init(self, context): super().init(context) self.inputs.new("cm_socket.midi", "[Key, Control] Data") self.inputs.new("cm_socket.object", "Object") self.inputs.new("cm_socket.bone", "Bone") def draw_buttons(self, context, layout): box = layout.box() box.prop(self, "anim_type") box.prop(self, "midi_type") row = box.row() row.prop(self, "factors") box = layout.box() box.prop(self, "use_bones") def get_midi(self): cm = bpy.context.scene.cm_pg tgt_obj = None bone = None sockets = self.inputs.keys() buffer_in = connected_node_midi(self, 0) input = connected_node_output(self, 1) if isinstance(input, dict): if "objects" in input.keys(): objects = input["objects"] if not isinstance(objects, list): objects = [objects] if len(objects) == 1: tgt_obj = objects[0] bone_in = connected_node_output(self, 2) if isinstance(bone_in, dict): if "bones" in bone_in.keys(): bone = bone_in["bones"] if buffer_in is not None: if self.midi_type == "con": num = 1 else: num = 0 values = [buffer_in[num], buffer_in[num], buffer_in[num]] vector_delta, euler_delta, scale_delta = off_set( values, self.factors) if self.use_bones and bone is not None: if self.anim_type == "loc": if self.factors.x != 0: bone.location.x = vector_delta.x if self.factors.y != 0: bone.location.y = vector_delta.y if self.factors.z != 0: bone.location.z = vector_delta.z elif self.anim_type == "rot": if self.factors.x != 0: bone.rotation_euler.x = euler_delta.x if self.factors.y != 0: bone.rotation_euler.y = euler_delta.y if self.factors.z != 0: bone.rotation_euler.z = euler_delta.z else: if self.factors.x != 0: bone.scale.x = scale_delta.x if self.factors.y != 0: bone.scale.y = scale_delta.y if self.factors.z != 0: bone.scale.z = scale_delta.z elif not self.use_bones and tgt_obj is not None: if self.anim_type == "loc": if self.factors.x != 0: tgt_obj.delta_location.x = vector_delta.x if self.factors.y != 0: tgt_obj.delta_location.y = vector_delta.y if self.factors.z != 0: tgt_obj.delta_location.z = vector_delta.z elif self.anim_type == "rot": if self.factors.x != 0: tgt_obj.delta_rotation_euler.x = euler_delta.x if self.factors.y != 0: tgt_obj.delta_rotation_euler.y = euler_delta.y if self.factors.z != 0: tgt_obj.delta_rotation_euler.z = euler_delta.z else: if self.factors.x != 0: tgt_obj.delta_scale.x = scale_delta.x if self.factors.y != 0: tgt_obj.delta_scale.y = scale_delta.y if self.factors.z != 0: tgt_obj.delta_scale.z = scale_delta.z return None def output(self): output = self.get_midi() return {"MIDI Handler": output}
class SvListInputNode(bpy.types.Node, SverchCustomTreeNode): ''' Creta a float or int List ''' bl_idname = 'SvListInputNode' bl_label = 'List Input' bl_icon = 'OUTLINER_OB_EMPTY' sv_icon = 'SV_LIST_INPUT' defaults = [0 for i in range(32)] to3d: BoolProperty(name='to3d', description='show in 3d panel', default=True) int_: IntProperty(name='int_', description='integer number', default=1, min=1, max=32, update=updateNode) v_int: IntProperty(name='int_', description='integer number', default=1, min=1, max=10, update=updateNode) int_list: IntVectorProperty(name='int_list', description="Integer list", default=defaults, size=32, update=updateNode) float_list: FloatVectorProperty(name='float_list', description="Float list", default=defaults, size=32, update=updateNode) vector_list: FloatVectorProperty(name='vector_list', description="Vector list", default=defaults, size=32, update=updateNode) def changeMode(self, context): if self.mode == 'vector': if 'Vector List' not in self.outputs: self.outputs.remove(self.outputs[0]) self.outputs.new('SvVerticesSocket', 'Vector List') return else: if 'List' not in self.outputs: self.outputs.remove(self.outputs[0]) self.outputs.new('SvStringsSocket', 'List') return modes = [("int_list", "Int", "Integer", "", 1), ("float_list", "Float", "Float", "", 2), ("vector", "Vector", "Vector", "", 3)] mode: EnumProperty(items=modes, default='int_list', update=changeMode) def sv_init(self, context): self.outputs.new('SvStringsSocket', "List") def draw_buttons(self, context, layout): if self.mode == 'vector': layout.prop(self, "v_int", text="List Length") else: layout.prop(self, "int_", text="List Length") layout.prop(self, "mode", expand=True) if self.mode == 'vector': col = layout.column(align=False) for i in range(self.v_int): row = col.row(align=True) for j in range(3): row.prop(self, 'vector_list', index=i * 3 + j, text='XYZ'[j]) else: col = layout.column(align=True) for i in range(self.int_): col.prop(self, self.mode, index=i, text=str(i)) def draw_buttons_ext(self, context, layout): layout.prop(self, 'to3d', text='to3d') @property def draw_3dpanel(self): return False if not self.outputs[0].is_linked or not self.to3d else True def draw_buttons_3dpanel(self, layout): layout.row(align=True).label(text=self.label or self.name) if self.mode == 'vector': colum_list = layout.column(align=True) for i in range(self.v_int): row = colum_list.row(align=True) for j in range(3): row.prop(self, 'vector_list', index=i * 3 + j, text='XYZ'[j] + (self.label if self.label else self.name)) else: colum_list = layout.column(align=True) for i in range(self.int_): row = colum_list.row(align=True) row.prop(self, self.mode, index=i, text=str(i) + (self.label if self.label else self.name)) row.scale_x = 0.8 def process(self): if self.outputs[0].is_linked: if self.mode == 'int_list': data = [list(self.int_list[:self.int_])] elif self.mode == 'float_list': data = [list(self.float_list[:self.int_])] elif self.mode == 'vector': c = self.v_int * 3 v_l = list(self.vector_list) data = [list(zip(v_l[0:c:3], v_l[1:c:3], v_l[2:c:3]))] self.outputs[0].sv_set(data)
class ImportOBJ(bpy.types.Operator, ImportHelper, IOOBJOrientationHelper): """Load a Wavefront OBJ File""" bl_idname = "import_scene.obj" bl_label = "Import OBJ" bl_options = {'PRESET', 'UNDO'} filename_ext = ".obj" filter_glob = StringProperty( default="*.obj;*.mtl", options={'HIDDEN'}, ) use_edges = BoolProperty( name="Lines", description="Import lines and faces with 2 verts as edge", default=True, ) use_smooth_groups = BoolProperty( name="Smooth Groups", description="Surround smooth groups by sharp edges", default=True, ) use_split_objects = BoolProperty( name="Object", description="Import OBJ Objects into Blender Objects", default=True, ) use_split_groups = BoolProperty( name="Group", description="Import OBJ Groups into Blender Objects", default=True, ) use_groups_as_vgroups = BoolProperty( name="Poly Groups", description="Import OBJ groups as vertex groups", default=False, ) use_image_search = BoolProperty( name="Image Search", description="Search subdirs for any associated images " "(Warning, may be slow)", default=True, ) split_mode = EnumProperty( name="Split", items=( ('ON', "Split", "Split geometry, omits unused verts"), ('OFF', "Keep Vert Order", "Keep vertex order from file"), ), ) global_clight_size = FloatProperty( name="Clamp Size", description="Clamp bounds under this value (zero to disable)", min=0.0, max=1000.0, soft_min=0.0, soft_max=1000.0, default=0.0, ) def execute(self, context): # print("Selected: " + context.active_object.name) from . import import_obj if self.split_mode == 'OFF': self.use_split_objects = False self.use_split_groups = False else: self.use_groups_as_vgroups = False keywords = self.as_keywords(ignore=( "axis_forward", "axis_up", "filter_glob", "split_mode", )) global_matrix = axis_conversion( from_forward=self.axis_forward, from_up=self.axis_up, ).to_4x4() keywords["global_matrix"] = global_matrix keywords["use_cycles"] = (context.scene.view_render.engine == 'CYCLES') if bpy.data.is_saved and context.user_preferences.filepaths.use_relative_paths: import os keywords["relpath"] = os.path.dirname(bpy.data.filepath) return import_obj.load(context, **keywords) def draw(self, context): layout = self.layout row = layout.row(align=True) row.prop(self, "use_smooth_groups") row.prop(self, "use_edges") box = layout.box() row = box.row() row.prop(self, "split_mode", expand=True) row = box.row() if self.split_mode == 'ON': row.label(text="Split by:") row.prop(self, "use_split_objects") row.prop(self, "use_split_groups") else: row.prop(self, "use_groups_as_vgroups") row = layout.split(percentage=0.67) row.prop(self, "global_clight_size") layout.prop(self, "axis_forward") layout.prop(self, "axis_up") layout.prop(self, "use_image_search")
class M3SceneProperties(bpy.types.PropertyGroup): def update_xray(self, context): x = (self.pass_through, self.show_edit_mesh_wire) shading = context.space_data.shading shading.show_xray = True if any(x) else False if self.show_edit_mesh_wire: shading.xray_alpha = 0.1 elif self.pass_through: shading.xray_alpha = 1 if context.active_object and context.active_object.type == "MESH" else 0.5 def update_uv_sync_select(self, context): ts = context.scene.tool_settings ts.use_uv_select_sync = self.uv_sync_select global selected active = context.active_object # restore previous selection if ts.use_uv_select_sync: bpy.ops.mesh.select_all(action='DESELECT') bm = bmesh.from_edit_mesh(active.data) bm.normal_update() bm.verts.ensure_lookup_table() if selected: for v in bm.verts: if v.index in selected: v.select_set(True) bm.select_flush(True) bmesh.update_edit_mesh(active.data) # also sync the selection mode # NOTE: disabled again, seems like it's beneficial to just go back to the previous mesh selection mode # if ts.uv_select_mode in ["VERTEX", "EDGE", "FACE"]: # bpy.ops.mesh.select_mode(type=ts.uv_select_mode.replace("VERTEX", "VERT")) # store the active selection else: bm = bmesh.from_edit_mesh(active.data) bm.normal_update() bm.verts.ensure_lookup_table() selected = [v.index for v in bm.verts if v.select] bpy.ops.mesh.select_all(action="SELECT") # also sync the selection mode mode = tuple(ts.mesh_select_mode) # EDGE mode in the mesh becomes, EDGE in uv as well if mode == (False, True, False): ts.uv_select_mode = "EDGE" # everything else becomes VERTEX, including FACE # that's because there's no reason to turn off sync for face selections in the first place, faces unlike verts and edges, are always only present once in uv space else: ts.uv_select_mode = "VERTEX" def update_show_cavity(self, context): t = (self.show_cavity, self.show_curvature) shading = context.space_data.shading shading.show_cavity = True if any(t) else False if t == (True, True): shading.cavity_type = "BOTH" elif t == (True, False): shading.cavity_type = "WORLD" elif t == (False, True): shading.cavity_type = "SCREEN" def update_grouppro_dotnames(self, context): gpcols = [col for col in bpy.data.collections if col.created_with_gp] for col in gpcols: # hide collections if self.grouppro_dotnames: if not col.name.startswith("."): col.name = ".%s" % col.name else: if col.name.startswith("."): col.name = col.name[1:] pass_through: BoolProperty(name="Pass Through", default=False, update=update_xray) show_edit_mesh_wire: BoolProperty(name="Show Edit Mesh Wireframe", default=False, update=update_xray) uv_sync_select: BoolProperty(name="Synce Selection", default=False, update=update_uv_sync_select) show_cavity: BoolProperty(name="Cavity", default=True, update=update_show_cavity) show_curvature: BoolProperty(name="Curvature", default=False, update=update_show_cavity) focus_history: CollectionProperty(type=HistoryEpochCollection) grouppro_dotnames: BoolProperty(name=".dotname GroupPro collections", default=False, update=update_grouppro_dotnames) def update_eevee_preset(self, context): eevee = context.scene.eevee shading = context.space_data.shading if self.eevee_preset == 'NONE': eevee.use_ssr = False eevee.use_gtao = False eevee.use_bloom = False eevee.use_volumetric_lights = False if self.eevee_preset_set_use_scene_lights: shading.use_scene_lights = False if self.eevee_preset_set_use_scene_world: shading.use_scene_world = False if context.scene.render.engine == 'BLENDER_EEVEE': if self.eevee_preset_set_use_scene_lights: shading.use_scene_lights_render = False if self.eevee_preset_set_use_scene_world: shading.use_scene_world_render = False elif self.eevee_preset == 'LOW': eevee.use_ssr = True eevee.use_ssr_halfres = True eevee.use_ssr_refraction = False eevee.use_gtao = True eevee.use_bloom = False eevee.use_volumetric_lights = False if self.eevee_preset_set_use_scene_lights: shading.use_scene_lights = True if self.eevee_preset_set_use_scene_world: shading.use_scene_world = False if context.scene.render.engine == 'BLENDER_EEVEE': if self.eevee_preset_set_use_scene_lights: shading.use_scene_lights_render = True if self.eevee_preset_set_use_scene_world: shading.use_scene_world_render = False elif self.eevee_preset == 'HIGH': eevee.use_ssr = True eevee.use_ssr_halfres = False eevee.use_ssr_refraction = True eevee.use_gtao = True eevee.use_bloom = True eevee.use_volumetric_lights = False if self.eevee_preset_set_use_scene_lights: shading.use_scene_lights = True if self.eevee_preset_set_use_scene_world: shading.use_scene_world = False if context.scene.render.engine == 'BLENDER_EEVEE': if self.eevee_preset_set_use_scene_lights: shading.use_scene_lights_render = True if self.eevee_preset_set_use_scene_world: shading.use_scene_world_render = False elif self.eevee_preset == 'ULTRA': eevee.use_ssr = True eevee.use_ssr_halfres = False eevee.use_ssr_refraction = True eevee.use_gtao = True eevee.use_bloom = True eevee.use_volumetric_lights = True if self.eevee_preset_set_use_scene_lights: shading.use_scene_lights = True if context.scene.render.engine == 'BLENDER_EEVEE': if self.eevee_preset_set_use_scene_lights: shading.use_scene_lights_render = True if self.eevee_preset_set_use_scene_lights: world = context.scene.world if world: shading.use_scene_world = True if context.scene.render.engine == 'BLENDER_EEVEE': shading.use_scene_world_render = True output = get_world_output(world) links = output.inputs[1].links if not links: tree = world.node_tree volume = tree.nodes.new('ShaderNodeVolumePrincipled') tree.links.new(volume.outputs[0], output.inputs[1]) volume.inputs[2].default_value = 0.1 volume.location = (-200, 200) def update_eevee_gtao_factor(self, context): context.scene.eevee.gtao_factor = self.eevee_gtao_factor def update_eevee_bloom_intensity(self, context): context.scene.eevee.bloom_intensity = self.eevee_bloom_intensity def update_render_engine(self, context): if self.avoid_update: self.avoid_update = False return context.scene.render.engine = self.render_engine if get_prefs().activate_render and get_prefs( ).activate_shading_pie and get_prefs( ).render_adjust_lights_on_render and get_area_light_poll( ) and self.adjust_lights_on_render: last = self.adjust_lights_on_render_last debug = False # debug = True if last in ['NONE', 'INCREASE'] and self.render_engine == 'CYCLES': self.adjust_lights_on_render_last = 'DECREASE' if debug: print("decreasing on switch to cycies engine") adjust_lights_for_rendering(mode='DECREASE') elif last == 'DECREASE' and self.render_engine == 'BLENDER_EEVEE': self.adjust_lights_on_render_last = 'INCREASE' if debug: print("increasing on switch to eevee engine") adjust_lights_for_rendering(mode='INCREASE') if get_prefs().activate_render and get_prefs( ).render_sync_light_visibility: sync_light_visibility(context.scene) def update_cycles_device(self, context): if self.avoid_update: self.avoid_update = False return context.scene.cycles.device = self.cycles_device def update_shading_light(self, context): if self.avoid_update: self.avoid_update = False return shading = context.space_data.shading shading.light = self.shading_light # use shadows for FLAT shading if self.use_flat_shadows: shading.show_shadows = shading.light == 'FLAT' def update_use_flat_shadows(self, context): if self.avoid_update: self.avoid_update = False return shading = context.space_data.shading if shading.light == 'FLAT': shading.show_shadows = self.use_flat_shadows def update_custom_views_local(self, context): if self.avoid_update: self.avoid_update = False return # only one custom view can be active at a time if self.custom_views_local and self.custom_views_cursor: self.avoid_update = True self.custom_views_cursor = False # toggle orhto grid context.space_data.overlay.show_ortho_grid = not self.custom_views_local # toggle trackball orbiting if get_prefs().custom_views_use_trackball: context.preferences.inputs.view_rotate_method = 'TRACKBALL' if self.custom_views_local else 'TURNTABLE' # set transform preset if get_prefs().activate_transform_pie and get_prefs( ).custom_views_set_transform_preset: bpy.ops.machin3.set_transform_preset( pivot='MEDIAN_POINT', orientation='LOCAL' if self.custom_views_local else 'GLOBAL') # toggle axes drawing if get_prefs().activate_shading_pie and get_prefs( ).custom_views_toggle_axes_drawing: dns = bpy.app.driver_namespace handler = dns.get('draw_object_axes') if handler: remove_object_axes_drawing_handler(handler) if self.custom_views_local and context.active_object: add_object_axes_drawing_handler(dns, context, [context.active_object], False) context.area.tag_redraw() def update_custom_views_cursor(self, context): if self.avoid_update: self.avoid_update = False return # only one custom view can be active at a time if self.custom_views_cursor and self.custom_views_local: self.avoid_update = True self.custom_views_local = False # toggle ortho grid context.space_data.overlay.show_ortho_grid = not self.custom_views_cursor # toggle trackball orbiting if get_prefs().custom_views_use_trackball: context.preferences.inputs.view_rotate_method = 'TRACKBALL' if self.custom_views_cursor else 'TURNTABLE' # only actually set the transform preset and draw the cursor axis if hyper cursor tools aren't active if 'machin3.tool_hyper_cursor' not in get_active_tool(context).idname: # set transform preset if get_prefs().activate_transform_pie and get_prefs( ).custom_views_set_transform_preset: bpy.ops.machin3.set_transform_preset( pivot='CURSOR' if self.custom_views_cursor else 'MEDIAN_POINT', orientation='CURSOR' if self.custom_views_cursor else 'GLOBAL') # toggle axes drawing if get_prefs().activate_shading_pie and get_prefs( ).custom_views_toggle_axes_drawing: dns = bpy.app.driver_namespace handler = dns.get('draw_object_axes') if handler: remove_object_axes_drawing_handler(handler) if self.custom_views_cursor: add_object_axes_drawing_handler(dns, context, [], True) context.area.tag_redraw() # SHADING eevee_preset: EnumProperty(name="Eevee Preset", description="Eevee Quality Presets", items=eevee_preset_items, default='NONE', update=update_eevee_preset) eevee_preset_set_use_scene_lights: BoolProperty( name="Set Use Scene Lights", description="Set Use Scene Lights when changing Eevee Preset", default=False) eevee_preset_set_use_scene_world: BoolProperty( name="Set Use Scene World", description="Set Use Scene World when changing Eevee Preset", default=False) eevee_gtao_factor: FloatProperty(name="Factor", default=1, min=0, step=0.1, update=update_eevee_gtao_factor) eevee_bloom_intensity: FloatProperty(name="Intensity", default=0.05, min=0, step=0.1, update=update_eevee_bloom_intensity) render_engine: EnumProperty(name="Render Engine", description="Render Engine", items=render_engine_items, default='BLENDER_EEVEE', update=update_render_engine) cycles_device: EnumProperty(name="Render Device", description="Render Device", items=cycles_device_items, default='CPU', update=update_cycles_device) shading_light: EnumProperty( name="Lighting Method", description="Lighting Method for Solid/Texture Viewport Shading", items=shading_light_items, default='MATCAP', update=update_shading_light) use_flat_shadows: BoolProperty( name="Use Flat Shadows", description="Use Shadows when in Flat Lighting", default=True, update=update_use_flat_shadows) object_axes_size: FloatProperty(name="Object Axes Size", default=0.3, min=0) object_axes_alpha: FloatProperty(name="Object Axes Alpha", default=0.75, min=0, max=1) adjust_lights_on_render: BoolProperty( name="Adjust Lights when Rendering", description= "Adjust Lights Area Lights when Rendering, to better match Eevee and Cycles", default=False) adjust_lights_on_render_divider: FloatProperty( name= "Divider used to calculate Cycles Light Strength from Eeeve Light Strength", default=4, min=1) adjust_lights_on_render_last: StringProperty(name="Last Light Adjustment", default='NONE') is_light_decreased_by_handler: BoolProperty( name="Have Lights been decreased by the init render handler?", default=False) # VIEW custom_views_local: BoolProperty( name="Custom Local Views", description= "Use Custom Views, based on the active object's orientation", default=False, update=update_custom_views_local) custom_views_cursor: BoolProperty( name="Custom Cursor Views", description="Use Custom Views, based on the cursor's orientation", default=False, update=update_custom_views_cursor) # ALIGN align_mode: EnumProperty(name="Align Mode", items=align_mode_items, default="VIEW") # SMART DRIVE show_smart_drive: BoolProperty(name="Show Smart Drive") driver_start: FloatProperty(name="Driver Start Value", precision=3) driver_end: FloatProperty(name="Driver End Value", precision=3) driver_axis: EnumProperty(name="Driver Axis", items=axis_items, default='X') driver_transform: EnumProperty(name="Driver Transform", items=driver_transform_items, default='LOCATION') driver_space: EnumProperty(name="Driver Space", items=driver_space_items, default='AUTO') driven_start: FloatProperty(name="Driven Start Value", precision=3) driven_end: FloatProperty(name="Driven End Value", precision=3) driven_axis: EnumProperty(name="Driven Axis", items=axis_items, default='X') driven_transform: EnumProperty(name="Driven Transform", items=driver_transform_items, default='LOCATION') driven_limit: EnumProperty(name="Driven Lmit", items=driver_limit_items, default='BOTH') # UNITY def update_unity_export_path(self, context): if self.avoid_update: self.avoid_update = False return path = self.unity_export_path if path: if not path.endswith('.fbx'): path += '.fbx' self.avoid_update = True self.unity_export_path = abspath(path) show_unity: BoolProperty(name="Show Unity") unity_export: BoolProperty( name="Export to Unity", description= "Enable to do the actual FBX export\nLeave it off to only prepare the Model" ) unity_export_path: StringProperty(name="Unity Export Path", subtype='FILE_PATH', update=update_unity_export_path) unity_triangulate: BoolProperty( name="Triangulate before exporting", description= "Add Triangulate Modifier to the end of every object's stack", default=False) # BoxCutter def update_bcorientation(self, context): bcprefs = get_addon_prefs('BoxCutter') if self.bcorientation == 'LOCAL': bcprefs.behavior.orient_method = 'LOCAL' elif self.bcorientation == 'NEAREST': bcprefs.behavior.orient_method = 'NEAREST' elif self.bcorientation == 'LONGEST': bcprefs.behavior.orient_method = 'TANGENT' bcorientation: EnumProperty(name="BoxCutter Orientation", items=bc_orientation_items, default='LOCAL', update=update_bcorientation) # GROUP def update_group_select(self, context): ''' if auto select is disabled, update the selected objets accordingly to properly represent that this allows you to easily select just the top_level group empties, even if they are hidden, by selecting the group and then disabling auto select ''' if not self.group_select: all_empties = [ obj for obj in context.selected_objects if obj.M3.is_group_empty ] top_level = [ obj for obj in all_empties if obj.parent not in all_empties ] for obj in context.selected_objects: if obj not in top_level: obj.select_set(False) def update_group_recursive_select(self, context): ''' if recursive select is disabled, update the selected objets accordingly to properly represent that this allows you to easily select just the top_level group objects, even if they are hidden, by selecting the group and then disabling recursive select NOTE: the update_group handler will do the rest and actually select the group, after this functions leaves just the top_level empties selected ''' if not self.group_recursive_select: all_empties = [ obj for obj in context.selected_objects if obj.M3.is_group_empty ] top_level = [ obj for obj in all_empties if obj.parent not in all_empties ] for obj in context.selected_objects: if obj not in top_level: obj.select_set(False) def update_group_hide(self, context): empties = [ obj for obj in context.visible_objects if obj.M3.is_group_empty ] for e in empties: if e == context.active_object or not context.scene.M3.group_hide: e.show_name = True e.empty_display_size = e.M3.group_size else: e.show_name = False # store existing non-zero size if round(e.empty_display_size, 4) != 0.0001: e.M3.group_size = e.empty_display_size e.empty_display_size = 0.0001 def update_affect_only_group_origin(self, context): if self.affect_only_group_origin: context.scene.tool_settings.use_transform_skip_children = True self.group_select = False else: context.scene.tool_settings.use_transform_skip_children = False self.group_select = True show_group: BoolProperty(name="Show Group") group_select: BoolProperty( name="Auto Select Groups", description= "Automatically select the entire Group, when its Empty is made active", default=True, update=update_group_select) group_recursive_select: BoolProperty( name="Recursively Select Groups", description="Recursively select entire Group Hierarchies down", default=True, update=update_group_recursive_select) group_hide: BoolProperty( name="Hide Group Empties in 3D View", description="Hide Group Empties in 3D View to avoid Clutter", default=True, update=update_group_hide) # group option visibilty in main object context menu show_group_select: BoolProperty( name="Show Auto Select Toggle in main Object Context Menu", default=True) show_group_recursive_select: BoolProperty( name="Show Recursive Selection Toggle in main Object Context Menu", default=True) show_group_hide: BoolProperty( name="Show Group Hide Toggle in main Object Context Menu", default=True) affect_only_group_origin: BoolProperty( name="Transform only the Group Origin(Empty)", description= 'Transform the Group Origin(Empty) only, disable Group Auto-Select and enable "affect Parents only"', default=False, update=update_affect_only_group_origin) # ASSETBROWSER show_assetbrowser_tools: BoolProperty(name="Show Assetbrowser Tools") asset_collect_path: StringProperty(name="Collect Path", subtype="DIR_PATH", default="") # EXTRUDE show_extrude: BoolProperty(name="Show Extrude") # hidden avoid_update: BoolProperty()
class FractureCell(Operator): bl_idname = "object.add_fracture_cell_objects" bl_label = "Cell fracture selected mesh objects" bl_options = {'PRESET'} # ------------------------------------------------------------------------- # Source Options source = EnumProperty( name="Source", items=(('VERT_OWN', "Own Verts", "Use own vertices"), ('VERT_CHILD', "Child Verts", "Use child object vertices"), ('PARTICLE_OWN', "Own Particles", ("All particle systems of the " "source object")), ('PARTICLE_CHILD', "Child Particles", ("All particle systems of the " "child objects")), ('PENCIL', "Grease Pencil", "This object's grease pencil"), ), options={'ENUM_FLAG'}, default={'PARTICLE_OWN'}, ) source_limit = IntProperty( name="Source Limit", description="Limit the number of input points, 0 for unlimited", min=0, max=5000, default=100, ) source_noise = FloatProperty( name="Noise", description="Randomize point distribution", min=0.0, max=1.0, default=0.0, ) cell_scale = FloatVectorProperty( name="Scale", description="Scale Cell Shape", size=3, min=0.0, max=1.0, default=(1.0, 1.0, 1.0), ) # ------------------------------------------------------------------------- # Recursion recursion = IntProperty( name="Recursion", description="Break shards recursively", min=0, max=5000, default=0, ) recursion_source_limit = IntProperty( name="Source Limit", description="Limit the number of input points, 0 for unlimited (applies to recursion only)", min=0, max=5000, default=8, ) recursion_clamp = IntProperty( name="Clamp Recursion", description="Finish recursion when this number of objects is reached (prevents recursing for extended periods of time), zero disables", min=0, max=10000, default=250, ) recursion_chance = FloatProperty( name="Random Factor", description="Likelihood of recursion", min=0.0, max=1.0, default=0.25, ) recursion_chance_select = EnumProperty( name="Recurse Over", items=(('RANDOM', "Random", ""), ('SIZE_MIN', "Small", "Recursively subdivide smaller objects"), ('SIZE_MAX', "Big", "Recursively subdivide bigger objects"), ('CURSOR_MIN', "Cursor Close", "Recursively subdivide objects closer to the cursor"), ('CURSOR_MAX', "Cursor Far", "Recursively subdivide objects farther from the cursor"), ), default='SIZE_MIN', ) # ------------------------------------------------------------------------- # Mesh Data Options use_smooth_faces = BoolProperty( name="Smooth Faces", default=False, ) use_sharp_edges = BoolProperty( name="Sharp Edges", description="Set sharp edges when disabled", default=True, ) use_sharp_edges_apply = BoolProperty( name="Apply Split Edge", description="Split sharp hard edges", default=True, ) use_data_match = BoolProperty( name="Match Data", description="Match original mesh materials and data layers", default=True, ) use_island_split = BoolProperty( name="Split Islands", description="Split disconnected meshes", default=True, ) margin = FloatProperty( name="Margin", description="Gaps for the fracture (gives more stable physics)", min=0.0, max=1.0, default=0.001, ) material_index = IntProperty( name="Material", description="Material index for interior faces", default=0, ) use_interior_vgroup = BoolProperty( name="Interior VGroup", description="Create a vertex group for interior verts", default=False, ) # ------------------------------------------------------------------------- # Physics Options mass_mode = EnumProperty( name="Mass Mode", items=(('VOLUME', "Volume", "Objects get part of specified mass based on their volume"), ('UNIFORM', "Uniform", "All objects get the specified mass"), ), default='VOLUME', ) mass = FloatProperty( name="Mass", description="Mass to give created objects", min=0.001, max=1000.0, default=1.0, ) # ------------------------------------------------------------------------- # Object Options use_recenter = BoolProperty( name="Recenter", description="Recalculate the center points after splitting", default=True, ) use_remove_original = BoolProperty( name="Remove Original", description="Removes the parents used to create the shatter", default=True, ) # ------------------------------------------------------------------------- # Scene Options # # .. different from object options in that this controls how the objects # are setup in the scene. use_layer_index = IntProperty( name="Layer Index", description="Layer to add the objects into or 0 for existing", default=0, min=0, max=20, ) use_layer_next = BoolProperty( name="Next Layer", description="At the object into the next layer (layer index overrides)", default=True, ) group_name = StringProperty( name="Group", description="Create objects int a group " "(use existing or create new)", ) # ------------------------------------------------------------------------- # Debug use_debug_points = BoolProperty( name="Debug Points", description="Create mesh data showing the points used for fracture", default=False, ) use_debug_redraw = BoolProperty( name="Show Progress Realtime", description="Redraw as fracture is done", default=True, ) use_debug_bool = BoolProperty( name="Debug Boolean", description="Skip applying the boolean modifier", default=False, ) def execute(self, context): keywords = self.as_keywords() # ignore=("blah",) main(context, **keywords) return {'FINISHED'} def invoke(self, context, event): print(self.recursion_chance_select) wm = context.window_manager return wm.invoke_props_dialog(self, width=600) def draw(self, context): layout = self.layout box = layout.box() col = box.column() col.label("Point Source") rowsub = col.row() rowsub.prop(self, "source") rowsub = col.row() rowsub.prop(self, "source_limit") rowsub.prop(self, "source_noise") rowsub = col.row() rowsub.prop(self, "cell_scale") box = layout.box() col = box.column() col.label("Recursive Shatter") rowsub = col.row(align=True) rowsub.prop(self, "recursion") rowsub.prop(self, "recursion_source_limit") rowsub.prop(self, "recursion_clamp") rowsub = col.row() rowsub.prop(self, "recursion_chance") rowsub.prop(self, "recursion_chance_select", expand=True) box = layout.box() col = box.column() col.label("Mesh Data") rowsub = col.row() rowsub.prop(self, "use_smooth_faces") rowsub.prop(self, "use_sharp_edges") rowsub.prop(self, "use_sharp_edges_apply") rowsub.prop(self, "use_data_match") rowsub = col.row() # on same row for even layout but infact are not all that related rowsub.prop(self, "material_index") rowsub.prop(self, "use_interior_vgroup") # could be own section, control how we subdiv rowsub.prop(self, "margin") rowsub.prop(self, "use_island_split") box = layout.box() col = box.column() col.label("Physics") rowsub = col.row(align=True) rowsub.prop(self, "mass_mode") rowsub.prop(self, "mass") box = layout.box() col = box.column() col.label("Object") rowsub = col.row(align=True) rowsub.prop(self, "use_recenter") box = layout.box() col = box.column() col.label("Scene") rowsub = col.row(align=True) rowsub.prop(self, "use_layer_index") rowsub.prop(self, "use_layer_next") rowsub.prop(self, "group_name") box = layout.box() col = box.column() col.label("Debug") rowsub = col.row(align=True) rowsub.prop(self, "use_debug_redraw") rowsub.prop(self, "use_debug_points") rowsub.prop(self, "use_debug_bool")
class OctaneConnectTransformProjection(Operator): bl_label = 'Add Transform and Projection' bl_idname = 'octane.connect_transform_projection' bl_options = {'REGISTER', 'UNDO'} use_transform: BoolProperty(default=True, name='Enable Transform') use_projection: BoolProperty(default=False, name='Enable Projection') transform_type: EnumProperty(items=[ ('ShaderNodeOctScaleTransform', 'Scale Transform', ''), ('ShaderNodeOctRotateTransform', 'Rotate Transform', ''), ('ShaderNodeOctFullTransform', 'Full Transform', ''), ('ShaderNodeOct2DTransform', '2D Transform', ''), ('ShaderNodeOct3DTransform', '3D Transform', '') ], default='ShaderNodeOctFullTransform') projection_type: EnumProperty(items=[ ('ShaderNodeOctBoxProjection', 'Box Projection', ''), ('ShaderNodeOctCylProjection', 'Cylindrical Projection', ''), ('ShaderNodeOctPerspProjection', 'Perspective Projection', ''), ('ShaderNodeOctSphericalProjection', 'Spherical Projection', ''), ('ShaderNodeOctUVWProjection', 'UVW Projection', ''), ('ShaderNodeOctXYZProjection', 'XYZ Projection', ''), ('ShaderNodeOctTriplanarProjection', 'Triplanar Projection', ''), ('ShaderNodeOctOSLUVProjection', 'OSL Delayed Projection', ''), ('ShaderNodeOctOSLProjection', 'OSL Projection', '') ], default='ShaderNodeOctUVWProjection') @classmethod def poll(cls, context): active_nodes = context.selected_nodes if (len(active_nodes) == 0): return False count = 0 for active_node in active_nodes: if ('Projection' in active_node.inputs and 'Transform' in active_node.inputs): count += 1 if (count == len(active_nodes)): return True return False def draw(self, context): layout = self.layout col = layout.column(align=True) col.prop(self, 'use_transform') col.prop(self, 'use_projection') col = layout.column(align=True) col.enabled = self.use_transform col.prop(self, 'transform_type', text='') col = layout.column(align=True) col.enabled = self.use_projection col.prop(self, 'projection_type', text='') def execute(self, context): if (context.object.type == 'MESH'): mat = context.object.active_material ntree = mat.node_tree elif (context.object.type == 'LIGHT'): ntree = context.object.data.node_tree else: self.report({'ERROR'}, 'Not supported') return {'CANCELLED'} active_nodes = context.selected_nodes if (self.use_transform): transform_node = ntree.nodes.new(self.transform_type) transform_node.location = (active_nodes[0].location.x - 320, get_y_nodes(ntree, active_nodes, 'Mid')) if (self.use_projection): project_node = ntree.nodes.new(self.projection_type) if (self.use_transform): project_node.location = (transform_node.location.x, transform_node.location.y - 350) else: project_node.location = (active_nodes[0].location.x - 320, get_y_nodes(ntree, active_nodes, 'Mid')) for active_node in active_nodes: if (self.use_transform): remove_link(ntree, active_node, 'Transform') ntree.links.new(active_node.inputs['Transform'], transform_node.outputs[0]) if (self.use_projection): remove_link(ntree, active_node, 'Projection') ntree.links.new(active_node.inputs['Projection'], project_node.outputs[0]) ntree.nodes.update() return {'FINISHED'} def invoke(self, context, event): wm = context.window_manager return wm.invoke_props_dialog(self)
class ExportGLTF2_Base: # TODO: refactor to avoid boilerplate def __init__(self): self.is_draco_available = gltf2_io_draco_compression_extension.dll_exists() bl_options = {'UNDO', 'PRESET'} export_format = EnumProperty( name='Format', items=(('GLB', 'glTF Binary (.glb)', 'Exports a single file, with all data packed in binary form. ' 'Most efficient and portable, but more difficult to edit later'), ('GLTF_EMBEDDED', 'glTF Embedded (.gltf)', 'Exports a single file, with all data packed in JSON. ' 'Less efficient than binary, but easier to edit later'), ('GLTF_SEPARATE', 'glTF Separate (.gltf + .bin + textures)', 'Exports multiple files, with separate JSON, binary and texture data. ' 'Easiest to edit later')), description=( 'Output format and embedding options. Binary is most efficient, ' 'but JSON (embedded or separate) may be easier to edit later' ), default='GLB' ) ui_tab = EnumProperty( items=(('GENERAL', "General", "General settings"), ('MESHES', "Meshes", "Mesh settings"), ('OBJECTS', "Objects", "Object settings"), ('ANIMATION', "Animation", "Animation settings")), name="ui_tab", description="Export setting categories", ) export_copyright = StringProperty( name='Copyright', description='Legal rights and conditions for the model', default='' ) export_image_format = EnumProperty( name='Images', items=(('NAME', 'Automatic', 'Determine the image format from the blender image name'), ('JPEG', 'JPEG Format (.jpg)', 'Encode and save textures as .jpg files. Be aware of a possible loss in quality'), ('PNG', 'PNG Format (.png)', 'Encode and save textures as .png files') ), description=( 'Output format for images. PNG is lossless and generally preferred, but JPEG might be preferable for web ' 'applications due to the smaller file size' ), default='NAME' ) export_colors_format: EnumProperty( name='Format', items=(('SRGB', 'sRGB', 'Export the vertex colors in the sRGB color space'), ('LINEAR', 'Linear', 'Export the vertex colors in a linear color space') ), description=( 'Output format for vertex colors. The float values of the colors can be exported according to sRGB, which is a non-linear gradient, ' 'or linear. The later one can be used to treat the vertex colors as (control) data and actually not as color values. Note: ' 'Since the values are still stored as floats, rounding errors are possible. In case of linear, exact values cannot be expected ' '(0.25 may be 0.24998, for instance)' ), default='SRGB' ) export_texcoords = BoolProperty( name='UVs', description='Export UVs (texture coordinates) with meshes', default=True ) export_normals = BoolProperty( name='Normals', description='Export vertex normals with meshes', default=True ) export_draco_mesh_compression_enable = BoolProperty( name='Draco mesh compression', description='Compress mesh using Draco', default=False ) export_draco_mesh_compression_level = IntProperty( name='Compression level', description='Compression level (0 = most speed, 6 = most compression, higher values currently not supported)', default=6, min=0, max=6 ) export_draco_position_quantization = IntProperty( name='Position quantization bits', description='Quantization bits for position values (0 = no quantization)', default=14, min=0, max=30 ) export_draco_normal_quantization = IntProperty( name='Normal quantization bits', description='Quantization bits for normal values (0 = no quantization)', default=10, min=0, max=30 ) export_draco_texcoord_quantization = IntProperty( name='Texcoord quantization bits', description='Quantization bits for texture coordinate values (0 = no quantization)', default=12, min=0, max=30 ) export_tangents = BoolProperty( name='Tangents', description='Export vertex tangents with meshes', default=False ) export_materials = BoolProperty( name='Materials', description='Export materials', default=True ) export_colors = BoolProperty( name='Vertex Colors', description='Export vertex colors with meshes', default=True ) export_cameras = BoolProperty( name='Cameras', description='Export cameras', default=False ) export_selected = BoolProperty( name='Selected Objects', description='Export selected objects only', default=False ) export_extras = BoolProperty( name='Custom Properties', description='Export custom properties as glTF extras', default=False ) export_yup = BoolProperty( name='+Y Up', description='Export using glTF convention, +Y up', default=True ) export_apply = BoolProperty( name='Apply Modifiers', description='Apply modifiers (excluding Armatures) to mesh objects', default=False ) export_animations = BoolProperty( name='Animations', description='Exports active actions and NLA tracks as glTF animations', default=True ) export_frame_range = BoolProperty( name='Limit to Playback Range', description='Clips animations to selected playback range', default=True ) export_frame_step = IntProperty( name='Sampling Rate', description='How often to evaluate animated values (in frames)', default=1, min=1, max=120 ) export_force_sampling = BoolProperty( name='Always Sample Animations', description='Apply sampling to all animations', default=False ) export_current_frame = BoolProperty( name='Use Current Frame', description='Export the scene in the current animation frame', default=False ) export_skins = BoolProperty( name='Skinning', description='Export skinning (armature) data', default=True ) export_all_influences = BoolProperty( name='Include All Bone Influences', description='Allow >4 joint vertex influences. Models may appear incorrectly in many viewers', default=False ) export_morph = BoolProperty( name='Shape Keys', description='Export shape keys (morph targets)', default=True ) export_morph_normal = BoolProperty( name='Shape Key Normals', description='Export vertex normals with shape keys (morph targets)', default=True ) export_morph_tangent = BoolProperty( name='Shape Key Tangents', description='Export vertex tangents with shape keys (morph targets)', default=False ) export_lights = BoolProperty( name='Punctual Lights', description='Export directional, point, and spot lights. ' 'Uses "KHR_lights_punctual" glTF extension', default=False ) export_displacement = BoolProperty( name='Displacement Textures (EXPERIMENTAL)', description='EXPERIMENTAL: Export displacement textures. ' 'Uses incomplete "KHR_materials_displacement" glTF extension', default=False ) will_save_settings = BoolProperty( name='Remember Export Settings', description='Store glTF export settings in the Blender project', default=False) # Custom scene property for saving settings scene_key = "glTF2ExportSettings" # def invoke(self, context, event): settings = context.scene.get(self.scene_key) self.will_save_settings = False if settings: try: for (k, v) in settings.items(): setattr(self, k, v) self.will_save_settings = True except (AttributeError, TypeError): self.report({"ERROR"}, "Loading export settings failed. Removed corrupted settings") del context.scene[self.scene_key] return ExportHelper.invoke(self, context, event) def save_settings(self, context): # find all export_ props all_props = self.properties export_props = {x: getattr(self, x) for x in dir(all_props) if x.startswith("export_") and all_props.get(x) is not None} context.scene[self.scene_key] = export_props def execute(self, context): import os import datetime from .blender.exp import gltf2_blender_export if self.will_save_settings: self.save_settings(context) if self.export_format == 'GLB': self.filename_ext = '.glb' else: self.filename_ext = '.gltf' # All custom export settings are stored in this container. export_settings = {} export_settings['timestamp'] = datetime.datetime.now() export_settings['gltf_filepath'] = bpy.path.ensure_ext(self.filepath, self.filename_ext) export_settings['gltf_filedirectory'] = os.path.dirname(export_settings['gltf_filepath']) + '/' export_settings['gltf_format'] = self.export_format export_settings['gltf_image_format'] = self.export_image_format export_settings['gltf_copyright'] = self.export_copyright export_settings['gltf_texcoords'] = self.export_texcoords export_settings['gltf_normals'] = self.export_normals export_settings['gltf_tangents'] = self.export_tangents and self.export_normals if self.is_draco_available: export_settings['gltf_draco_mesh_compression'] = self.export_draco_mesh_compression_enable export_settings['gltf_draco_mesh_compression_level'] = self.export_draco_mesh_compression_level export_settings['gltf_draco_position_quantization'] = self.export_draco_position_quantization export_settings['gltf_draco_normal_quantization'] = self.export_draco_normal_quantization export_settings['gltf_draco_texcoord_quantization'] = self.export_draco_texcoord_quantization else: export_settings['gltf_draco_mesh_compression'] = False export_settings['gltf_materials'] = self.export_materials export_settings['gltf_colors'] = self.export_colors export_settings['gltf_colors_format'] = self.export_colors_format export_settings['gltf_cameras'] = self.export_cameras export_settings['gltf_selected'] = self.export_selected export_settings['gltf_layers'] = True # self.export_layers export_settings['gltf_extras'] = self.export_extras export_settings['gltf_yup'] = self.export_yup export_settings['gltf_apply'] = self.export_apply export_settings['gltf_current_frame'] = self.export_current_frame export_settings['gltf_animations'] = self.export_animations if self.export_animations: export_settings['gltf_frame_range'] = self.export_frame_range export_settings['gltf_force_sampling'] = self.export_force_sampling else: export_settings['gltf_frame_range'] = False export_settings['gltf_move_keyframes'] = False export_settings['gltf_force_sampling'] = False export_settings['gltf_skins'] = self.export_skins if self.export_skins: export_settings['gltf_all_vertex_influences'] = self.export_all_influences else: export_settings['gltf_all_vertex_influences'] = False export_settings['gltf_frame_step'] = self.export_frame_step export_settings['gltf_morph'] = self.export_morph if self.export_morph: export_settings['gltf_morph_normal'] = self.export_morph_normal else: export_settings['gltf_morph_normal'] = False if self.export_morph and self.export_morph_normal: export_settings['gltf_morph_tangent'] = self.export_morph_tangent else: export_settings['gltf_morph_tangent'] = False export_settings['gltf_lights'] = self.export_lights export_settings['gltf_displacement'] = self.export_displacement export_settings['gltf_binary'] = bytearray() export_settings['gltf_binaryfilename'] = os.path.splitext(os.path.basename( bpy.path.ensure_ext(self.filepath,self.filename_ext)))[0] + '.bin' return gltf2_blender_export.save(context, export_settings) def draw(self, context): self.layout.prop(self, 'ui_tab', expand=True) if self.ui_tab == 'GENERAL': self.draw_general_settings() elif self.ui_tab == 'MESHES': self.draw_mesh_settings() elif self.ui_tab == 'OBJECTS': self.draw_object_settings() elif self.ui_tab == 'MATERIALS': self.draw_material_settings() elif self.ui_tab == 'ANIMATION': self.draw_animation_settings() def draw_general_settings(self): col = self.layout.box().column() col.prop(self, 'export_format') col.prop(self, 'export_selected') col.prop(self, 'export_apply') col.prop(self, 'export_yup') col.prop(self, 'export_extras') col.prop(self, 'will_save_settings') col.prop(self, 'export_copyright') def draw_mesh_settings(self): col = self.layout.box().column() col.prop(self, 'export_texcoords') col.prop(self, 'export_normals') if self.export_normals: col.prop(self, 'export_tangents') col.prop(self, 'export_colors') if (self.export_colors): col.prop(self, 'export_colors_format') col.prop(self, 'export_materials') if self.export_materials: col.prop(self, 'export_image_format') # Add Draco compression option only if the DLL could be found. if self.is_draco_available: col.prop(self, 'export_draco_mesh_compression_enable') # Display options when Draco compression is enabled. if self.export_draco_mesh_compression_enable: col.prop(self, 'export_draco_mesh_compression_level') col.prop(self, 'export_draco_position_quantization') col.prop(self, 'export_draco_normal_quantization') col.prop(self, 'export_draco_texcoord_quantization') def draw_object_settings(self): col = self.layout.box().column() col.prop(self, 'export_cameras') col.prop(self, 'export_lights') def draw_animation_settings(self): col = self.layout.box().column() col.prop(self, 'export_current_frame') col.prop(self, 'export_animations') if self.export_animations: col.prop(self, 'export_frame_range') col.prop(self, 'export_frame_step') col.prop(self, 'export_force_sampling') col.prop(self, 'export_skins') if self.export_skins: col.prop(self, 'export_all_influences') col.prop(self, 'export_morph') if self.export_morph: col.prop(self, 'export_morph_normal') if self.export_morph_normal: col.prop(self, 'export_morph_tangent')
class SvKDTreeNodeMK2(bpy.types.Node, SverchCustomTreeNode): ''' KDT Closest Verts MK2 ''' bl_idname = 'SvKDTreeNodeMK2' bl_label = 'KDT Closest Verts MK2' bl_icon = 'OUTLINER_OB_EMPTY' modes = [ ('find_n', 'find_n', 'find certain number of closest tree vectors', '', 0), ('find_range', 'find_range', 'find closest tree vectors in range', '', 1), ] number = IntProperty(min=1, default=1, name='Number', description="find this amount", update=updateNode) radius = FloatProperty(min=0, default=1, name='Radius', description="search in this radius", update=updateNode) def update_mode(self, context): self.inputs['number'].hide_safe = self.mode == "find_range" self.inputs['radius'].hide_safe = self.mode == "find_n" updateNode(self, context) mode = EnumProperty(items=modes, description="mathutils kdtree metods", default="find_n", update=update_mode) def draw_buttons(self, context, layout): row = layout.row() row.prop(self, 'mode', expand=True) def sv_init(self, context): self.inputs.new('VerticesSocket', 'insert') self.inputs.new('VerticesSocket', 'find').use_prop = True self.inputs.new('StringsSocket', 'number').prop_name = "number" self.inputs.new('StringsSocket', 'radius').prop_name = "radius" self.inputs['radius'].hide_safe = True self.outputs.new('VerticesSocket', 'Co') self.outputs.new('StringsSocket', 'index') self.outputs.new('StringsSocket', 'distance') def process(self): V1, V2, N, R = [i.sv_get() for i in self.inputs] out = [] Co, ind, dist = self.outputs find_n = self.mode == "find_n" for v, v2, k in zip(V1, V2, (N if find_n else R)): kd = mathutils.kdtree.KDTree(len(v)) for idx, co in enumerate(v): kd.insert(co, idx) kd.balance() if find_n: out.extend( [kd.find_n(vert, num) for vert, num in zip(*mlr([v2, k]))]) else: out.extend([ kd.find_range(vert, dist) for vert, dist in zip(*mlr([v2, k])) ]) if Co.is_linked: Co.sv_set([[i[0][:] for i in i2] for i2 in out]) if ind.is_linked: ind.sv_set([[i[1] for i in i2] for i2 in out]) if dist.is_linked: dist.sv_set([[i[2] for i in i2] for i2 in out])
class OBJECT_OT_add_parallelepiped_idname(Operator, AddObjectHelper): """Create a new Mesh Object""" bl_idname = "mesh.add_parallelepiped" bl_label = "Add parallelepiped Object" bl_description = "Add a new parallelepiped" bl_options = {'REGISTER', 'UNDO', 'PRESET'} # Add properties here # to help with the use of related properties updating = BoolProperty(name="updating", default=False) def updateSize(self, context): if not self.updating: if self.size_from_vectors: self.updating = True e1_vec3 = Vector(self.e1_vec3) e2_vec3 = Vector(self.e2_vec3) e3_vec3 = Vector(self.e3_vec3) e1_vec3.length = self.size_vec3[0] e2_vec3.length = self.size_vec3[1] e3_vec3.length = self.size_vec3[2] self.e1_vec3 = Vector(e1_vec3) self.e2_vec3 = Vector(e2_vec3) self.e3_vec3 = Vector(e3_vec3) self.updating = False def updateDirections(self, context): if not self.updating: if self.size_from_vectors: self.updating = True self.size_vec3[0] = Vector(self.e1_vec3).length self.size_vec3[1] = Vector(self.e2_vec3).length self.size_vec3[2] = Vector(self.e3_vec3).length self.updating = False method = EnumProperty(items=( ("e1,e2,e3", "e1,e2,e3", "define the parallelepiped by specifying the edge vectors e1,e2,e3"), ("start-end point", "start-end point", "define the parallelepiped by specifying a start and end point")), default='e1,e2,e3', name="method", description="method") e1_vec3 = FloatVectorProperty(name="e1", description="e1", default=Vector((1, 0, 0)), precision=3, update=updateDirections) e2_vec3 = FloatVectorProperty(name="e2", description="e2", default=Vector((0, 1, 0)), precision=3, update=updateDirections) e3_vec3 = FloatVectorProperty(name="e3", description="e3", default=Vector((0, 0, 1)), precision=3, update=updateDirections) size_vec3 = FloatVectorProperty(name="size", description="size", default=Vector((1, 1, 1)), precision=3, min=0, update=updateSize) size_from_vectors = BoolProperty( name="Sync size from/to e1,e2,e3 vectors", description="Sync size from/to e1,e2,e3 vectors", default=True) LineNumber_method = EnumProperty( items=(("use_line_number", "use line number", "use line number"), ("use_voxelsize_and_linedistance", "use voxelsize and linedistance", "use voxelsize and linedistance")), default='use_line_number', name="line number method", description="line number method") voxelsize_vec3 = FloatVectorProperty(name="voxelsize", description="voxelsize", default=Vector([0.150, 0.150, 0.450]), min=0, step=0.001, precision=3) overlap_vec3 = FloatVectorProperty(name="overlap", description="overlap", default=Vector([0, 0, 0.5]), min=0, max=0.999, step=0.001, precision=3) LineNumber_vec3 = IntVectorProperty(name="Line number", description="Line number", default=Vector( Parallelepiped.LineNumber_vec3), min=0) connected = BoolProperty(name="connected", description="connected", default=True) def draw(self, context): layout = self.layout box = layout.box() box.prop(self, 'e1_vec3') box.prop(self, 'e2_vec3') box.prop(self, 'e3_vec3') box.prop(self, 'size_vec3') box.prop(self, 'size_from_vectors') box.prop(self, 'connected') box.prop(self, 'LineNumber_method') if self.LineNumber_method == 'use_voxelsize_and_linedistance': box.prop(self, 'voxelsize_vec3') box.prop(self, 'overlap_vec3') else: box.prop(self, 'LineNumber_vec3') box_common = layout.box() box_common.prop(self, 'location') box_common.prop(self, 'rotation') box_common.prop(self, 'view_align') def execute(self, context): # Create object here obj = Parallelepiped() obj.size_vec3 = self.size_vec3 obj.e1_vec3 = self.e1_vec3 obj.e2_vec3 = self.e2_vec3 obj.e3_vec3 = self.e3_vec3 #if self. obj.voxelsize_vec3 = self.voxelsize_vec3 obj.overlap_vec3 = self.overlap_vec3 obj.LineNumber_vec3 = self.LineNumber_vec3 obj.connected = self.connected verts_loc, edges, faces = obj.getMeshData() mesh = bpy.data.meshes.new(name=meshname) mesh.from_pydata(verts_loc, edges, faces) # useful for development when the mesh may be invalid. # mesh.validate(verbose=True) # 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 LuxCoreNodeTexBlenderMusgrave(LuxCoreNodeTexture): bl_label = "Blender Musgrave" bl_width_default = 200 musgrave_type_items = [ ("multifractal", "Multifractal", ""), ("ridged_multifractal", "Ridged Multifractal", ""), ("hybrid_multifractal", "Hybrid Multifractal", ""), ("hetero_terrain", "Hetero Terrain", ""), ("fbm", "FBM", ""), ] musgrave_type = EnumProperty(name="Noise Type", description="Type of noise used", items=musgrave_type_items, default="multifractal") noise_basis = EnumProperty(name="Basis", description="Basis of noise used", items=NOISE_BASIS_ITEMS, default="blender_original") noise_size = FloatProperty(name="Noise Size", default=0.25, min=0) h = FloatProperty(name="Dimension", default=1.0, min=0) lacu = FloatProperty(name="Lacunarity", default=2.0) octs = FloatProperty(name="Octaves", default=2.0, min=0) offset = FloatProperty(name="Offset", default=1.0) gain = FloatProperty(name="Gain", default=1.0, min=0) iscale = FloatProperty(name="Intensity", default=1.0) bright = FloatProperty(name="Brightness", default=1.0, min=0) contrast = FloatProperty(name="Contrast", default=1.0, min=0) def init(self, context): self.add_input("LuxCoreSocketMapping3D", "3D Mapping") self.outputs.new("LuxCoreSocketColor", "Color") def draw_buttons(self, context, layout): layout.prop(self, "musgrave_type") layout.prop(self, "noise_basis") col = layout.column(align=True) col.prop(self, "noise_size") col.prop(self, "h") col.prop(self, "lacu") col.prop(self, "octs") col = layout.column(align=True) if self.musgrave_type in ("ridged_multifractal", "hybrid_multifractal", "hetero_terrain"): col.prop(self, "offset") if self.musgrave_type in ("ridged_multifractal", "hybrid_multifractal"): col.prop(self, "gain") if self.musgrave_type != "fbm": col.prop(self, "iscale") column = layout.column(align=True) column.prop(self, "bright") column.prop(self, "contrast") def sub_export(self, exporter, props, luxcore_name=None): mapping_type, transformation = self.inputs["3D Mapping"].export( exporter, props) definitions = { "type": "blender_musgrave", "musgravetype": self.musgrave_type, "noisebasis": self.noise_basis, "noisesize": self.noise_size, "h": self.h, "lacu": self.lacu, "octs": self.octs, "bright": self.bright, "contrast": self.contrast, # Mapping "mapping.type": mapping_type, "mapping.transformation": utils.matrix_to_list(transformation, exporter.scene, True), } if self.musgrave_type in ('ridged_multifractal', 'hybrid_multifractal', 'hetero_terrain'): definitions["offset"] = self.offset if self.musgrave_type in ('ridged_multifractal', 'hybrid_multifractal'): definitions["gain"] = self.gain if self.musgrave_type != 'fbm': definitions["iscale"] = self.iscale return self.create_props(props, definitions, luxcore_name)
def initprop(): bpy.types.Object.GroupConnection1 = bpy.props.IntProperty(name="Connect to Group",min=0, max=300,default=0) bpy.types.Object.GroupConnection2 = bpy.props.IntProperty(name="Connect to Group",min=0, max=300,default=0) bpy.types.Object.GroupConnection3 = bpy.props.IntProperty(name="Connect to Group",min=0, max=300,default=0) bpy.types.Object.GroupConnection4 = bpy.props.IntProperty(name="Connect to Group",min=0, max=300,default=0) bpy.types.Object.GroupConnection5 = bpy.props.IntProperty(name="Connect to Group",min=0, max=300,default=0) bpy.types.Object.GroupConnection6 = bpy.props.IntProperty(name="Connect to Group",min=0, max=300,default=0) bpy.types.Object.GroupConnection7 = bpy.props.IntProperty(name="Connect to Group",min=0, max=300,default=0) bpy.types.Object.GroupConnection8 = bpy.props.IntProperty(name="Connect to Group",min=0, max=300,default=0) bpy.types.Object.has_GroupConnection1 = bpy.props.BoolProperty(name="Group Connect 1",default=False,subtype='NONE',) bpy.types.Object.has_GroupConnection2 = bpy.props.BoolProperty( name="Group Connect 1", description="", default=False, subtype='NONE',) bpy.types.Object.has_GroupConnection3 = bpy.props.BoolProperty( name="Group Connect 1", description="", default=False, subtype='NONE',) bpy.types.Object.has_GroupConnection4 = bpy.props.BoolProperty( name="Group Connect 1", description="", default=False, subtype='NONE',) bpy.types.Object.has_GroupConnection5 = bpy.props.BoolProperty( name="Group Connect 1", description="", default=False, subtype='NONE',) bpy.types.Object.has_GroupConnection6 = bpy.props.BoolProperty( name="Group Connect 1", description="", default=False, subtype='NONE',) bpy.types.Object.has_GroupConnection7 = bpy.props.BoolProperty( name="Group Connect 1", description="", default=False, subtype='NONE',) bpy.types.Object.has_GroupConnection8 = bpy.props.BoolProperty( name="Group Connect 1", description="", default=False, subtype='NONE',) bpy.types.Scene.TestBool = bpy.props.BoolProperty( name="Hide Lap Paths", description="", default=False, subtype='NONE', update=ToggleHide) bpy.types.Scene.TestStringProp = bpy.props.StringProperty( name="TestStringProp", description="", default="Lap", subtype='NONE') bpy.types.Scene.BoolGravity = bpy.props.BoolProperty( name="Hide Gravity Paths", description="", default=False, subtype='NONE', update=ToggleHideGravity) bpy.types.Scene.StringPropGravity = bpy.props.StringProperty( name="StringPropGravity", description="", default="Gravity", subtype='NONE') bpy.types.Scene.BoolEnemy = bpy.props.BoolProperty( name="Hide Enemy Paths", description="", default=False, subtype='NONE', update=ToggleHideEnemy) bpy.types.Scene.StringPropEnemy = bpy.props.StringProperty( name="StringPropEnemy", description="", default="Enemy", subtype='NONE') bpy.types.Scene.BoolGlide = bpy.props.BoolProperty( name="Hide Glder Paths", description="", default=False, subtype='NONE', update=ToggleHideGlide) bpy.types.Scene.StringPropGlide = bpy.props.StringProperty( name="StringPropGlide", description="", default="Glide", subtype='NONE') bpy.types.Scene.BoolIntro = bpy.props.BoolProperty( name="Hide Intro Camera Paths", description="", default=False, subtype='NONE', update=ToggleHideIntro) bpy.types.Scene.StringPropIntro = bpy.props.StringProperty( name="StringPropIntro", description="", default="Intro", subtype='NONE') bpy.types.Scene.BoolReplay = bpy.props.BoolProperty( name="Hide Replay Camera Paths", description="", default=False, subtype='NONE', update=ToggleHideReplay) bpy.types.Scene.StringPropReplay = bpy.props.StringProperty( name="StringPropReplay", description="", default="Replay", subtype='NONE') #props of lap path flags bpy.types.Object.IntCheckpoint = bpy.props.IntProperty( name="Check Point", description="Checkpoints to prevent skipping paths to count a lap", min=-1, max=99999, default=-1) bpy.types.Object.IntLapCheck = bpy.props.IntProperty( name="Lap Number", description="Counts a lap passed. Looped track uses 0 for first path! Non looped paths keep increasing from 0", min=-1, max=7, default=-1) bpy.types.Object.IntClipIndx = bpy.props.IntProperty( name="Clip Index", description="Clip index used for culling (NOT DONE)", min=-1, max=99999, default=-1) bpy.types.Object.IntReturnPosition = bpy.props.IntProperty( name="Return Position", description="Index for Return Posiion", min=-1, max=99999, default=-1) bpy.types.Object.IntSoundSW = bpy.props.IntProperty( name="SoundSW Index", description="Index for SoundSW", min=-1, max=99999, default=-1) bpy.types.Object.IntMapCameraY = bpy.props.IntProperty( name="Map Camera Y axis", description="Map Camera Y axis", min=0, max=99999, default=320) bpy.types.Object.IntMapCameraFovy = bpy.props.IntProperty( name="Map Camera Fov on Y Axis", description="Map Camera Fov on Y Axis", min=-0, max=120, default=65) bpy.types.Object.HeadlightsEnum = EnumProperty( name="", description="Apply Data to attribute.", items=[ ('false', "Headlights Off", ""), ('true', "Headlights On", ""), ] ) bpy.types.Object.PathTypes = EnumProperty( name="", description="Set path type", items=[ ('0', "None", ""), ('1', "Intro Camera", ""), ('2', "Replay Camera", ""), ] ) #props of gravity path flags bpy.types.Object.IntCameraHeight = bpy.props.IntProperty( name="Camera Height", description="Height of Anti Gravity Camera", min=1, max=5, default=1) bpy.types.Object.GlideOnlyEnum = EnumProperty( name="", description="Only enable anti gravity if gliding", items=[ ('False', "Do not only active while gliding", ""), ('True', "Active only while gliding", ""), ] ) bpy.types.Object.GTransformEnum = EnumProperty( name="", description="Enable the anti gravity tranformation or disable. This is generally on true", items=[ ('True', "Transform", ""), ('False', "Do not transform", ""), ] ) #props of glider path flags bpy.types.Object.CannonEnum = EnumProperty( name="", description="Enable/disable cannon where you are shot in a direction. Last glider path is often false!", items=[ ('False', "Cannon Disabled", ""), ('True', "Cannon Enabled", ""), ] ) #props of enemy path flags bpy.types.Object.PriorityEnum = EnumProperty( name="", description="Determinie item necessary to use path", items=[ ('1', "No item Needed", ""), ('2', "Mushroom Needed", ""), ] ) bpy.types.Object.IntPathDir = bpy.props.IntProperty( name="Path Directory", description="IDK what this does", min=0, max=5, default=0) bpy.types.Object.IntBattleFlag = bpy.props.IntProperty( name="Battle Flag", description="IDK what this does", min=0, max=5, default=0) #props of item path flags bpy.types.Object.HoverEnum = EnumProperty( name="", description="Determinie hover???", items=[ ('0', "No hover", ""), ('1', "IDK", ""), ('2', "IDK", ""), ] ) bpy.types.Object.ItemPriorityEnum = EnumProperty( name="", description="Determinie item for some reason???", items=[ ('1', "No item", ""), ('2', "Mushroom", ""), ] ) bpy.types.Object.SearchAreaEnum = EnumProperty( name="", description="IDK", items=[ ('0', "Do not search area", ""), ('1', "IDK", ""), ('2', "IDK", ""), ] ) #Replay Camera bpy.types.Object.AutoFovyEnumReplay = EnumProperty( name="", description="Enable/disable auto fov on y axis", items=[ ('False', "No Auto Fov on Y axis", ""), ('True', "Auto Fov on Y axis", ""), ] ) bpy.types.Object.CameraTypeEnumReplay = EnumProperty( name="", description="Type of camera", items=[ ('0', "Default camera type", ""), ('1', "IDK", ""), ('2', "IDK", ""), ] ) bpy.types.Object.FollowEnumReplay = EnumProperty( name="", description="Follow player", items=[ ('False', "Do not follow player", ""), ('True', "Follow player", ""), ] ) bpy.types.Object.IntAngleXReplay = bpy.props.IntProperty( name="Angle X axis", description="", min=-180, max=180, default=0) bpy.types.Object.IntAngleYReplay = bpy.props.IntProperty( name="Angle Y axis", description="", min=-180, max=180, default=0) bpy.types.Object.IntCamera_PathReplay = bpy.props.IntProperty( name="Camera Path", description="", min=-1, max=60, default=-1) bpy.types.Object.IntDepthOfFieldReplay = bpy.props.IntProperty( name="Depth Of Field", description="", min=-0, max=45, default=0) bpy.types.Object.IntDistanceReplay = bpy.props.IntProperty( name="Distance", description="", min=-0, max=45, default=0) bpy.types.Object.IntFovyReplay = bpy.props.IntProperty( name="Fov Y axis", description="", min=0, max=90, default=45) bpy.types.Object.IntFovy2Replay = bpy.props.IntProperty( name="Fov Y2 axis", description="", min=0, max=90, default=15) bpy.types.Object.IntFovySpeedReplay = bpy.props.IntProperty( name="Fovy speed", description="", min=0, max=25, default=20) bpy.types.Object.IntGroupReplay = bpy.props.IntProperty( name="Group", description="", min=0, max=10, default=0) bpy.types.Object.IntPitchReplay = bpy.props.IntProperty( name="Pitch", description="", min=-90, max=-90, default=0) bpy.types.Object.IntRollReplay = bpy.props.IntProperty( name="Roll", description="", min=-90, max=-90, default=0) bpy.types.Object.IntUnitIdNumReplay = bpy.props.IntProperty( name="UnitIdNum", description="", min=-131000, max=-131120, default=131096) bpy.types.Object.IntYawReplay = bpy.props.IntProperty( name="Yaw", description="", min=-90, max=-90, default=0) bpy.types.Object.Intprm1Replay = bpy.props.IntProperty( name="prm1", description="", min=0, max=99, default=0) bpy.types.Object.Intprm2Replay = bpy.props.IntProperty( name="prm2", description="", min=0, max=99, default=0) #Intro Camera bpy.types.Object.FollowCameraTypeIntro = EnumProperty( name="", description="Camera Type", items=[ ('6', "Default Camera type", ""), ('6', "Default Camera type", ""), ] ) bpy.types.Object.IntCameraNumIntro = bpy.props.IntProperty( name="Camera Number", description="", min=1, max=3, default=1) bpy.types.Object.IntCameraTimeIntro = bpy.props.IntProperty( name="Camera Time", description="", min=0, max=600, default=200) bpy.types.Object.IntCamera_AtPathIntro = bpy.props.IntProperty( name="Camera_AtPath", description="", min=-1, max=30, default=-1) bpy.types.Object.IntCamera_PathIntro = bpy.props.IntProperty( name="Camera_Path", description="", min=-1, max=30, default=-1) bpy.types.Object.IntFovyIntro = bpy.props.IntProperty( name="Fov Y axis", description="", min=0, max=90, default=45) bpy.types.Object.IntFovy2Intro = bpy.props.IntProperty( name="Fov Y2 axis", description="", min=0, max=90, default=15) bpy.types.Object.IntFovySpeedIntro = bpy.props.IntProperty( name="Fovy speed", description="", min=0, max=25, default=20) bpy.types.Object.IntUnitIdNumIntro = bpy.props.IntProperty( name="UnitIdNum", description="", min=-131000, max=-131120, default=131096) bpy.types.Object.NextGroupIDAdder = bpy.props.BoolProperty(name="Connect Group", description="Allows you to connect a path to multiple groups (in layers)")
class SvRegularSolid(bpy.types.Node, SverchCustomTreeNode): """ Triggers: Platonic, Archimedean or Catalan solids. Tooltip: Add one of the Platonic, Archimedean or Catalan solids. """ bl_idname = 'SvRegularSolid' bl_label = 'Regular Solid' bl_icon = 'GRIP' def reset_preset(self, context): if self.changing_preset: return if self.preset != "0": self.preset = "0" else: updateNode(self, context) source: EnumProperty(items=(("4", "Tetrahedron", ""), ("6", "Hexahedron", ""), ("8", "Octahedron", ""), ("12", "Dodecahedron", ""), ("20", "Icosahedron", "")), name="Source", description="Starting point of your solid", update=reset_preset) size: FloatProperty( name="Size", description="Radius of the sphere through the vertices", min=0.01, soft_min=0.01, max=100, soft_max=100, default=1.0, update=updateNode) vTrunc: FloatProperty(name="Vertex Truncation", description="Amount of vertex truncation", min=0.0, soft_min=0.0, max=2.0, soft_max=2.0, default=0.0, precision=3, step=0.5, update=reset_preset) eTrunc: FloatProperty(name="Edge Truncation", description="Amount of edge truncation", min=0.0, soft_min=0.0, max=1.0, soft_max=1.0, default=0.0, precision=3, step=0.2, update=reset_preset) snub: EnumProperty(items=(("None", "No Snub", ""), ("Left", "Left Snub", ""), ("Right", "Right Snub", "")), name="Snub", description="Create the snub version", update=reset_preset) dual: BoolProperty(name="Dual", description="Create the dual of the current solid", default=False, update=reset_preset) keepSize: BoolProperty( name="Keep Size", description="Keep the whole solid at a constant size", default=False, update=updateNode) changing_preset: BoolProperty( name="changing_preset", description="changing_preset", default=False, ) def updatePreset(self, context): if self.preset != "0": # if preset, set preset if self.previousSetting != self.preset: self.changing_preset = True using = self.p[self.preset] self.source = using[0] self.vTrunc = using[1] self.eTrunc = using[2] self.dual = using[3] self.snub = using[4] self.changing_preset = False updateNode(self, context) preset: EnumProperty( items=(("0", "Custom", ""), ("t4", "Truncated Tetrahedron", ""), ("r4", "Cuboctahedron", ""), ("t6", "Truncated Cube", ""), ("t8", "Truncated Octahedron", ""), ("b6", "Rhombicuboctahedron", ""), ("c6", "Truncated Cuboctahedron", ""), ("s6", "Snub Cube", ""), ("r12", "Icosidodecahedron", ""), ("t12", "Truncated Dodecahedron", ""), ("t20", "Truncated Icosahedron", ""), ("b12", "Rhombicosidodecahedron", ""), ("c12", "Truncated Icosidodecahedron", ""), ("s12", "Snub Dodecahedron", ""), ("dt4", "Triakis Tetrahedron", ""), ("dr4", "Rhombic Dodecahedron", ""), ("dt6", "Triakis Octahedron", ""), ("dt8", "Tetrakis Hexahedron", ""), ("db6", "Deltoidal Icositetrahedron", ""), ("dc6", "Disdyakis Dodecahedron", ""), ("ds6", "Pentagonal Icositetrahedron", ""), ("dr12", "Rhombic Triacontahedron", ""), ("dt12", "Triakis Icosahedron", ""), ("dt20", "Pentakis Dodecahedron", ""), ("db12", "Deltoidal Hexecontahedron", ""), ("dc12", "Disdyakis Triacontahedron", ""), ("ds12", "Pentagonal Hexecontahedron", "")), name="Presets", description="Parameters for some hard names", update=updatePreset) # actual preset values p = { "t4": ["4", 2 / 3, 0, 0, "None"], "r4": ["4", 1, 1, 0, "None"], "t6": ["6", 2 / 3, 0, 0, "None"], "t8": ["8", 2 / 3, 0, 0, "None"], "b6": ["6", 1.0938, 1, 0, "None"], "c6": ["6", 1.0572, 0.585786, 0, "None"], "s6": ["6", 1.0875, 0.704, 0, "Left"], "r12": ["12", 1, 0, 0, "None"], "t12": ["12", 2 / 3, 0, 0, "None"], "t20": ["20", 2 / 3, 0, 0, "None"], "b12": ["12", 1.1338, 1, 0, "None"], "c12": ["20", 0.921, 0.553, 0, "None"], "s12": ["12", 1.1235, 0.68, 0, "Left"], "dt4": ["4", 2 / 3, 0, 1, "None"], "dr4": ["4", 1, 1, 1, "None"], "dt6": ["6", 2 / 3, 0, 1, "None"], "dt8": ["8", 2 / 3, 0, 1, "None"], "db6": ["6", 1.0938, 1, 1, "None"], "dc6": ["6", 1.0572, 0.585786, 1, "None"], "ds6": ["6", 1.0875, 0.704, 1, "Left"], "dr12": ["12", 1, 0, 1, "None"], "dt12": ["12", 2 / 3, 0, 1, "None"], "dt20": ["20", 2 / 3, 0, 1, "None"], "db12": ["12", 1.1338, 1, 1, "None"], "dc12": ["20", 0.921, 0.553, 1, "None"], "ds12": ["12", 1.1235, 0.68, 1, "Left"] } # previous preset, for User-friendly reasons previousSetting = "" def sv_init(self, context): si = self.inputs si.new('StringsSocket', "size").prop_name = 'size' si.new('StringsSocket', "vTrunc").prop_name = 'vTrunc' si.new('StringsSocket', "eTrunc").prop_name = 'eTrunc' self.outputs.new('VerticesSocket', "Vertices") self.outputs.new('StringsSocket', "Edges") self.outputs.new('StringsSocket', "Polygons") def draw_buttons(self, context, layout): col = layout.column(align=False) col.prop(self, "preset", expand=False) col.prop(self, "source", expand=False) col.prop(self, "snub", expand=False) row = layout.row(align=True) row.prop(self, "dual", toggle=True) row.prop(self, "keepSize", toggle=True) def get_data(self): size = self.inputs["size"].sv_get() vTrunc = self.inputs["vTrunc"].sv_get() eTrunc = self.inputs["eTrunc"].sv_get() params = [size, vTrunc, eTrunc] return match_long_repeat(params) def process(self): if not any(s.is_linked for s in self.outputs): return verts_out, edges_out, polys_out = [], [], [] params = self.get_data() get_edges = self.outputs['Edges'].is_linked for p in zip(*params): p = match_long_repeat(p) for p2 in zip(*p): size, vTrunc, eTrunc = p2 verts, faces = createSolid(self.source, vTrunc, eTrunc, self.dual, self.snub) # resize to normal size, or if keepSize, make sure all verts are of length 'size' if self.keepSize: rad = size / verts[-1 if self.dual else 0].length else: rad = size verts = [list(i * rad) for i in verts] verts_out.append(verts) polys_out.append(faces) if get_edges: edges_out.append(pols_edges([faces], unique_edges=True)[0]) if self.outputs['Vertices'].is_linked: self.outputs['Vertices'].sv_set(verts_out) if get_edges: self.outputs['Edges'].sv_set(edges_out) if self.outputs['Polygons'].is_linked: self.outputs['Polygons'].sv_set(polys_out)
class MUV_OT_MirrorUV(bpy.types.Operator): """ Operation class: Mirror UV """ bl_idname = "uv.muv_mirror_uv" bl_label = "Mirror UV" bl_options = {'REGISTER', 'UNDO'} axis = EnumProperty(items=(('X', "X", "Mirror Along X axis"), ('Y', "Y", "Mirror Along Y axis"), ('Z', "Z", "Mirror Along Z axis")), name="Axis", description="Mirror Axis", default='X') error = FloatProperty(name="Error", description="Error threshold", default=0.001, min=0.0, max=100.0, soft_min=0.0, soft_max=1.0) @classmethod def poll(cls, context): # we can not get area/space/region from console if common.is_console_mode(): return True return _is_valid_context(context) def execute(self, context): obj = context.active_object bm = bmesh.from_edit_mesh(obj.data) error = self.error axis = self.axis if 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() faces = [f for f in bm.faces if f.select] for f_dst in faces: count = len(f_dst.verts) for f_src in bm.faces: # check if this is a candidate to do mirror UV if f_src.index == f_dst.index: continue if count != len(f_src.verts): continue # test if the vertices x values are the same sign dst = _get_face_center(f_dst) src = _get_face_center(f_src) if (dst.x > 0 and src.x > 0) or (dst.x < 0 and src.x < 0): continue # invert source axis if axis == 'X': src.x = -src.x elif axis == 'Y': src.y = -src.z elif axis == 'Z': src.z = -src.z # do mirror UV if _is_vector_similar(dst, src, error): _mirror_uvs(uv_layer, f_src, f_dst, self.axis, self.error) bmesh.update_edit_mesh(obj.data) return {'FINISHED'}
class SvDistancetLineLineNode(bpy.types.Node, SverchCustomTreeNode): ''' Triggers: Intersect, Trim Tooltip: Distance Line to line and closest points in the lines ''' bl_idname = 'SvDistancetLineLineNode' bl_label = 'Distance Line Line' bl_icon = 'OUTLINER_OB_EMPTY' sv_icon = 'SV_DISTANCE' tolerance = FloatProperty( name="tolerance", description='intersection tolerance', default=1.0e-6, min=0.0, precision=6, update=updateNode) list_match_global = EnumProperty( name="Match Global", description="Behavior on different list lengths, multiple objects level", items=list_match_modes, default="REPEAT", update=updateNode) def sv_init(self, context): '''create sockets''' sinw = self.inputs.new sonw = self.outputs.new sinw('VerticesSocket', "Verts Line A") sinw('VerticesSocket', "Verts Line B") sonw('StringsSocket', "Distance") sonw('StringsSocket', "Intersect") sonw('VerticesSocket', "Closest Point A") sonw('VerticesSocket', "Closest Point B") sonw('StringsSocket', "A in segment") sonw('StringsSocket', "B in segment") def draw_buttons_ext(self, context, layout): '''draw buttons on the N-panel''' layout.prop(self, "tolerance") layout.separator() layout.label(text="List Match:") layout.prop(self, "list_match_global", text="Global Match", expand=False) def rclick_menu(self, context, layout): '''right click sv_menu items''' layout.prop(self, "tolerance") layout.prop_menu_enum(self, "list_match_global", text="List Match Global") def get_data(self): '''get all data from sockets and match lengths''' si = self.inputs return list_match_func[self.list_match_global]([s.sv_get(default=[[]]) for s in si]) def process(self): '''main node function called every update''' so = self.outputs si = self.inputs if not (any(s.is_linked for s in so) and all(s.is_linked for s in si)): return result = [[] for socket in so] gates = [socket.is_linked for socket in so] group = self.get_data() for line_a, line_b in zip(*group): distance_line_line(line_a, line_b, result, gates, self.tolerance) for i, res in enumerate(result): if gates[i]: so[i].sv_set(res)
def register(): IDStore = bpy.types.Scene IDStore.renaming_sufpre_type = EnumProperty( name="Suffix or Prefix by Type", items=prefixSuffixItems, description="Add Prefix or Suffix to type", default='SUF') IDStore.renaming_object_types = EnumProperty( name="Renaming Objects", items=renamingEntitiesItems, description="Which kind of object to rename", ) IDStore.renaming_object_types_specified = EnumProperty( name="Object Types", items=enumObjectTypes, description="Which kind of object to rename", options={'ENUM_FLAG'}, default={ 'CURVE', 'LATTICE', 'SURFACE', 'MESH', 'ARMATURE', 'LIGHT', 'CAMERA', 'EMPTY', 'GPENCIL', 'FONT', 'SPEAKER', 'LIGHT_PROBE', 'VOLUME' }) IDStore.renaming_newName = StringProperty(name="New Name", default='') IDStore.renaming_search = StringProperty(name='Search', default='') IDStore.renaming_replace = StringProperty(name='Replace', default='') IDStore.renaming_suffix = StringProperty(name="Suffix", default='') IDStore.renaming_prefix = StringProperty(name="Prefix", default='') IDStore.renaming_numerate = StringProperty(name="Numerate", default='###') IDStore.renaming_only_selection = BoolProperty( name="Selected Objects", description="Rename Selected Objects", default=True) IDStore.renamingPanel_advancedMode = BoolProperty( name="Advanced Renaming", description="Enable additional feautres for renaming", default=False) IDStore.renaming_matchcase = BoolProperty(name="Match Case", description="", default=True) IDStore.renaming_useRegex = BoolProperty(name="Use Regex", description="", default=False) IDStore.renaming_usenumerate = BoolProperty( name="Numerate", description= "Enable and Disable the numeration of objects. This can be especially useful in combination with the custom numberation variable @n", default=True, ) IDStore.renaming_base_numerate = IntProperty(name="Step Size", default=1) IDStore.renaming_start_number = IntProperty(name="Step Size", default=1) IDStore.renaming_digits_numerate = IntProperty(name="Number Length", default=3) IDStore.renaming_cut_size = IntProperty(name="Trim Size", default=3) from bpy.utils import register_class for cls in classes: register_class(cls)
class LUXCORE_OT_render_settings_helper(bpy.types.Operator): bl_idname = "luxcore.render_settings_helper" bl_label = "Render Settings Helper" bl_description = "Interactive render settings guide" bl_options = {"UNDO"} yes_no_items = [ ("NOT_SET", "Please Choose", "", 0), ("YES", "Yes", "", 1), ("NO", "No", "", 2), ] use_cycles_settings: EnumProperty(items=yes_no_items) env_visibility_items = [ ("NOT_SET", "Please Choose", "", 0), ("INDOORS", "Indoors", "Choose this if the world background is only visible through small openings like windows", 1), ("OUTDOORS", "Outdoors or Studio", "Choose this if the world background is unobstructed", 2), ] env_visibility: EnumProperty(items=env_visibility_items) has_caustics: EnumProperty(items=yes_no_items) has_SDS_caustics: EnumProperty(items=yes_no_items) def _use_GPU(self): return utils.is_opencl_build() or utils.is_cuda_build() def invoke(self, context, event): return context.window_manager.invoke_props_dialog(self, width=450) def execute(self, context): settings = context.scene.luxcore config = settings.config # Stuff that's independent from user choices config.engine = "PATH" config.sampler = "SOBOL" config.sampler_gpu = "SOBOL" config.sobol_adaptive_strength = 0.9 if self._use_GPU(): config.device = "OCL" else: config.device = "CPU" settings.denoiser.enabled = True settings.denoiser.type = "OIDN" # Evaluate user choices if self.use_cycles_settings == "YES": use_cycles_settings() # Env. light visibility and indirect light speedup config.envlight_cache.enabled = self.env_visibility == "INDOORS" config.photongi.enabled = self.env_visibility == "INDOORS" config.photongi.indirect_enabled = self.env_visibility == "INDOORS" # Caustics config.path.hybridbackforward_enable = self.has_caustics == "YES" # Caustic cache if self.has_SDS_caustics == "YES": config.photongi.caustic_enabled = True # Disable radius shrinking config.photongi.caustic_updatespp_minradius = config.photongi.caustic_lookup_radius utils_ui.tag_region_for_redraw(context, "PROPERTIES", "WINDOW") return {"FINISHED"} def _show_result(self, text): layout = self.layout row = layout.row(align=True) row.label(text="", icon=icons.GREEN_RHOMBUS) row.label(text=text) def draw(self, context): layout = self.layout config = context.scene.luxcore.config question.index = 1 # Should Cycles settings be ported? question(layout, "Should Cycles settings and shaders be used?") layout.prop(self, "use_cycles_settings", expand=True) if self.use_cycles_settings == "NOT_SET": layout.separator() return if self.use_cycles_settings == "YES": self._show_result( "Will use Cycles settings for materials, lights and world") # Is the environment light obscured or not, is indirect light likely noisy or not? question(layout, "Is your scene indoors or outdoors?") layout.prop(self, "env_visibility", expand=True) if self.env_visibility == "NOT_SET": layout.separator() return if self.env_visibility == "INDOORS": self._show_result("Will enable PhotonGI Indirect Cache") self._show_result("Will enable Environment Light Cache") else: self._show_result( "Indirect and environment light caches not needed") # Caustics question(layout, "Are there caustics in your scene?") layout.prop(self, "has_caustics", expand=True) if self.has_caustics == "NOT_SET": layout.separator() return if self.has_caustics == "YES": self._show_result('Will enable "Add Light Tracing" option') else: self._show_result('"Add Light Tracing" not needed') if self.has_caustics == "YES": # SDS caustics layout.label( text= "Are the caustics visible in a mirror, or are the viewed through glass (e.g. in a pool)?" ) layout.prop(self, "has_SDS_caustics", expand=True) if self.has_SDS_caustics == "NOT_SET": layout.separator() return if self.has_SDS_caustics == "YES": self._show_result('Will enable PhotonGI Caustic Cache') col = layout.column(align=True) col.label( text= "What would be a good photon radius for your scene size? (in meters)" ) col.label( text= "(Too large values will look blurred, too small values will create noise)" ) col.prop(config.photongi, "caustic_lookup_radius") else: self._show_result('Caustic cache not needed') # Show general settings that will be used layout.separator() layout.label(text="Additionally, these general settings will be set:") self._show_result("Engine: Path") self._show_result(f'Device: {"GPU" if self._use_GPU() else "CPU"}') self._show_result("Sampler: Sobol (adaptive)") self._show_result("Denoiser: enabled")
class NODE_OT_add_search(NodeAddOperator, Operator): '''Add a node to the active tree''' bl_idname = "node.add_search" bl_label = "Search and Add Node" bl_options = {'REGISTER', 'UNDO'} bl_property = "node_item" _enum_item_hack = [] # Create an enum list from node items def node_enum_items(self, context): enum_items = NODE_OT_add_search._enum_item_hack enum_items.clear() for index, item in enumerate(nodeitems_utils.node_items_iter(context)): if isinstance(item, nodeitems_utils.NodeItem): nodetype = getattr(bpy.types, item.nodetype, None) if nodetype: enum_items.append((str(index), item.label, nodetype.bl_rna.description, index)) return enum_items # Look up the item based on index def find_node_item(self, context): node_item = int(self.node_item) for index, item in enumerate(nodeitems_utils.node_items_iter(context)): if index == node_item: return item return None node_item = EnumProperty( name="Node Type", description="Node type", items=node_enum_items, ) def execute(self, context): item = self.find_node_item(context) # no need to keep self._enum_item_hack.clear() if item: # apply settings from the node item for setting in item.settings.items(): ops = self.settings.add() ops.name = setting[0] ops.value = setting[1] self.create_node(context, item.nodetype) if self.use_transform: bpy.ops.transform.translate('INVOKE_DEFAULT', remove_on_cancel=True) return {'FINISHED'} else: return {'CANCELLED'} def invoke(self, context, event): self.store_mouse_cursor(context, event) # Delayed execution in the search popup context.window_manager.invoke_search_popup(self) return {'CANCELLED'}
class SvEasingNode(bpy.types.Node, SverchCustomTreeNode): '''Curved interpolation''' bl_idname = 'SvEasingNode' bl_label = 'Easing 0..1' sv_icon = 'SV_EASING' n_id: StringProperty(default='') activate: BoolProperty(name='Show', description='Activate drawing', default=True, update=updateNode) selected_mode: EnumProperty(items=easing_list, description="Set easing Function to:", default="0", update=updateNode) in_float: FloatProperty(min=0.0, max=1.0, default=0.0, name='Float Input', description='input to the easy function', update=updateNode) selected_theme_mode: EnumProperty(items=enum_item_4( ["default", "scope", "sniper"]), default="sniper", update=updateNode) location_theta: FloatProperty(name="location theta") def custom_draw_socket(self, socket, context, l): r = l.row(align=True) split = r.split(factor=0.85) r1 = split.row(align=True) r1.prop(self, "selected_mode", text="") r1.prop(self, 'activate', icon='NORMALIZE_FCURVES', text="") r2 = split.row() r2.label(text=f"{socket.objects_number or ''}") def draw_buttons_ext(self, context, l): l.prop(self, "selected_theme_mode") def sv_init(self, context): self.inputs.new('SvStringsSocket', "Float").prop_name = 'in_float' self.outputs.new('SvStringsSocket', "Float").custom_draw = 'custom_draw_socket' self.get_and_set_gl_scale_info() def get_offset(self): return [ int(j) for j in (Vector(self.absolute_location) + Vector((self.width + 20, 0)))[:] ] def get_drawing_attributes(self): """ adjust render location based on preference multiplier setting """ try: with sv_preferences() as prefs: multiplier = prefs.render_location_xy_multiplier scale = prefs.render_scale except: # print('did not find preferences - you need to save user preferences') multiplier = 1.0 scale = 1.0 # cache this. self.location_theta = multiplier return scale def generate_graph_geom(self, config): geom = lambda: None x, y = config.loc size = 140 * config.scale back_color, grid_color, line_color = config.palette easing_func = config.easing_func # background geom w = size h = size geom.background_coords = [(x, y), (x + w, y), (w + x, y - h), (x, y - h)] geom.background_indices = [(0, 1, 2), (0, 2, 3)] # grid geom and associated vertex colors num_divs = 8 offset = size / num_divs vertices = [] vertex_colors = [] indices = [] for i in range(num_divs + 1): xpos1 = x + (i * offset) ypos1 = y ypos2 = y - size vertices.extend([[xpos1, ypos1], [xpos1, ypos2]]) ypos = y - (i * offset) vertices.extend([[x, ypos], [x + size, ypos]]) vertex_colors.extend([ grid_color, ] * 4) for i in range(0, (num_divs + 1) * 4, 2): indices.append([i, i + 1]) # graph-line geom and associated vertex colors idx_offset = len(vertices) graphline = [] num_points = 100 seg_diff = 1 / num_points for i in range(num_points + 1): _px = x + ((i * seg_diff) * size) _py = y - (1 - easing_func(i * seg_diff) * size) - size graphline.append([_px, _py]) vertex_colors.append(line_color) vertices.extend(graphline) for i in range(num_points): indices.append([idx_offset + i, idx_offset + i + 1]) geom.vertices = vertices geom.vertex_colors = vertex_colors geom.indices = indices return geom def process(self): p = self.inputs['Float'].sv_get() n_id = node_id(self) # end early nvBGL.callback_disable(n_id) float_out = self.outputs['Float'] easing_func = easing_dict.get(int(self.selected_mode)) if float_out.is_linked: out = [] for obj in p: r = [] for i in obj: r.append(easing_func(i)) out.append(r) float_out.sv_set(out) else: float_out.sv_set([[None]]) if self.activate and self.inputs[0].is_linked: config = lambda: None scale = self.get_drawing_attributes() config.loc = (0, 0) config.palette = palette_dict.get(self.selected_theme_mode)[:] config.scale = scale config.easing_func = easing_func geom = self.generate_graph_geom(config) # config.batch, config.shader = self.generate_shader(geom) draw_data = { 'mode': 'custom_function', 'tree_name': self.id_data.name[:], 'node_name': self.name[:], 'loc': get_drawing_location, 'custom_function': simple28_grid_xy, 'args': (geom, config) } nvBGL.callback_enable(n_id, draw_data) def sv_free(self): nvBGL.callback_disable(node_id(self)) def sv_copy(self, node): self.n_id = ''
class SvInterpolationStripesNode(bpy.types.Node, SverchCustomTreeNode): '''Vector Interpolate Stripes''' bl_idname = 'SvInterpolationStripesNode' bl_label = 'Stripes Mult' bl_icon = 'OUTLINER_OB_EMPTY' # vector math functions mode_items = [ ("SIMPLE", "Simple", "", 0), ("MULT", "Mult", "", 1), ("SIN", "Sin", "", 2), ("COS", "Cos", "", 3), ("POW", "POW", "", 4), ("SQRT", "Sqrt", "", 5), ] current_op = StringProperty(default="SIMPLE") def mode_change(self, context): if not (self.operations == self.current_op): self.label = 'Stripes ' + self.operations self.current_op = self.operations updateNode(self, context) operations = EnumProperty(items=mode_items, name="Function", description="Function choice", default="SIMPLE", update=mode_change) factor = FloatProperty(name="factor", default=1.0, precision=5, update=updateNode) minimum = FloatProperty(name="minimum", default=0.0, min=0.0, max=0.5, precision=5, update=updateNode) maximum = FloatProperty(name="maximum", default=1.0, min=0.5, max=1.0, precision=5, update=updateNode) scale = FloatProperty(name="scale", default=1.0, precision=5, update=updateNode) t_in_x = FloatProperty(name="tU", default=.5, min=0, max=1, precision=5, update=updateNode) t_in_y = FloatProperty(name="tV", default=.5, min=0, max=1, precision=5, update=updateNode) def sv_init(self, context): s = self.inputs.new('VerticesSocket', 'Vertices') s.use_prop = True self.inputs.new('StringsSocket', 'IntervalX') self.inputs.new('StringsSocket', 'IntervalY') a = self.inputs.new('VerticesSocket', 'Attractor') a.use_prop = True s.prop = (0, 0, 1) self.outputs.new('VerticesSocket', 'vStripesOut') self.outputs.new('VerticesSocket', 'vStripesIn') self.outputs.new('VerticesSocket', 'vShape') self.outputs.new('StringsSocket', 'sCoefs') def draw_buttons(self, context, layout): col = layout.column(align=True) row = col.row(align=True) row.prop(self, 'factor') row = col.row(align=True) row.prop(self, 'scale') row = col.row(align=True) row.prop(self, 'operations') def draw_buttons_ext(self, context, layout): col = layout.column(align=True) row = col.row(align=True) row.prop(self, 'minimum') row = col.row(align=True) row.prop(self, 'maximum') def interpol(self, verts, t_ins): verts_out = [] for v, t_in in zip(verts, repeat_last(t_ins)): pts = np.array(v).T tmp = np.apply_along_axis(np.linalg.norm, 0, pts[:, :-1] - pts[:, 1:]) t = np.insert(tmp, 0, 0).cumsum() t = t / t[-1] t_corr = [min(1, max(t_c, 0)) for t_c in t_in] spl = cubic_spline(v, t) out = eval_spline(spl, t, t_corr) verts_out.append(out) return verts_out def distance(self, x, y): vec = Vector((x[0] - y[0], x[1] - y[1], x[2] - y[2])) return vec.length def process(self): if 'vStripesOut' not in self.outputs: return if not any((s.is_linked for s in self.outputs)): return if self.inputs['Vertices'].is_linked: verts = self.inputs['Vertices'].sv_get() verts = dataCorrect(verts) attrs = self.inputs['Attractor'].sv_get() attrs = dataCorrect(attrs) if not self.inputs['IntervalX'].is_linked: t_ins_x = [[i / 10 for i in range(0, 11)]] else: t_ins_x = self.inputs['IntervalX'].sv_get() if not self.inputs['IntervalY'].is_linked: t_ins_y = [[i / 10 for i in range(0, 11)]] else: t_ins_y = self.inputs['IntervalY'].sv_get() factor = self.factor scale = self.scale minimum = self.minimum maximum = self.maximum operations = self.operations func = vector_out[operations] # initial interpolation vertsX = self.interpol(verts, t_ins_x) verts_T = np.swapaxes(np.array(vertsX), 0, 1).tolist() verts_int = self.interpol(verts_T, t_ins_y) # calculating distances with maximum one dists = [] verts_int, attrs = match_long_repeat([verts_int, attrs]) for overts, oattrs in zip(verts_int, attrs): overts, oattrs = match_long_repeat([overts, oattrs]) dists_ = [] for v, a in zip(overts, oattrs): dists_.append(self.distance(v, a)) dists.append(dists_) dists_np = np.array(dists) maxidist = dists_np.max() # normalize distances to coefficients for every vertex # can be extended with formula evaluation... next step #factor = eval(self.factor) # vector-output try: #dists_normalized = dists_np/(maxidist*len(t_ins_y)) dists_normalized = func(dists_np, maxidist, t_ins_y, factor, scale, minimum, maximum) #print(dists_normalized) except ZeroDivisionError: print("division by zero!") return #except: # print('stripes cannot calc function') # return # calculate vertex moving coefficient # simmetrically mirrored t_ins_y_np = np.array(t_ins_y).repeat(len(dists_normalized), 0) a = np.roll(t_ins_y_np, 1, 1) b = np.roll(t_ins_y_np, -1, 1) c = t_ins_y_np - (t_ins_y_np - a) * dists_normalized / 2 d = t_ins_y_np + (b - t_ins_y_np) * dists_normalized / 2 # replacing first-last for both mirrors c[:, 0] = t_ins_y_np[:, 0] d[:, -1] = t_ins_y_np[:, -1] t_ins_y_mins = c.tolist() t_ins_y_plus = d.tolist() # secondary interpolation # processing sliced stripes vertsY_mins = self.interpol(verts_int, t_ins_y_mins) vertsY_plus = self.interpol(verts_int, t_ins_y_plus) verts_T_mins = np.swapaxes(np.array(vertsY_mins), 0, 1).tolist() verts_T_plus = np.swapaxes(np.array(vertsY_plus), 0, 1).tolist() verts_X_mins = self.interpol(verts_T_mins, t_ins_x) verts_X_plus = self.interpol(verts_T_plus, t_ins_x) # zipping for UVconnect node to "eat" this # mirrors on left and right side from initial interpolation verts_out = [[M, P] for M, P in zip(verts_X_mins, verts_X_plus)] vm, vp = verts_X_mins[1:], verts_X_plus[:-1] #print('mnis----------',verts_X_mins[0]) verts_inner_out = [[M, P] for M, P in zip(vm, vp)] if self.outputs['vStripesOut'].is_linked: SvSetSocketAnyType(self, 'vStripesOut', verts_out) if self.outputs['vStripesIn'].is_linked: SvSetSocketAnyType(self, 'vStripesIn', verts_inner_out) if self.outputs['vShape'].is_linked: SvSetSocketAnyType(self, 'vShape', verts_int) if self.outputs['sCoefs'].is_linked: SvSetSocketAnyType(self, 'sCoefs', dists_normalized.tolist())
class EXPORTGIS_OT_shapefile(Operator, ExportHelper): """Export from ESRI shapefile file format (.shp)""" bl_idname = "exportgis.shapefile" # important since its how bpy.ops.import.shapefile is constructed (allows calling operator from python console or another script) #bl_idname rules: must contain one '.' (dot) charactere, no capital letters, no reserved words (like 'import') bl_description = 'export to ESRI shapefile file format (.shp)' bl_label = "Export SHP" bl_options = {"UNDO"} # ExportHelper class properties filename_ext = ".shp" filter_glob: StringProperty( default="*.shp", options={'HIDDEN'}, ) exportType: EnumProperty(name="Feature type", description="Select feature type", items=[('POINTZ', 'Point', ""), ('POLYLINEZ', 'Line', ""), ('POLYGONZ', 'Polygon', "")]) objectsSource: EnumProperty(name="Objects", description="Objects to export", items=[('COLLEC', 'Collection', "Export a collection of objects"), ('SELECTED', 'Selected objects', "Export the current selection")], default='SELECTED') def listCollections(self, context): return [(c.name, c.name, "Collection") for c in bpy.data.collections] selectedColl: EnumProperty(name="Collection", description="Select the collection to export", items=listCollections) mode: EnumProperty(name="Mode", description="Select the export strategy", items=[ ('OBJ2FEAT', 'Objects to features', "Create one multipart feature per object"), ('MESH2FEAT', 'Mesh to features', "Decompose mesh primitives to separate features") ], default='OBJ2FEAT') @classmethod def poll(cls, context): return context.mode == 'OBJECT' def draw(self, context): #Function used by blender to draw the panel. layout = self.layout layout.prop(self, 'objectsSource') if self.objectsSource == 'COLLEC': layout.prop(self, 'selectedColl') layout.prop(self, 'mode') layout.prop(self, 'exportType') def execute(self, context): filePath = self.filepath folder = os.path.dirname(filePath) scn = context.scene geoscn = GeoScene(scn) if geoscn.isGeoref: dx, dy = geoscn.getOriginPrj() crs = SRS(geoscn.crs) try: wkt = crs.getWKT() except Exception as e: log.warning('Cannot convert crs to wkt', exc_info=True) wkt = None elif geoscn.isBroken: self.report({'ERROR'}, "Scene georef is broken, please fix it beforehand") return {'CANCELLED'} else: dx, dy = (0, 0) wkt = None if self.objectsSource == 'SELECTED': objects = [ obj for obj in bpy.context.selected_objects if obj.type == 'MESH' ] elif self.objectsSource == 'COLLEC': objects = bpy.data.collections[self.selectedColl].all_objects objects = [obj for obj in objects if obj.type == 'MESH'] if not objects: self.report({'ERROR'}, "Selection is empty or does not contain any mesh") return {'CANCELLED'} outShp = shpWriter(filePath) if self.exportType == 'POLYGONZ': outShp.shapeType = POLYGONZ #15 if self.exportType == 'POLYLINEZ': outShp.shapeType = POLYLINEZ #13 if self.exportType == 'POINTZ' and self.mode == 'MESH2FEAT': outShp.shapeType = POINTZ if self.exportType == 'POINTZ' and self.mode == 'OBJ2FEAT': outShp.shapeType = MULTIPOINTZ #create fields (all needed fields sould be created before adding any new record) #TODO more robust evaluation, and check for boolean and date types cLen = 255 #string fields default length nLen = 20 #numeric fields default length dLen = 5 #numeric fields default decimal precision maxFieldNameLen = 8 #shp capabilities limit field name length to 8 characters outShp.field('objId', 'N', nLen) #export id for obj in objects: for k, v in obj.items(): k = k[0:maxFieldNameLen] #evaluate the field type with the first value if k not in [f[0] for f in outShp.fields]: if isinstance(v, float) or isinstance(v, int): fieldType = 'N' elif isinstance(v, str): if v.lstrip("-+").isdigit(): v = int(v) fieldType = 'N' else: try: v = float(v) except ValueError: fieldType = 'C' else: fieldType = 'N' else: continue if fieldType == 'C': outShp.field(k, fieldType, cLen) elif fieldType == 'N': if isinstance(v, int): outShp.field(k, fieldType, nLen, 0) else: outShp.field(k, fieldType, nLen, dLen) for i, obj in enumerate(objects): loc = obj.location bm = bmesh.new() bm.from_object( obj, context.evaluated_depsgraph_get(), deform=True) #'deform' allows to consider modifier deformation bm.transform(obj.matrix_world) nFeat = 1 if self.exportType == 'POINTZ': if len(bm.verts) == 0: continue #Extract coords & adjust values against georef deltas pts = [[v.co.x + dx, v.co.y + dy, v.co.z] for v in bm.verts] if self.mode == 'MESH2FEAT': for j, pt in enumerate(pts): outShp.pointz(*pt) nFeat = len(pts) elif self.mode == 'OBJ2FEAT': outShp.multipointz(pts) if self.exportType == 'POLYLINEZ': if len(bm.edges) == 0: continue lines = [] for edge in bm.edges: #Extract coords & adjust values against georef deltas line = [(vert.co.x + dx, vert.co.y + dy, vert.co.z) for vert in edge.verts] lines.append(line) if self.mode == 'MESH2FEAT': for j, line in enumerate(lines): outShp.linez([line]) nFeat = len(lines) elif self.mode == 'OBJ2FEAT': outShp.linez(lines) if self.exportType == 'POLYGONZ': if len(bm.faces) == 0: continue #build geom polygons = [] for face in bm.faces: #Extract coords & adjust values against georef deltas poly = [(vert.co.x + dx, vert.co.y + dy, vert.co.z) for vert in face.verts] poly.append(poly[0]) #close poly #In Blender face is up if points are in anticlockwise order #for shapefiles, face's up with clockwise order poly.reverse() polygons.append(poly) if self.mode == 'MESH2FEAT': for j, polygon in enumerate(polygons): outShp.polyz([polygon]) nFeat = len(polygons) elif self.mode == 'OBJ2FEAT': outShp.polyz(polygons) #Writing attributes Data attributes = {'objId': i} for k, v in obj.items(): k = k[0:maxFieldNameLen] if not any([f[0] == k for f in outShp.fields]): continue fType = next((f[1] for f in outShp.fields if f[0] == k)) if fType in ('N', 'F'): try: v = float(v) except ValueError: log.info( 'Cannot cast value {} to float for appending field {}, NULL value will be inserted instead' .format(v, k)) v = None attributes[k] = v #assign None to orphans shp fields (if the key does not exists in the custom props of this object) attributes.update({ f[0]: None for f in outShp.fields if f[0] not in attributes.keys() }) #Write for n in range(nFeat): outShp.record(**attributes) outShp.close() if wkt is not None: prjPath = os.path.splitext(filePath)[0] + '.prj' prj = open(prjPath, "w") prj.write(wkt) prj.close() self.report({'INFO'}, "Export complete") return {'FINISHED'}
def register(): bpy.utils.register_class(measureit_main.RunHintDisplayButton) bpy.utils.register_class(measureit_main.AddSegmentButton) bpy.utils.register_class(measureit_main.AddAreaButton) bpy.utils.register_class(measureit_main.AddSegmentOrtoButton) bpy.utils.register_class(measureit_main.AddAngleButton) bpy.utils.register_class(measureit_main.AddArcButton) bpy.utils.register_class(measureit_main.AddLabelButton) bpy.utils.register_class(measureit_main.AddNoteButton) bpy.utils.register_class(measureit_main.AddLinkButton) bpy.utils.register_class(measureit_main.AddOriginButton) bpy.utils.register_class(measureit_main.DeleteSegmentButton) bpy.utils.register_class(measureit_main.DeleteAllSegmentButton) bpy.utils.register_class(measureit_main.DeleteAllSumButton) bpy.utils.register_class(measureit_main.MeasureitEditPanel) bpy.utils.register_class(measureit_main.MeasureitMainPanel) bpy.utils.register_class(measureit_main.MeasureitConfPanel) bpy.utils.register_class(measureit_main.MeasureitRenderPanel) bpy.utils.register_class(measureit_main.RenderSegmentButton) bpy.utils.register_class(Measure_Pref) update_panel(None, bpy.context) # Define properties Scene.measureit_default_color = FloatVectorProperty( name="Default color", description="Default Color", default=(0.173, 0.545, 1.0, 1.0), min=0.1, max=1, subtype='COLOR', size=4) Scene.measureit_font_size = IntProperty(name="Text Size", description="Default text size", default=14, min=10, max=150) Scene.measureit_hint_space = FloatProperty(name='Separation', min=0, max=100, default=0.1, precision=3, description="Default distance to display measure") Scene.measureit_gl_ghost = BoolProperty(name="All", description="Display measures for all objects," " not only selected", default=True) Scene.measureit_gl_txt = StringProperty(name="Text", maxlen=256, description="Short description (use | for line break)") Scene.measureit_gl_precision = IntProperty(name='Precision', min=0, max=5, default=2, description="Number of decimal precision") Scene.measureit_gl_show_d = BoolProperty(name="ShowDist", description="Display distances", default=True) Scene.measureit_gl_show_n = BoolProperty(name="ShowName", description="Display texts", default=False) Scene.measureit_scale = BoolProperty(name="Scale", description="Use scale factor", default=False) Scene.measureit_scale_factor = FloatProperty(name='Factor', min=0.001, max=9999999, default=1.0, precision=3, description="Scale factor 1:x") Scene.measureit_scale_color = FloatVectorProperty(name="Scale color", description="Scale Color", default=(1, 1, 0, 1.0), min=0.1, max=1, subtype='COLOR', size=4) Scene.measureit_scale_font = IntProperty(name="Font", description="Text size", default=14, min=10, max=150) Scene.measureit_scale_pos_x = IntProperty(name="Position X", description="Margin on the X axis", default=5, min=0, max=100) Scene.measureit_scale_pos_y = IntProperty(name="Position Y", description="Margin on the Y axis", default=5, min=0, max=100) Scene.measureit_gl_scaletxt = StringProperty(name="ScaleText", maxlen=48, description="Scale title", default="Scale:") Scene.measureit_scale_precision = IntProperty(name='Precision', min=0, max=5, default=0, description="Number of decimal precision") Scene.measureit_ovr = BoolProperty(name="Override", description="Override colors and fonts", default=False) Scene.measureit_ovr_font = IntProperty(name="Font", description="Override text size", default=14, min=10, max=150) Scene.measureit_ovr_color = FloatVectorProperty(name="Override color", description="Override Color", default=(1, 0, 0, 1.0), min=0.1, max=1, subtype='COLOR', size=4) Scene.measureit_ovr_width = IntProperty(name='Override width', min=1, max=10, default=1, description='override line width') Scene.measureit_units = EnumProperty(items=(('1', "Automatic", "Use scene units"), ('2', "Meters", ""), ('3', "Centimeters", ""), ('4', "Milimiters", ""), ('5', "Feet", ""), ('6', "Inches", "")), name="Units", default="2", description="Units") Scene.measureit_hide_units = BoolProperty(name="hide_units", description="Do not display unit of measurement on viewport", default=False) Scene.measureit_render = BoolProperty(name="Render", description="Save an image with measures over" " render image", default=False) Scene.measureit_render_type = EnumProperty(items=(('1', "*Current", "Use current render"), ('2', "OpenGL", ""), ('3', "Animation OpenGL", ""), ('4', "Image", ""), ('5', "Animation", "")), name="Render type", description="Type of render image") Scene.measureit_sum = EnumProperty(items=(('99', "-", "Select a group for sum"), ('0', "A", ""), ('1', "B", ""), ('2', "C", ""), ('3', "D", ""), ('4', "E", ""), ('5', "F", ""), ('6', "G", ""), ('7', "H", ""), ('8', "I", ""), ('9', "J", ""), ('10', "K", ""), ('11', "L", ""), ('12', "M", ""), ('13', "N", ""), ('14', "O", ""), ('15', "P", ""), ('16', "Q", ""), ('17', "R", ""), ('18', "S", ""), ('19', "T", ""), ('20', "U", ""), ('21', "V", ""), ('22', "W", ""), ('23', "X", ""), ('24', "Y", ""), ('25', "Z", "")), name="Sum in Group", description="Add segment length in selected group") Scene.measureit_rf = BoolProperty(name="render_frame", description="Add a frame in render output", default=False) Scene.measureit_rf_color = FloatVectorProperty(name="Fcolor", description="Frame Color", default=(0.9, 0.9, 0.9, 1.0), min=0.1, max=1, subtype='COLOR', size=4) Scene.measureit_rf_border = IntProperty(name='fborder ', min=1, max=1000, default=10, description='Frame space from border') Scene.measureit_rf_line = IntProperty(name='fline', min=1, max=10, default=1, description='Line width for border') Scene.measureit_glarrow_a = EnumProperty(items=(('99', "--", "No arrow"), ('1', "Line", "The point of the arrow are lines"), ('2', "Triangle", "The point of the arrow is triangle"), ('3', "TShape", "The point of the arrow is a T")), name="A end", description="Add arrows to point A") Scene.measureit_glarrow_b = EnumProperty(items=(('99', "--", "No arrow"), ('1', "Line", "The point of the arrow are lines"), ('2', "Triangle", "The point of the arrow is triangle"), ('3', "TShape", "The point of the arrow is a T")), name="B end", description="Add arrows to point B") Scene.measureit_glarrow_s = IntProperty(name="Size", description="Arrow size", default=15, min=6, max=500) Scene.measureit_debug = BoolProperty(name="Debug", description="Display information for debuging" " (expand/collapse for enabling or disabling)" " this information is only renderered for " "selected objects", default=False) Scene.measureit_debug_select = BoolProperty(name="Selected", description="Display information " "for selected vertices/faces", default=False) Scene.measureit_debug_vertices = BoolProperty(name="Vertices", description="Display vertex number", default=True) Scene.measureit_debug_location = BoolProperty(name="Location", description="Display vertex location", default=False) Scene.measureit_debug_faces = BoolProperty(name="Faces", description="Display face number", default=False) Scene.measureit_debug_normals = BoolProperty(name="Normals", description="Display face normal " "vector and creation order", default=False) Scene.measureit_debug_normal_details = BoolProperty(name="Details", description="Display face normal details", default=True) Scene.measureit_debug_font = IntProperty(name="Font", description="Debug text size", default=14, min=10, max=150) Scene.measureit_debug_color = FloatVectorProperty(name="Debug color", description="Debug Color", default=(1, 0, 0, 1.0), min=0.1, max=1, subtype='COLOR', size=4) Scene.measureit_debug_color2 = FloatVectorProperty(name="Debug face color", description="Debug face Color", default=(0, 1, 0, 1.0), min=0.1, max=1, subtype='COLOR', size=4) Scene.measureit_debug_color3 = FloatVectorProperty(name="Debug vector color", description="Debug vector Color", default=(1.0, 1.0, 0.1, 1.0), min=0.1, max=1, subtype='COLOR', size=4) Scene.measureit_debug_normal_size = FloatProperty(name='Len', min=0.001, max=9, default=0.5, precision=2, description="Normal arrow size") Scene.measureit_debug_width = IntProperty(name='Debug width', min=1, max=10, default=2, description='Vector line thickness') Scene.measureit_debug_precision = IntProperty(name='Precision', min=0, max=5, default=1, description="Number of decimal precision") # OpenGL flag wm = WindowManager # register internal property wm.measureit_run_opengl = BoolProperty(default=False)
class add_mesh_bolt(bpy.types.Operator): bl_idname = "mesh.bolt_add" bl_label = "Add Bolt" bl_options = {'REGISTER', 'UNDO', 'PRESET'} bl_description = "Construct many types of Bolts" align_matrix = Matrix() MAX_INPUT_NUMBER = 50 # edit - Whether to add or update edit = BoolProperty( name="", description="", default=False, options={'HIDDEN'} ) # Model Types Model_Type_List = [('bf_Model_Bolt', 'BOLT', 'Bolt Model'), ('bf_Model_Nut', 'NUT', 'Nut Model')] bf_Model_Type = EnumProperty( attr='bf_Model_Type', name='Model', description='Choose the type off model you would like', items=Model_Type_List, default='bf_Model_Bolt' ) # Head Types Model_Type_List = [('bf_Head_Hex', 'HEX', 'Hex Head'), ('bf_Head_Cap', 'CAP', 'Cap Head'), ('bf_Head_Dome', 'DOME', 'Dome Head'), ('bf_Head_Pan', 'PAN', 'Pan Head'), ('bf_Head_CounterSink', 'COUNTER SINK', 'Counter Sink Head')] bf_Head_Type = EnumProperty( attr='bf_Head_Type', name='Head', description='Choose the type off Head you would like', items=Model_Type_List, default='bf_Head_Hex' ) # Bit Types Bit_Type_List = [('bf_Bit_None', 'NONE', 'No Bit Type'), ('bf_Bit_Allen', 'ALLEN', 'Allen Bit Type'), ('bf_Bit_Philips', 'PHILLIPS', 'Phillips Bit Type')] bf_Bit_Type = EnumProperty( attr='bf_Bit_Type', name='Bit Type', description='Choose the type of bit to you would like', items=Bit_Type_List, default='bf_Bit_None' ) # Nut Types Nut_Type_List = [('bf_Nut_Hex', 'HEX', 'Hex Nut'), ('bf_Nut_Lock', 'LOCK', 'Lock Nut')] bf_Nut_Type = EnumProperty( attr='bf_Nut_Type', name='Nut Type', description='Choose the type of nut you would like', items=Nut_Type_List, default='bf_Nut_Hex' ) # Shank Types bf_Shank_Length = FloatProperty( attr='bf_Shank_Length', name='Shank Length', default=0, min=0, soft_min=0, max=MAX_INPUT_NUMBER, description='Length of the unthreaded shank' ) bf_Shank_Dia = FloatProperty( attr='bf_Shank_Dia', name='Shank Dia', default=3, min=0, soft_min=0, max=MAX_INPUT_NUMBER, description='Diameter of the shank' ) bf_Phillips_Bit_Depth = FloatProperty( attr='bf_Phillips_Bit_Depth', name='Bit Depth', default=1.1431535482406616, min=0, soft_min=0, max=MAX_INPUT_NUMBER, description='Depth of the Phillips Bit' ) bf_Allen_Bit_Depth = FloatProperty( attr='bf_Allen_Bit_Depth', name='Bit Depth', default=1.5, min=0, soft_min=0, max=MAX_INPUT_NUMBER, description='Depth of the Allen Bit' ) bf_Allen_Bit_Flat_Distance = FloatProperty( attr='bf_Allen_Bit_Flat_Distance', name='Flat Dist', default=2.5, min=0, soft_min=0, max=MAX_INPUT_NUMBER, description='Flat Distance of the Allen Bit' ) bf_Hex_Head_Height = FloatProperty( attr='bf_Hex_Head_Height', name='Head Height', default=2, min=0, soft_min=0, max=MAX_INPUT_NUMBER, description='Height of the Hex Head' ) bf_Hex_Head_Flat_Distance = FloatProperty( attr='bf_Hex_Head_Flat_Distance', name='Flat Dist', default=5.5, min=0, soft_min=0, max=MAX_INPUT_NUMBER, description='Flat Distance of the Hex Head' ) bf_CounterSink_Head_Dia = FloatProperty( attr='bf_CounterSink_Head_Dia', name='Head Dia', default=5.5, min=0, soft_min=0, max=MAX_INPUT_NUMBER, description='Diameter of the Counter Sink Head' ) bf_Cap_Head_Height = FloatProperty( attr='bf_Cap_Head_Height', name='Head Height', default=5.5, min=0, soft_min=0, max=MAX_INPUT_NUMBER, description='Height of the Cap Head' ) bf_Cap_Head_Dia = FloatProperty( attr='bf_Cap_Head_Dia', name='Head Dia', default=3, min=0, soft_min=0, max=MAX_INPUT_NUMBER, description='Diameter of the Cap Head' ) bf_Dome_Head_Dia = FloatProperty( attr='bf_Dome_Head_Dia', name='Dome Head Dia', default=5.6, min=0, soft_min=0, max=MAX_INPUT_NUMBER, description='Length of the unthreaded shank' ) bf_Pan_Head_Dia = FloatProperty( attr='bf_Pan_Head_Dia', name='Pan Head Dia', default=5.6, min=0, soft_min=0, max=MAX_INPUT_NUMBER, description='Diameter of the Pan Head') bf_Philips_Bit_Dia = FloatProperty( attr='bf_Philips_Bit_Dia', name='Bit Dia', default=1.8199999332427979, min=0, soft_min=0, max=MAX_INPUT_NUMBER, description='Diameter of the Philips Bit') bf_Thread_Length = FloatProperty( attr='bf_Thread_Length', name='Thread Length', default=6, min=0, soft_min=0, max=MAX_INPUT_NUMBER, description='Length of the Thread') bf_Major_Dia = FloatProperty( attr='bf_Major_Dia', name='Major Dia', default=3, min=0, soft_min=0, max=MAX_INPUT_NUMBER, description='Outside diameter of the Thread') bf_Pitch = FloatProperty( attr='bf_Pitch', name='Pitch', default=0.35, min=0.1, soft_min=0.1, max=7.0, description='Pitch if the thread' ) bf_Minor_Dia = FloatProperty( attr='bf_Minor_Dia', name='Minor Dia', default=2.6211137771606445, min=0, soft_min=0, max=MAX_INPUT_NUMBER, description='Inside diameter of the Thread' ) bf_Crest_Percent = IntProperty( attr='bf_Crest_Percent', name='Crest Percent', default=10, min=1, soft_min=1, max=90, description='Percent of the pitch that makes up the Crest' ) bf_Root_Percent = IntProperty( attr='bf_Root_Percent', name='Root Percent', default=10, min=1, soft_min=1, max=90, description='Percent of the pitch that makes up the Root' ) bf_Div_Count = IntProperty( attr='bf_Div_Count', name='Div count', default=36, min=4, soft_min=4, max=4096, description='Div count determine circle resolution' ) bf_Hex_Nut_Height = FloatProperty( attr='bf_Hex_Nut_Height', name='Hex Nut Height', default=2.4, min=0, soft_min=0, max=MAX_INPUT_NUMBER, description='Height of the Hex Nut' ) bf_Hex_Nut_Flat_Distance = FloatProperty( attr='bf_Hex_Nut_Flat_Distance', name='Hex Nut Flat Dist', default=5.5, min=0, soft_min=0, max=MAX_INPUT_NUMBER, description='Flat distance of the Hex Nut' ) def draw(self, context): layout = self.layout col = layout.column() # ENUMS col.prop(self, 'bf_Model_Type') col.separator() # Bit if self.bf_Model_Type == 'bf_Model_Bolt': col.prop(self, 'bf_Bit_Type') if self.bf_Bit_Type == 'bf_Bit_None': pass elif self.bf_Bit_Type == 'bf_Bit_Allen': col.prop(self, 'bf_Allen_Bit_Depth') col.prop(self, 'bf_Allen_Bit_Flat_Distance') elif self.bf_Bit_Type == 'bf_Bit_Philips': col.prop(self, 'bf_Phillips_Bit_Depth') col.prop(self, 'bf_Philips_Bit_Dia') col.separator() # Head if self.bf_Model_Type == 'bf_Model_Bolt': col.prop(self, 'bf_Head_Type') if self.bf_Head_Type == 'bf_Head_Hex': col.prop(self, 'bf_Hex_Head_Height') col.prop(self, 'bf_Hex_Head_Flat_Distance') elif self.bf_Head_Type == 'bf_Head_Cap': col.prop(self, 'bf_Cap_Head_Height') col.prop(self, 'bf_Cap_Head_Dia') elif self.bf_Head_Type == 'bf_Head_Dome': col.prop(self, 'bf_Dome_Head_Dia') elif self.bf_Head_Type == 'bf_Head_Pan': col.prop(self, 'bf_Pan_Head_Dia') elif self.bf_Head_Type == 'bf_Head_CounterSink': col.prop(self, 'bf_CounterSink_Head_Dia') col.separator() # Shank if self.bf_Model_Type == 'bf_Model_Bolt': col.label(text='Shank') col.prop(self, 'bf_Shank_Length') col.prop(self, 'bf_Shank_Dia') col.separator() # Nut if self.bf_Model_Type == 'bf_Model_Nut': col.prop(self, 'bf_Nut_Type') col.prop(self, 'bf_Hex_Nut_Height') col.prop(self, 'bf_Hex_Nut_Flat_Distance') # Thread col.label(text='Thread') if self.bf_Model_Type == 'bf_Model_Bolt': col.prop(self, 'bf_Thread_Length') col.prop(self, 'bf_Major_Dia') col.prop(self, 'bf_Minor_Dia') col.prop(self, 'bf_Pitch') col.prop(self, 'bf_Crest_Percent') col.prop(self, 'bf_Root_Percent') col.prop(self, 'bf_Div_Count') @classmethod def poll(cls, context): return context.scene is not None def execute(self, context): # print('EXECUTING...') createMesh.Create_New_Mesh(self, context, self.align_matrix) return {'FINISHED'} def invoke(self, context, event): # print('\n___________START_____________') # store creation_matrix self.align_matrix = align_matrix(context) self.execute(context) return {'FINISHED'}
class SvNurbsLoftNode(bpy.types.Node, SverchCustomTreeNode): """ Triggers: NURBS Loft / Skin Tooltip: Generate a NURBS surface by lofting (skinning) through several NURBS-like curves """ bl_idname = 'SvNurbsLoftNode' bl_label = 'NURBS Loft' bl_icon = 'OUTLINER_OB_EMPTY' sv_icon = 'SV_SURFACE_FROM_CURVES' u_knots_modes = [ ('UNIFY', "Unify", "Unify knot vectors of curves by inserting knots into curves where needed", 0), ('AVERAGE', "Average", "Use average knot vector from curves; this will work only when curves have same number of control points!", 1) ] u_knots_mode : EnumProperty( name = "U Knots", description = "How to make slice curves knot vectors equal", items = u_knots_modes, default = 'UNIFY', update = updateNode) metric : EnumProperty( name = "Metric", description = "Metric to be used for interpolation", items = supported_metrics, default = 'DISTANCE', update = updateNode) def get_implementations(self, context): items = [] i = 0 if geomdl is not None: item = (SvNurbsCurve.GEOMDL, "Geomdl", "Geomdl (NURBS-Python) package implementation",i) i += 1 items.append(item) item = (SvNurbsCurve.NATIVE, "Sverchok", "Sverchok built-in implementation", i) items.append(item) return items nurbs_implementation : EnumProperty( name = "Implementation", items = get_implementations, update = updateNode) degree_v : IntProperty( name = "Degree V", min = 1, max = 7, default = 3, update = updateNode) def draw_buttons(self, context, layout): layout.prop(self, 'nurbs_implementation', text='') def draw_buttons_ext(self, context, layout): self.draw_buttons(context, layout) layout.prop(self, 'u_knots_mode') layout.prop(self, 'metric') def sv_init(self, context): self.inputs.new('SvCurveSocket', "Curves") self.inputs.new('SvStringsSocket', "DegreeV").prop_name = 'degree_v' self.outputs.new('SvSurfaceSocket', "Surface") self.outputs.new('SvCurveSocket', "UnifiedCurves") self.outputs.new('SvCurveSocket', "VCurves") def process(self): if not any(socket.is_linked for socket in self.outputs): return curves_s = self.inputs['Curves'].sv_get() degrees_s = self.inputs['DegreeV'].sv_get() curves_s = ensure_nesting_level(curves_s, 3, data_types=(SvCurve,)) degrees_s = ensure_nesting_level(degrees_s, 2) surface_out = [] curves_out = [] v_curves_out = [] for curves_i, degrees in zip_long_repeat(curves_s, degrees_s): new_surfaces = [] new_curves = [] new_v_curves = [] for curves, degree_v in zip_long_repeat(curves_i, degrees): curves = [SvNurbsCurve.to_nurbs(c) for c in curves] if any(c is None for c in curves): raise Exception("Some of curves are not NURBS!") unified_curves, v_curves, new_surface = simple_loft(curves, degree_v = degree_v, knots_u = self.u_knots_mode, metric = self.metric, implementation = self.nurbs_implementation) new_surfaces.append(new_surface) new_curves.extend(unified_curves) new_v_curves.extend(v_curves) surface_out.append(new_surfaces) curves_out.append(new_curves) v_curves_out.append(new_v_curves) self.outputs['Surface'].sv_set(surface_out) self.outputs['UnifiedCurves'].sv_set(curves_out) self.outputs['VCurves'].sv_set(v_curves_out)