diff --git a/add_dimension.py b/add_dimension.py index 1b95bbb96623aa21f4ee7f91c0c67c81a035d50c..e62b56f3513731fd244dae36d6dbbf4e99800beb 100644 --- a/add_dimension.py +++ b/add_dimension.py @@ -1724,7 +1724,7 @@ def createCurve(vertArray, self, align_matrix): DimensionCurve.rotation_euler[0] = radians(self.Dimension_rotation) DimensionCurve.rotation_euler[1] = u1 DimensionCurve.rotation_euler[2] = u2 - + # Align to view if self.Dimension_align_to_camera : obj_camera = bpy.context.scene.camera @@ -1747,7 +1747,7 @@ def createCurve(vertArray, self, align_matrix): group_name = 'Dimensions' bpy.ops.object.mode_set(mode = 'OBJECT') - + if group_name in bpy.data.groups: group = bpy.data.groups[group_name] else: @@ -1764,7 +1764,7 @@ def createCurve(vertArray, self, align_matrix): if self.Dimension_appoint_parent and not self.Dimension_parent == '': const = DimensionCurve.constraints.new(type='CHILD_OF') const.target = bpy.data.objects[self.Dimension_parent] - const.inverse_matrix = bpy.data.objects[self.Dimension_parent].matrix_world.inverted() + const.inverse_matrix = bpy.data.objects[self.Dimension_parent].matrix_world.inverted() bpy.context.scene.update() bpy.ops.object.select_all(action='DESELECT') @@ -1818,7 +1818,7 @@ def createCurve(vertArray, self, align_matrix): #### Parent DimensionCurve.Dimension_parent = self.Dimension_parent DimensionCurve.Dimension_appoint_parent = self.Dimension_appoint_parent - + #### Units DimensionCurve.Dimension_units = self.Dimension_units DimensionCurve.Dimension_add_units_name = self.Dimension_add_units_name diff --git a/add_mesh_clusters/add_mesh_cluster.py b/add_mesh_clusters/add_mesh_cluster.py index 9e30203fa00cc43eeef57bea7e6fa4bb99f020f0..53e54e1e48a9c8d3b81e3ecf49eb300927031bc9 100644 --- a/add_mesh_clusters/add_mesh_cluster.py +++ b/add_mesh_clusters/add_mesh_cluster.py @@ -171,14 +171,14 @@ class CLASS_atom_cluster_Elements(object): self.radii_ionic = radii_ionic # This is the class, which stores the properties of one atom. -class CLASS_atom_cluster_atom(object): +class CLASS_atom_cluster_atom(object): __slots__ = ('location') def __init__(self, location): self.location = location # ----------------------------------------------------------------------------- # Read atom data - + def DEF_atom_read_atom_data(): del ATOM_CLUSTER_ELEMENTS[:] @@ -195,7 +195,7 @@ def DEF_atom_read_atom_data(): radii,radii_ionic) ATOM_CLUSTER_ELEMENTS.append(li) - + # ----------------------------------------------------------------------------- # Routines for shapes @@ -217,19 +217,19 @@ def vec_in_parabole(atom_pos, height, diameter): regular = True inner = True - - px = atom_pos[0] - py = atom_pos[1] + + px = atom_pos[0] + py = atom_pos[1] pz = atom_pos[2] + height/2.0 - + a = diameter / sqrt(4 * height) - - + + if pz < 0.0: return (False, False) if px == 0.0 and py == 0.0: return (True, True) - + if py == 0.0: y = 0.0 x = a * a * pz / px @@ -238,17 +238,17 @@ def vec_in_parabole(atom_pos, height, diameter): y = pz * py * a * a / (px*px + py*py) x = y * px / py z = (x*x + y*y) / (a * a) - + if( atom_pos.length > sqrt(x*x+y*y+z*z) ): regular = False - + return (regular, inner) def vec_in_pyramide_square(atom_pos, size, skin): - + """ - Please, if possible leave all this! The code documents the + Please, if possible leave all this! The code documents the mathemetical way of cutting a pyramide with square base. P1 = Vector((-size/2, 0.0, -size/4)) @@ -262,7 +262,7 @@ def vec_in_pyramide_square(atom_pos, size, skin): v12 = P1 - P6 n1 = v11.cross(v12) g1 = -n1 * P1 - + # Second face v21 = P6 - P4 v22 = P6 - P5 @@ -274,20 +274,20 @@ def vec_in_pyramide_square(atom_pos, size, skin): v32 = P1 - P6 n3 = v32.cross(v31) g3 = -n3 * P1 - + # Forth face v41 = P6 - P2 v42 = P2 - P4 n4 = v41.cross(v42) g4 = -n4 * P2 - + # Fith face, base v51 = P2 - P1 v52 = P2 - P4 n5 = v51.cross(v52) g5 = -n5 * P2 """ - + # A much faster way for calculation: size2 = size * size size3 = size2 * size @@ -300,7 +300,7 @@ def vec_in_pyramide_square(atom_pos, size, skin): n4 = Vector(( 1/4, -1/4, 1/4)) * size2 g4 = g1 n5 = Vector(( 0.0, 0.0, -1/2)) * size2 - g5 = -1/8 * size3 + g5 = -1/8 * size3 distance_plane_1 = abs((n1 * atom_pos - g1)/n1.length) on_plane_1 = (atom_pos - n1 * (distance_plane_1/n1.length)).length @@ -330,7 +330,7 @@ def vec_in_pyramide_square(atom_pos, size, skin): return (regular, inner) size = size * (1.0 - skin) - + size2 = size * size size3 = size2 * size n1 = Vector((-1/4, -1/4, 1/4)) * size2 @@ -342,7 +342,7 @@ def vec_in_pyramide_square(atom_pos, size, skin): n4 = Vector(( 1/4, -1/4, 1/4)) * size2 g4 = g1 n5 = Vector(( 0.0, 0.0, -1/2)) * size2 - g5 = -1/8 * size3 + g5 = -1/8 * size3 distance_plane_1 = abs((n1 * atom_pos - g1)/n1.length) on_plane_1 = (atom_pos - n1 * (distance_plane_1/n1.length)).length @@ -354,7 +354,7 @@ def vec_in_pyramide_square(atom_pos, size, skin): on_plane_4 = (atom_pos - n4 * (distance_plane_4/n4.length)).length distance_plane_5 = abs((n5 * atom_pos - g5)/n5.length) on_plane_5 = (atom_pos - n5 * (distance_plane_5/n5.length)).length - + inner = False if(atom_pos.length > on_plane_1): inner = True @@ -371,22 +371,22 @@ def vec_in_pyramide_square(atom_pos, size, skin): def vec_in_pyramide_hex_abc(atom_pos, size, skin): - + a = size/2.0 #c = size/2.0*cos((30/360)*2.0*pi) c = size * 0.4330127020 - #s = size/2.0*sin((30/360)*2.0*pi) - s = size * 0.25 + #s = size/2.0*sin((30/360)*2.0*pi) + s = size * 0.25 #h = 2.0 * (sqrt(6.0)/3.0) * c h = 1.632993162 * c """ - Please, if possible leave all this! The code documents the + Please, if possible leave all this! The code documents the mathemetical way of cutting a tetraeder. P1 = Vector((0.0, a, 0.0)) P2 = Vector(( -c, -s, 0.0)) - P3 = Vector(( c, -s, 0.0)) + P3 = Vector(( c, -s, 0.0)) P4 = Vector((0.0, 0.0, h)) C = (P1+P2+P3+P4)/4.0 P1 = P1 - C @@ -399,7 +399,7 @@ def vec_in_pyramide_hex_abc(atom_pos, size, skin): v12 = P1 - P4 n1 = v11.cross(v12) g1 = -n1 * P1 - + # Second face v21 = P2 - P3 v22 = P2 - P4 @@ -411,7 +411,7 @@ def vec_in_pyramide_hex_abc(atom_pos, size, skin): v32 = P3 - P4 n3 = v31.cross(v32) g3 = -n3 * P3 - + # Forth face v41 = P2 - P1 v42 = P2 - P3 @@ -452,12 +452,12 @@ def vec_in_pyramide_hex_abc(atom_pos, size, skin): return (regular, inner) size = size * (1.0 - skin) - + a = size/2.0 #c = size/2.0*cos((30/360)*2.0*pi) c= size * 0.4330127020 - #s = size/2.0*sin((30/360)*2.0*pi) - s = size * 0.25 + #s = size/2.0*sin((30/360)*2.0*pi) + s = size * 0.25 #h = 2.0 * (sqrt(6.0)/3.0) * c h = 1.632993162 * c @@ -478,7 +478,7 @@ def vec_in_pyramide_hex_abc(atom_pos, size, skin): on_plane_3 = (atom_pos - n3 * (distance_plane_3/n3.length)).length distance_plane_4 = abs((n4 * atom_pos - g4)/n4.length) on_plane_4 = (atom_pos - n4 * (distance_plane_4/n4.length)).length - + inner = False if(atom_pos.length > on_plane_1): inner = True @@ -490,7 +490,7 @@ def vec_in_pyramide_hex_abc(atom_pos, size, skin): inner = True return (regular, inner) - + def vec_in_octahedron(atom_pos,size, skin): @@ -499,7 +499,7 @@ def vec_in_octahedron(atom_pos,size, skin): inner = True """ - Please, if possible leave all this! The code documents the + Please, if possible leave all this! The code documents the mathemetical way of cutting an octahedron. P1 = Vector((-size/2, 0.0, 0.0)) @@ -514,19 +514,19 @@ def vec_in_octahedron(atom_pos,size, skin): v12 = P2 - P3 n1 = v11.cross(v12) g1 = -n1 * P2 - + # Second face v21 = P1 - P5 v22 = P1 - P3 n2 = v21.cross(v22) - g2 = -n2 * P1 - + g2 = -n2 * P1 + # Third face v31 = P1 - P2 v32 = P1 - P6 n3 = v31.cross(v32) g3 = -n3 * P1 - + # Forth face v41 = P6 - P2 v42 = P2 - P4 @@ -557,7 +557,7 @@ def vec_in_octahedron(atom_pos,size, skin): n8 = v82.cross(v81) g8 = -n8 * P1 """ - + # A much faster way for calculation: size2 = size * size size3 = size2 * size @@ -720,12 +720,12 @@ def vec_in_truncated_octahedron(atom_pos,size, skin): # pp = (size/2.0) - (sqrt(2.0)/2.0) * ((size/sqrt(2.0))/3.0) pp = size / 3.0 - n_1 = Vector((1.0,0.0,0.0)) - n_2 = Vector((-1.0,0.0,0.0)) - n_3 = Vector((0.0,1.0,0.0)) + n_1 = Vector((1.0,0.0,0.0)) + n_2 = Vector((-1.0,0.0,0.0)) + n_3 = Vector((0.0,1.0,0.0)) n_4 = Vector((0.0,-1.0,0.0)) - n_5 = Vector((0.0,0.0,1.0)) - n_6 = Vector((0.0,0.0,-1.0)) + n_5 = Vector((0.0,0.0,1.0)) + n_6 = Vector((0.0,0.0,-1.0)) distance_plane_1b = abs((n_1 * atom_pos + pp)/n_1.length) on_plane_1b = (atom_pos - n_1 * (distance_plane_1b/n_1.length)).length @@ -773,7 +773,7 @@ def vec_in_truncated_octahedron(atom_pos,size, skin): return (regular, inner) size = size * (1.0 - skin) - + # The normal octahedron size2 = size * size size3 = size2 * size @@ -815,13 +815,13 @@ def vec_in_truncated_octahedron(atom_pos,size, skin): # pp = (size/2.0) - (sqrt(2.0)/2.0) * ((size/sqrt(2.0))/3.0) pp = size / 3.0 - n_1 = Vector((1.0,0.0,0.0)) - n_2 = Vector((-1.0,0.0,0.0)) - n_3 = Vector((0.0,1.0,0.0)) + n_1 = Vector((1.0,0.0,0.0)) + n_2 = Vector((-1.0,0.0,0.0)) + n_3 = Vector((0.0,1.0,0.0)) n_4 = Vector((0.0,-1.0,0.0)) - n_5 = Vector((0.0,0.0,1.0)) - n_6 = Vector((0.0,0.0,-1.0)) - + n_5 = Vector((0.0,0.0,1.0)) + n_6 = Vector((0.0,0.0,-1.0)) + distance_plane_1b = abs((n_1 * atom_pos + pp)/n_1.length) on_plane_1b = (atom_pos - n_1 * (distance_plane_1b/n_1.length)).length distance_plane_2b = abs((n_2 * atom_pos + pp)/n_2.length) @@ -865,7 +865,7 @@ def vec_in_truncated_octahedron(atom_pos,size, skin): inner = True if(atom_pos.length > on_plane_6b): inner = True - + return (regular, inner) # ----------------------------------------------------------------------------- @@ -906,11 +906,11 @@ def create_hexagonal_abcabc_lattice(ctype, size, skin, lattice): for k in range(-number_z,number_z+1): for j in range(-number_y,number_y+1): for i in range(-number_x,number_x+1): - atom = Vector((float(i)*e,float(j)*f,float(k)*g)) + atom = Vector((float(i)*e,float(j)*f,float(k)*g)) if y_displ == 1: if z_displ == 1: - atom[0] += e/2.0 + atom[0] += e/2.0 else: atom[0] -= e/2.0 if z_displ == 1: @@ -926,7 +926,7 @@ def create_hexagonal_abcabc_lattice(ctype, size, skin, lattice): # size = height, skin = diameter message = vec_in_pyramide_hex_abc(atom, size, skin) elif ctype == "parabolid_abc": - message = vec_in_parabole(atom, size, skin) + message = vec_in_parabole(atom, size, skin) if message[0] == True and message[1] == True: atom_add = CLASS_atom_cluster_atom(atom) @@ -934,8 +934,8 @@ def create_hexagonal_abcabc_lattice(ctype, size, skin, lattice): atom_number_total += 1 atom_number_drawn += 1 if message[0] == True and message[1] == False: - atom_number_total += 1 - + atom_number_total += 1 + if y_displ == 1: y_displ = 0 else: @@ -990,10 +990,10 @@ def create_hexagonal_abab_lattice(ctype, size, skin, lattice): for i in range(-number_x,number_x+1): atom = Vector((float(i)*e,float(j)*f,float(k)*g)) - + if "odd" in y_displ: if "odd" in z_displ: - atom[0] += e/2.0 + atom[0] += e/2.0 else: atom[0] -= e/2.0 if "odd" in z_displ: @@ -1004,16 +1004,16 @@ def create_hexagonal_abab_lattice(ctype, size, skin, lattice): message = vec_in_sphere(atom, size, skin) elif ctype == "parabolid_ab": # size = height, skin = diameter - message = vec_in_parabole(atom, size, skin) - + message = vec_in_parabole(atom, size, skin) + if message[0] == True and message[1] == True: atom_add = CLASS_atom_cluster_atom(atom) ATOM_CLUSTER_ALL_ATOMS.append(atom_add) atom_number_total += 1 atom_number_drawn += 1 if message[0] == True and message[1] == False: - atom_number_total += 1 - + atom_number_total += 1 + if "even" in y_displ: y_displ = "odd" else: @@ -1034,7 +1034,7 @@ def create_square_lattice(ctype, size, skin, lattice): atom_number_total = 0 atom_number_drawn = 0 - + if ctype == "parabolid_square": # size = height, skin = diameter number_k = int(size/(2.0*lattice)) @@ -1043,14 +1043,14 @@ def create_square_lattice(ctype, size, skin, lattice): else: number_k = int(size/(2.0*lattice)) number_j = int(size/(2.0*lattice)) - number_i = int(size/(2.0*lattice)) + number_i = int(size/(2.0*lattice)) for k in range(-number_k,number_k+1): for j in range(-number_j,number_j+1): for i in range(-number_i,number_i+1): - atom = Vector((float(i),float(j),float(k))) * lattice + atom = Vector((float(i),float(j),float(k))) * lattice if ctype == "sphere_square": message = vec_in_sphere(atom, size, skin) @@ -1058,9 +1058,9 @@ def create_square_lattice(ctype, size, skin, lattice): message = vec_in_pyramide_square(atom, size, skin) elif ctype == "parabolid_square": # size = height, skin = diameter - message = vec_in_parabole(atom, size, skin) + message = vec_in_parabole(atom, size, skin) elif ctype == "octahedron": - message = vec_in_octahedron(atom, size, skin) + message = vec_in_octahedron(atom, size, skin) elif ctype == "truncated_octahedron": message = vec_in_truncated_octahedron(atom,size, skin) @@ -1070,7 +1070,7 @@ def create_square_lattice(ctype, size, skin, lattice): atom_number_total += 1 atom_number_drawn += 1 if message[0] == True and message[1] == False: - atom_number_total += 1 + atom_number_total += 1 print("Atom positions calculated") @@ -1092,7 +1092,7 @@ def create_square_lattice(ctype, size, skin, lattice): # The following code is a translation from an existing Fortran code into Python. # The Fortran code has been created by Christine Mottet and translated by me -# (Clemens Barth). +# (Clemens Barth). # Although a couple of code lines are non-typical for Python, it is best to # leave the code as is. @@ -1138,7 +1138,7 @@ def create_icosahedron(size, lattice): z[i] = 0.0 y[i+4] = 0.0 x[i+8] = 0.0 - + for i in range(2, 3+1): x[i] = tdef x[i+2] = -tdef @@ -1171,7 +1171,7 @@ def create_icosahedron(size, lattice): for i in range(1, 12+1): for j in range(1, 12+1): naret[i][j] = 0 - for k in range (1, 12+1): + for k in range (1, 12+1): nfacet[i][j][k] = 0 nl1 = 6 @@ -1195,7 +1195,7 @@ def create_icosahedron(size, lattice): for j in range(2, 12+1): if j <= i: continue - + xij = xs[j] - xs[i] yij = ys[j] - ys[i] zij = zs[j] - zs[i] @@ -1208,11 +1208,11 @@ def create_icosahedron(size, lattice): diffij = abs(dij2-dssn2) if diffij >= epsi: continue - + for k in range(3, 12+1): if k <= j: continue - + xjk = xs[k] - xs[j] yjk = ys[k] - ys[j] zjk = zs[k] - zs[j] @@ -1223,7 +1223,7 @@ def create_icosahedron(size, lattice): diffjk = abs(djk2-dssn2) if diffjk >= epsi: continue - + xik = xs[k] - xs[i] yik = ys[k] - ys[i] zik = zs[k] - zs[i] @@ -1234,7 +1234,7 @@ def create_icosahedron(size, lattice): diffik = abs(dik2-dssn2) if diffik >= epsi: continue - + if nfacet[i][j][k] != 0: continue @@ -1294,7 +1294,7 @@ def create_icosahedron(size, lattice): for i in range (1,natot+1): - atom = Vector((x[i],y[i],z[i])) * lattice + atom = Vector((x[i],y[i],z[i])) * lattice atom_add = CLASS_atom_cluster_atom(atom) ATOM_CLUSTER_ALL_ATOMS.append(atom_add) @@ -1302,20 +1302,3 @@ def create_icosahedron(size, lattice): atom_number_drawn += 1 return (atom_number_total, atom_number_drawn) - - - - - - - - - - - - - - - - - diff --git a/add_mesh_rocks/rockgen.py b/add_mesh_rocks/rockgen.py index 013d3e0e005b45717d8882370c0bcde44ecf4c39..eb66c77a8101369ccc76e363d1b9c42cc5877f44 100644 --- a/add_mesh_rocks/rockgen.py +++ b/add_mesh_rocks/rockgen.py @@ -995,7 +995,7 @@ def generateObject(context, muX, sigmaX, scaleX, upperSkewX, muY, sigmaY, if scaleDisplace: ## bpy.data.objects[name].scale = Vector((averageX, averageY, averageZ)) obj.object.scale = Vector((averageX, averageY, averageZ)) - + # For a slight speed bump / Readability: ## mesh = bpy.data.meshes[name] mesh = obj.object.data diff --git a/amaranth/node_editor/switch_material.py b/amaranth/node_editor/switch_material.py index bd5d6bcae24b40e0b888b2da382ddecbfd83cf86..c27e0355477098977fc05d0effd07da92a5d5a32 100644 --- a/amaranth/node_editor/switch_material.py +++ b/amaranth/node_editor/switch_material.py @@ -54,7 +54,7 @@ class AMNodeEditorMaterialSelect(bpy.types.Operator): @classmethod def poll(cls, context): return context.active_object - + def execute(self,context): bpy.context.active_object.active_material_index = int(self.material_select) return {'FINISHED'} diff --git a/amaranth/render/unsimplify.py b/amaranth/render/unsimplify.py index 9d01b0881db3ca7f23b989b2b5ecb938cfa46366..25f9df1bc7cc831852c8fd54124a375a64c89c32 100644 --- a/amaranth/render/unsimplify.py +++ b/amaranth/render/unsimplify.py @@ -81,4 +81,3 @@ def unregister(): bpy.types.CYCLES_SCENE_PT_simplify.remove(unsimplify_ui) else: bpy.types.CyclesScene_PT_simplify.remove(unsimplify_ui) - diff --git a/automat/AdjOp.py b/automat/AdjOp.py index 846ba776d73f00ed8f2c9edc7ad44c871ede059f..c9feb1df0c96747922bc0d58ef129cc2b69cdfa7 100644 --- a/automat/AdjOp.py +++ b/automat/AdjOp.py @@ -5,34 +5,34 @@ if "bpy" in locals(): importlib.reload(JSONOps) else: from . import JSONOps - + import bpy import os class AdjustableOperatorFromTexture(bpy.types.Operator): - + """This operator generates adjustable materials from textures in Cycles. This is a subclass from bpy.types.Operator. """ # Metadata of the operator - + bl_idname = "com.new_adj_automat" bl_label = "Adjustable Material from Image" bl_options = {"UNDO"} - + # Variables used for storing the filepath given by blender's file manager - + filepath = bpy.props.StringProperty(subtype="FILE_PATH") filename = bpy.props.StringProperty() directory = bpy.props.StringProperty(subtype="FILE_PATH") - - + + def execute(self, context): - + """This is the main runnable method of the operator. This creates all the node setup.""" @@ -40,12 +40,12 @@ This creates all the node setup.""" # Create the material mat = bpy.data.materials.new("Material") - + mat.use_nodes = True nodes = mat.node_tree.nodes # Empty whatever nodes we allready had. - + for node in nodes.keys(): nodes.remove(nodes[node]) @@ -70,7 +70,7 @@ This creates all the node setup.""" # We set one of our blurs to be stronger blurs[1]["Blur strength"].outputs[0].default_value = 1000 - + # We link the blurs up to the rest of the material links = mat.node_tree.links @@ -89,26 +89,26 @@ This creates all the node setup.""" nodes_dict["Bump Image"].image = image_data # Try to add the material to the selected object - + try: bpy.context.object.data.materials.append(mat) except AttributeError: - + # If there is no object with materials selected, # don't add the material to anythinng. - + pass - + # Tell that all went well - + return {"FINISHED"} - + def invoke(self, context, event): - + """This method opens the file browser. After that, the execute(...) method gets ran, creating the node setup. It also checks that the render engine is Cycles. """ - + if bpy.context.scene.render.engine == 'CYCLES': self.filename = "" context.window_manager.fileselect_add(self) diff --git a/automat/JSONOps.py b/automat/JSONOps.py index b0800846ed66381bb37f382dfdf1b352a93e4862..30d79ba0e92fbb183d970a81d721a38550b22ed1 100644 --- a/automat/JSONOps.py +++ b/automat/JSONOps.py @@ -75,7 +75,7 @@ The file is read using Python's built-in JSON parser, so indentation or line bre nodes_dict = {} nodes = mat.node_tree.nodes - # We iterate a first time to create the nodes with their settings + # We iterate a first time to create the nodes with their settings for node in nodes_JSON["NodeSetup"]: technical_name = node["type"] @@ -116,7 +116,7 @@ The file is read using Python's built-in JSON parser, so indentation or line bre if len(node["in"][i]) == 3: # Contruct and execute the line adding a link - + exec ("links.new(nodes_dict[\"" + node["in"][i][0] + "\"].outputs[" + str(node["in"][i][1]) + "], nodes_dict[\"" + node["label"] + "\"].inputs[" @@ -133,4 +133,4 @@ The file is read using Python's built-in JSON parser, so indentation or line bre # We return the nodes for purposes of further access to them - return nodes_dict \ No newline at end of file + return nodes_dict diff --git a/cacharanth/__init__.py b/cacharanth/__init__.py index 6a1aada5326fa4cb924747e7ee06f51043a84ef7..6c6cf0e45f3a95ad4f8bed244e83ba34226aadca 100644 --- a/cacharanth/__init__.py +++ b/cacharanth/__init__.py @@ -33,7 +33,7 @@ bl_info = { import bpy from cacharanth import ui, meshcache - + def register(): ui.register() meshcache.register() diff --git a/cacharanth/util.py b/cacharanth/util.py index 2e79345fcab78b12b91ed0129fa94c3ff26e7eef..f8386fbdd9091374eb980ed0e8da9617b274f9c9 100644 --- a/cacharanth/util.py +++ b/cacharanth/util.py @@ -42,14 +42,14 @@ class OperatorCallContext(): # store active/selected state to restore it after operator execution self.curact = scene.objects.active self.cursel = { ob : ob.select for ob in scene.objects } - + # undo can store files a lot when running operators internally, # disable since we only need one undo step after main operators anyway self.use_global_undo = prefs.edit.use_global_undo prefs.edit.use_global_undo = False return (self.curact, self.cursel) - + def __exit__(self, exc_type, exc_value, traceback): scene = bpy.context.scene prefs = bpy.context.user_preferences @@ -63,7 +63,7 @@ class OperatorCallContext(): def select_single_object(ob): scene = bpy.context.scene - + scene.objects.active = ob for tob in scene.objects: tob.select = (tob == ob) diff --git a/cmu_mocap_browser/data.py b/cmu_mocap_browser/data.py index c201c89156f24796fe63b5bb0beff5cf66e5c573..ddec7a4e3aa80f854209ce69af490d0a360a4888 100644 --- a/cmu_mocap_browser/data.py +++ b/cmu_mocap_browser/data.py @@ -123,4 +123,3 @@ class CMUMocapLib(bpy.types.AddonPreferences): layout.prop(self, "local_storage") layout.prop(self, "follow_structure") layout.prop(self, "automatically_import") - diff --git a/cmu_mocap_browser/makehuman.py b/cmu_mocap_browser/makehuman.py index 6c5c951facd4024a9ae5296a8d5fb025f42e5b02..466a40b3f49ea3bf242b0045eaa3fd0733d9a9dc 100644 --- a/cmu_mocap_browser/makehuman.py +++ b/cmu_mocap_browser/makehuman.py @@ -32,13 +32,13 @@ lfoot LegIK_L T_pose_align = [d.split() for d in """\ -clavicle UpArmRot -humerus LoArm +clavicle UpArmRot +humerus LoArm radius Hand .8 wrist Hand -hipjoint UpLeg -femur LoLeg -tibia Foot +hipjoint UpLeg +femur LoLeg +tibia Foot foot Toe""".splitlines()] @@ -126,7 +126,7 @@ class CMUMocapAlignArmatures(bpy.types.Operator): c_d = DPB['Hip_L'].matrix.translation b_d = .5 * (c_d + DPB['Hip_R'].matrix.translation) - # get alignment matrix + # get alignment matrix S = Matrix().to_3x3() S[0] = (c_s - b_s).normalized() S[1] = (a_s - b_s).normalized() @@ -142,14 +142,14 @@ class CMUMocapAlignArmatures(bpy.types.Operator): # scale source to match destination s = (a_d - b_d).length / (a_s - b_s).length bpy.ops.transform.resize(value=(s, s, s)) - + # align armatures rot = T.to_quaternion() bpy.ops.transform.rotate(value=rot.angle, axis=rot.axis) a_s = SPB['upperneck'].matrix.translation a_s = SMW * a_s bpy.ops.transform.translate(value=a_d - a_s) - + bpy.ops.pose.select_all(action='DESELECT') for bdef in T_pose_align: for side in "lr": @@ -280,7 +280,7 @@ class CMUMocapTransferer(bpy.types.Operator): c = DPB[db].constraints["Floor"] c.name = name c.target = floor - + bpy.ops.mhx.toggle_fk_ik(toggle="MhaArmIk_L 1 2 3") bpy.ops.mhx.toggle_fk_ik(toggle="MhaArmIk_R 1 18 19") bpy.ops.mhx.toggle_fk_ik(toggle="MhaLegIk_L 1 4 5") @@ -296,4 +296,3 @@ class CMUMocapTransferer(bpy.types.Operator): bpy.context.scene.frame_set(bpy.context.scene.frame_current) context.window_manager.event_timer_remove(self.timer) bpy.ops.object.mode_set(mode='OBJECT') - diff --git a/curve_tools/Curves.py b/curve_tools/Curves.py index 6f74a2b3fc28c309cf404c4282f0333cbeca04ce..e2608eeb4e3a4d23aa524850c756d95bdcaf5bc7 100644 --- a/curve_tools/Curves.py +++ b/curve_tools/Curves.py @@ -7,17 +7,17 @@ class BezierPoint: @staticmethod def FromBlenderBezierPoint(blenderBezierPoint): return BezierPoint(blenderBezierPoint.handle_left, blenderBezierPoint.co, blenderBezierPoint.handle_right) - - + + def __init__(self, handle_left, co, handle_right): self.handle_left = handle_left self.co = co self.handle_right = handle_right - - + + def Copy(self): return BezierPoint(self.handle_left.copy(), self.co.copy(), self.handle_right.copy()) - + def Reversed(self): return BezierPoint(self.handle_right, self.co, self.handle_left) @@ -34,14 +34,14 @@ class BezierSegment: bp2 = BezierPoint.FromBlenderBezierPoint(blenderBezierPoint2) return BezierSegment(bp1, bp2) - - + + def Copy(self): return BezierSegment(self.bezierPoint1.Copy(), self.bezierPoint2.Copy()) - + def Reversed(self): return BezierSegment(self.bezierPoint2.Reversed(), self.bezierPoint1.Reversed()) - + def Reverse(self): # make a copy, otherwise neighboring segment may be affected tmp = self.bezierPoint1.Copy() @@ -49,41 +49,41 @@ class BezierSegment: self.bezierPoint2 = tmp self.bezierPoint1.Reverse() self.bezierPoint2.Reverse() - - + + def __init__(self, bezierPoint1, bezierPoint2): # bpy.types.BezierSplinePoint # ## NOTE/TIP: copy() helps with repeated (intersection) action -- ?? self.bezierPoint1 = bezierPoint1.Copy() self.bezierPoint2 = bezierPoint2.Copy() - + self.ctrlPnt0 = self.bezierPoint1.co self.ctrlPnt1 = self.bezierPoint1.handle_right self.ctrlPnt2 = self.bezierPoint2.handle_left self.ctrlPnt3 = self.bezierPoint2.co - + self.coeff0 = self.ctrlPnt0 self.coeff1 = self.ctrlPnt0 * (-3.0) + self.ctrlPnt1 * (+3.0) self.coeff2 = self.ctrlPnt0 * (+3.0) + self.ctrlPnt1 * (-6.0) + self.ctrlPnt2 * (+3.0) self.coeff3 = self.ctrlPnt0 * (-1.0) + self.ctrlPnt1 * (+3.0) + self.ctrlPnt2 * (-3.0) + self.ctrlPnt3 - - + + def CalcPoint(self, parameter = 0.5): parameter2 = parameter * parameter parameter3 = parameter * parameter2 - + rvPoint = self.coeff0 + self.coeff1 * parameter + self.coeff2 * parameter2 + self.coeff3 * parameter3 - + return rvPoint - - + + def CalcDerivative(self, parameter = 0.5): parameter2 = parameter * parameter - + rvPoint = self.coeff1 + self.coeff2 * parameter * 2.0 + self.coeff3 * parameter2 * 3.0 - + return rvPoint - + def CalcLength(self, nrSamples = 2): nrSamplesFloat = float(nrSamples) @@ -91,101 +91,101 @@ class BezierSegment: for iSample in range(nrSamples): par1 = float(iSample) / nrSamplesFloat par2 = float(iSample + 1) / nrSamplesFloat - + point1 = self.CalcPoint(parameter = par1) point2 = self.CalcPoint(parameter = par2) diff12 = point1 - point2 - + rvLength += diff12.magnitude - + return rvLength - - + + #http://en.wikipedia.org/wiki/De_Casteljau's_algorithm def CalcSplitPoint(self, parameter = 0.5): par1min = 1.0 - parameter - + bez00 = self.ctrlPnt0 bez01 = self.ctrlPnt1 bez02 = self.ctrlPnt2 bez03 = self.ctrlPnt3 - + bez10 = bez00 * par1min + bez01 * parameter bez11 = bez01 * par1min + bez02 * parameter bez12 = bez02 * par1min + bez03 * parameter - + bez20 = bez10 * par1min + bez11 * parameter bez21 = bez11 * par1min + bez12 * parameter - + bez30 = bez20 * par1min + bez21 * parameter - + bezPoint1 = BezierPoint(self.bezierPoint1.handle_left, bez00, bez10) bezPointNew = BezierPoint(bez20, bez30, bez21) bezPoint2 = BezierPoint(bez12, bez03, self.bezierPoint2.handle_right) - + return [bezPoint1, bezPointNew, bezPoint2] - + class BezierSpline: @staticmethod def FromSegments(listSegments): rvSpline = BezierSpline(None) - + rvSpline.segments = listSegments - + return rvSpline - - + + def __init__(self, blenderBezierSpline): if not blenderBezierSpline is None: - if blenderBezierSpline.type != 'BEZIER': + if blenderBezierSpline.type != 'BEZIER': print("## ERROR:", "blenderBezierSpline.type != 'BEZIER'") raise Exception("blenderBezierSpline.type != 'BEZIER'") if len(blenderBezierSpline.bezier_points) < 1: if not blenderBezierSpline.use_cyclic_u: print("## ERROR:", "len(blenderBezierSpline.bezier_points) < 1") raise Exception("len(blenderBezierSpline.bezier_points) < 1") - + self.bezierSpline = blenderBezierSpline - + self.resolution = 12 self.isCyclic = False if not self.bezierSpline is None: self.resolution = self.bezierSpline.resolution_u self.isCyclic = self.bezierSpline.use_cyclic_u - + self.segments = self.SetupSegments() - - + + def __getattr__(self, attrName): if attrName == "nrSegments": return len(self.segments) - + if attrName == "bezierPoints": rvList = [] - + for seg in self.segments: rvList.append(seg.bezierPoint1) if not self.isCyclic: rvList.append(self.segments[-1].bezierPoint2) - + return rvList - + if attrName == "resolutionPerSegment": try: rvResPS = int(self.resolution / self.nrSegments) except: rvResPS = 2 if rvResPS < 2: rvResPS = 2 - + return rvResPS - + if attrName == "length": return self.CalcLength() - + return None - - + + def SetupSegments(self): rvSegments = [] if self.bezierSpline is None: return rvSegments - + nrBezierPoints = len(self.bezierSpline.bezier_points) for iBezierPoint in range(nrBezierPoints - 1): bezierPoint1 = self.bezierSpline.bezier_points[iBezierPoint] @@ -195,10 +195,10 @@ class BezierSpline: bezierPoint1 = self.bezierSpline.bezier_points[-1] bezierPoint2 = self.bezierSpline.bezier_points[0] rvSegments.append(BezierSegment.FromBlenderBezierPoints(bezierPoint1, bezierPoint2)) - + return rvSegments - - + + def UpdateSegments(self, newSegments): prevNrSegments = len(self.segments) diffNrSegments = len(newSegments) - prevNrSegments @@ -206,154 +206,154 @@ class BezierSpline: newBezierPoints = [] for segment in newSegments: newBezierPoints.append(segment.bezierPoint1) if not self.isCyclic: newBezierPoints.append(newSegments[-1].bezierPoint2) - + self.bezierSpline.bezier_points.add(diffNrSegments) - + for i, bezPoint in enumerate(newBezierPoints): blBezPoint = self.bezierSpline.bezier_points[i] - + blBezPoint.tilt = 0 blBezPoint.radius = 1.0 - + blBezPoint.handle_left_type = 'FREE' blBezPoint.handle_left = bezPoint.handle_left blBezPoint.co = bezPoint.co blBezPoint.handle_right_type = 'FREE' - blBezPoint.handle_right = bezPoint.handle_right + blBezPoint.handle_right = bezPoint.handle_right self.segments = newSegments else: print("### WARNING: UpdateSegments(): not diffNrSegments > 0") - - + + def Reversed(self): revSegments = [] - + for iSeg in reversed(range(self.nrSegments)): revSegments.append(self.segments[iSeg].Reversed()) - + rvSpline = BezierSpline.FromSegments(revSegments) rvSpline.resolution = self.resolution rvSpline.isCyclic = self.isCyclic - + return rvSpline - - + + def Reverse(self): revSegments = [] - - for iSeg in reversed(range(self.nrSegments)): + + for iSeg in reversed(range(self.nrSegments)): self.segments[iSeg].Reverse() revSegments.append(self.segments[iSeg]) - + self.segments = revSegments - - + + def CalcDivideResolution(self, segment, parameter): if not segment in self.segments: print("### WARNING: InsertPoint(): not segment in self.segments") return None - + iSeg = self.segments.index(segment) dPar = 1.0 / self.nrSegments splinePar = dPar * (parameter + float(iSeg)) - + res1 = int(splinePar * self.resolution) if res1 < 2: print("### WARNING: CalcDivideResolution(): res1 < 2 -- res1: %d" % res1, "-- setting it to 2") res1 = 2 - + res2 = int((1.0 - splinePar) * self.resolution) if res2 < 2: print("### WARNING: CalcDivideResolution(): res2 < 2 -- res2: %d" % res2, "-- setting it to 2") res2 = 2 - + return [res1, res2] # return [self.resolution, self.resolution] - - + + def CalcPoint(self, parameter): nrSegs = self.nrSegments - + segmentIndex = int(nrSegs * parameter) if segmentIndex < 0: segmentIndex = 0 if segmentIndex > (nrSegs - 1): segmentIndex = nrSegs - 1 - + segmentParameter = nrSegs * parameter - segmentIndex if segmentParameter < 0.0: segmentParameter = 0.0 if segmentParameter > 1.0: segmentParameter = 1.0 - + return self.segments[segmentIndex].CalcPoint(parameter = segmentParameter) - - + + def CalcDerivative(self, parameter): nrSegs = self.nrSegments - + segmentIndex = int(nrSegs * parameter) if segmentIndex < 0: segmentIndex = 0 if segmentIndex > (nrSegs - 1): segmentIndex = nrSegs - 1 - + segmentParameter = nrSegs * parameter - segmentIndex if segmentParameter < 0.0: segmentParameter = 0.0 if segmentParameter > 1.0: segmentParameter = 1.0 - + return self.segments[segmentIndex].CalcDerivative(parameter = segmentParameter) - - + + def InsertPoint(self, segment, parameter): if not segment in self.segments: print("### WARNING: InsertPoint(): not segment in self.segments") return iSeg = self.segments.index(segment) nrSegments = len(self.segments) - + splitPoints = segment.CalcSplitPoint(parameter = parameter) bezPoint1 = splitPoints[0] bezPointNew = splitPoints[1] bezPoint2 = splitPoints[2] - + segment.bezierPoint1.handle_right = bezPoint1.handle_right segment.bezierPoint2 = bezPointNew - - if iSeg < (nrSegments - 1): + + if iSeg < (nrSegments - 1): nextSeg = self.segments[iSeg + 1] nextSeg.bezierPoint1.handle_left = bezPoint2.handle_left else: if self.isCyclic: nextSeg = self.segments[0] nextSeg.bezierPoint1.handle_left = bezPoint2.handle_left - - + + newSeg = BezierSegment(bezPointNew, bezPoint2) self.segments.insert(iSeg + 1, newSeg) - - + + def Split(self, segment, parameter): if not segment in self.segments: print("### WARNING: InsertPoint(): not segment in self.segments") return None iSeg = self.segments.index(segment) nrSegments = len(self.segments) - + splitPoints = segment.CalcSplitPoint(parameter = parameter) bezPoint1 = splitPoints[0] bezPointNew = splitPoints[1] bezPoint2 = splitPoints[2] - - + + newSpline1Segments = [] for iSeg1 in range(iSeg): newSpline1Segments.append(self.segments[iSeg1]) if len(newSpline1Segments) > 0: newSpline1Segments[-1].bezierPoint2.handle_right = bezPoint1.handle_right newSpline1Segments.append(BezierSegment(bezPoint1, bezPointNew)) - + newSpline2Segments = [] newSpline2Segments.append(BezierSegment(bezPointNew, bezPoint2)) for iSeg2 in range(iSeg + 1, nrSegments): newSpline2Segments.append(self.segments[iSeg2]) if len(newSpline2Segments) > 1: newSpline2Segments[1].bezierPoint1.handle_left = newSpline2Segments[0].bezierPoint2.handle_left - - + + newSpline1 = BezierSpline.FromSegments(newSpline1Segments) newSpline2 = BezierSpline.FromSegments(newSpline2Segments) - + return [newSpline1, newSpline2] @@ -361,27 +361,27 @@ class BezierSpline: if mode == 'At midpoint': self.JoinAtMidpoint(spline2) return - + if mode == 'Insert segment': self.JoinInsertSegment(spline2) return - - print("### ERROR: Join(): unknown mode:", mode) + + print("### ERROR: Join(): unknown mode:", mode) def JoinAtMidpoint(self, spline2): bezPoint1 = self.segments[-1].bezierPoint2 bezPoint2 = spline2.segments[0].bezierPoint1 - + mpHandleLeft = bezPoint1.handle_left.copy() mpCo = (bezPoint1.co + bezPoint2.co) * 0.5 mpHandleRight = bezPoint2.handle_right.copy() mpBezPoint = BezierPoint(mpHandleLeft, mpCo, mpHandleRight) - + self.segments[-1].bezierPoint2 = mpBezPoint spline2.segments[0].bezierPoint1 = mpBezPoint for seg2 in spline2.segments: self.segments.append(seg2) - + self.resolution += spline2.resolution self.isCyclic = False # is this ok? @@ -389,25 +389,25 @@ class BezierSpline: def JoinInsertSegment(self, spline2): self.segments.append(BezierSegment(self.segments[-1].bezierPoint2, spline2.segments[0].bezierPoint1)) for seg2 in spline2.segments: self.segments.append(seg2) - + self.resolution += spline2.resolution # extra segment will usually be short -- impact on resolution negligable - + self.isCyclic = False # is this ok? - - + + def RefreshInScene(self): bezierPoints = self.bezierPoints - + currNrBezierPoints = len(self.bezierSpline.bezier_points) diffNrBezierPoints = len(bezierPoints) - currNrBezierPoints if diffNrBezierPoints > 0: self.bezierSpline.bezier_points.add(diffNrBezierPoints) - + for i, bezPoint in enumerate(bezierPoints): blBezPoint = self.bezierSpline.bezier_points[i] - + blBezPoint.tilt = 0 blBezPoint.radius = 1.0 - + blBezPoint.handle_left_type = 'FREE' blBezPoint.handle_left = bezPoint.handle_left blBezPoint.co = bezPoint.co @@ -416,179 +416,179 @@ class BezierSpline: self.bezierSpline.use_cyclic_u = self.isCyclic self.bezierSpline.resolution_u = self.resolution - - + + def CalcLength(self): try: nrSamplesPerSegment = int(self.resolution / self.nrSegments) except: nrSamplesPerSegment = 2 if nrSamplesPerSegment < 2: nrSamplesPerSegment = 2 - + rvLength = 0.0 for segment in self.segments: rvLength += segment.CalcLength(nrSamples = nrSamplesPerSegment) - + return rvLength - - + + def GetLengthIsSmallerThan(self, threshold): try: nrSamplesPerSegment = int(self.resolution / self.nrSegments) except: nrSamplesPerSegment = 2 if nrSamplesPerSegment < 2: nrSamplesPerSegment = 2 - + length = 0.0 for segment in self.segments: length += segment.CalcLength(nrSamples = nrSamplesPerSegment) if not length < threshold: return False - + return True - - + + class Curve: def __init__(self, blenderCurve): self.curve = blenderCurve self.curveData = blenderCurve.data - + self.splines = self.SetupSplines() - - + + def __getattr__(self, attrName): if attrName == "nrSplines": return len(self.splines) - + if attrName == "length": return self.CalcLength() - + if attrName == "worldMatrix": return self.curve.matrix_world - + if attrName == "location": return self.curve.location - + return None - - + + def SetupSplines(self): rvSplines = [] for spline in self.curveData.splines: if spline.type != 'BEZIER': print("## WARNING: only bezier splines are supported, atm; other types are ignored") continue - + try: newSpline = BezierSpline(spline) - except: + except: print("## EXCEPTION: newSpline = BezierSpline(spline)") continue - + rvSplines.append(newSpline) - + return rvSplines - - + + def RebuildInScene(self): self.curveData.splines.clear() - + for spline in self.splines: blSpline = self.curveData.splines.new('BEZIER') blSpline.use_cyclic_u = spline.isCyclic blSpline.resolution_u = spline.resolution - + bezierPoints = [] for segment in spline.segments: bezierPoints.append(segment.bezierPoint1) if not spline.isCyclic: bezierPoints.append(spline.segments[-1].bezierPoint2) #else: print("????", "spline.isCyclic") - + nrBezierPoints = len(bezierPoints) blSpline.bezier_points.add(nrBezierPoints - 1) - + for i, blBezPoint in enumerate(blSpline.bezier_points): bezPoint = bezierPoints[i] - + blBezPoint.tilt = 0 blBezPoint.radius = 1.0 - + blBezPoint.handle_left_type = 'FREE' blBezPoint.handle_left = bezPoint.handle_left blBezPoint.co = bezPoint.co blBezPoint.handle_right_type = 'FREE' blBezPoint.handle_right = bezPoint.handle_right - - + + def CalcLength(self): rvLength = 0.0 for spline in self.splines: rvLength += spline.length - + return rvLength - - + + def RemoveShortSplines(self, threshold): splinesToRemove = [] - + for spline in self.splines: if spline.GetLengthIsSmallerThan(threshold): splinesToRemove.append(spline) - + for spline in splinesToRemove: self.splines.remove(spline) - + return len(splinesToRemove) - - + + def JoinNeighbouringSplines(self, startEnd, threshold, mode): nrJoins = 0 - + while True: firstPair = self.JoinGetFirstPair(startEnd, threshold) if firstPair is None: break - + firstPair[0].Join(firstPair[1], mode) self.splines.remove(firstPair[1]) - + nrJoins += 1 - + return nrJoins - - + + def JoinGetFirstPair(self, startEnd, threshold): nrSplines = len(self.splines) - + if startEnd: for iCurrentSpline in range(nrSplines): currentSpline = self.splines[iCurrentSpline] - + for iNextSpline in range(iCurrentSpline + 1, nrSplines): nextSpline = self.splines[iNextSpline] - + currEndPoint = currentSpline.segments[-1].bezierPoint2.co nextStartPoint = nextSpline.segments[0].bezierPoint1.co if Math.IsSamePoint(currEndPoint, nextStartPoint, threshold): return [currentSpline, nextSpline] - + nextEndPoint = nextSpline.segments[-1].bezierPoint2.co currStartPoint = currentSpline.segments[0].bezierPoint1.co if Math.IsSamePoint(nextEndPoint, currStartPoint, threshold): return [nextSpline, currentSpline] - + return None else: for iCurrentSpline in range(nrSplines): currentSpline = self.splines[iCurrentSpline] - + for iNextSpline in range(iCurrentSpline + 1, nrSplines): nextSpline = self.splines[iNextSpline] - + currEndPoint = currentSpline.segments[-1].bezierPoint2.co nextStartPoint = nextSpline.segments[0].bezierPoint1.co if Math.IsSamePoint(currEndPoint, nextStartPoint, threshold): return [currentSpline, nextSpline] - + nextEndPoint = nextSpline.segments[-1].bezierPoint2.co currStartPoint = currentSpline.segments[0].bezierPoint1.co if Math.IsSamePoint(nextEndPoint, currStartPoint, threshold): return [nextSpline, currentSpline] - + if Math.IsSamePoint(currEndPoint, nextEndPoint, threshold): nextSpline.Reverse() #print("## ", "nextSpline.Reverse()") return [currentSpline, nextSpline] - + if Math.IsSamePoint(currStartPoint, nextStartPoint, threshold): currentSpline.Reverse() #print("## ", "currentSpline.Reverse()") return [currentSpline, nextSpline] - + return None diff --git a/curve_tools/Math.py b/curve_tools/Math.py index 208f769e4ffb742b5af6084679429040069e1c1d..8ac6ff4236a8b0c4e68c1d7ba8634f1c17911f43 100644 --- a/curve_tools/Math.py +++ b/curve_tools/Math.py @@ -3,110 +3,110 @@ from mathutils import * def IsSamePoint(v31, v32, limitDistance): if (v31 - v32).magnitude < limitDistance: return True - + return False - + class Plane: @staticmethod def XY(): p1 = Vector((0, 0, 0)) p2 = Vector((1, 0, 0)) p3 = Vector((0, 1, 0)) - + return Plane(p1, p2, p3) - + # plane equation: (p - position).dot(normal) = 0 def __init__(self, P1, P2, P3): self.normal = (P2 - P1).cross(P3 - P1) self.normal.normalize() - + self.position = P1 - - + + def CalcIntersectionPointLineSegment(self, PL1, PL2): DL = PL2 - PL1 - + try: rvPar = ((self.position - PL1).dot(self.normal)) / (DL.dot(self.normal)) except: return None - + return rvPar - - + + def CalcNormalParameter(self, vector): return (vector - self.position).dot(self.normal) - - + + def CalcProjection(self, vector): normalParameter = self.CalcNormalParameter(vector) - + rvv3 = vector - (self.normal * normalParameter) - + return [normalParameter, rvv3] - - - + + + # http://geomalgorithms.com/a07-_distance.html def CalcClosestPointLineSegments(v3P0, v3P1, v3Q0, v3Q1): u = v3P1 - v3P0 v = v3Q1 - v3Q0 - + w0 = v3P0 - v3Q0 a = u.dot(u) b = u.dot(v) c = v.dot(v) d = u.dot(w0) e = v.dot(w0) - - + + try: parP = (b * e - c * d) / (a * c - b * b) except: return None - + try: parQ = (a * e - b * d) / (a * c - b * b) except: return None - - + + return [parP, parQ] - + def CalcIntersectionPointLineSegments(v3P0, v3P1, v3Q0, v3Q1, limitDistance): rvList = CalcClosestPointLineSegments(v3P0, v3P1, v3Q0, v3Q1) if rvList is None: return None - - + + parP = rvList[0] if parP < 0.0: return None if parP > 1.0: return None - + parQ = rvList[1] if parQ < 0.0: return None if parQ > 1.0: return None - - + + pointP = v3P0 + ((v3P1 - v3P0) * parP) pointQ = v3Q0 + ((v3Q1 - v3Q0) * parQ) if not IsSamePoint(pointP, pointQ, limitDistance): return None - + return [parP, parQ, pointP, pointQ] - + def CalcIntersectionPointsLineSegmentsPOV(v3P0, v3P1, v3Q0, v3Q1, v3POV): planeQ = Plane(v3POV, v3Q0, v3Q1) parP = planeQ.CalcIntersectionPointLineSegment(v3P0, v3P1) if parP is None: return None if parP < 0.0: return None if parP > 1.0: return None - + planeP = Plane(v3POV, v3P0, v3P1) parQ = planeP.CalcIntersectionPointLineSegment(v3Q0, v3Q1) if parQ is None: return None if parQ < 0.0: return None if parQ > 1.0: return None - + return [parP, parQ] - + def CalcIntersectionPointsLineSegmentsDIR(v3P0, v3P1, v3Q0, v3Q1, v3DIR): v3POV = v3Q0 + v3DIR planeQ = Plane(v3POV, v3Q0, v3Q1) @@ -114,24 +114,22 @@ def CalcIntersectionPointsLineSegmentsDIR(v3P0, v3P1, v3Q0, v3Q1, v3DIR): if parP is None: return None if parP < 0.0: return None if parP > 1.0: return None - + v3POV = v3P0 + v3DIR planeP = Plane(v3POV, v3P0, v3P1) parQ = planeP.CalcIntersectionPointLineSegment(v3Q0, v3Q1) if parQ is None: return None if parQ < 0.0: return None if parQ > 1.0: return None - + return [parP, parQ] - + def CalcRotationMatrix(v3From, v3To): cross = v3From.cross(v3To) - + try: angle = v3From.angle(v3To) except: return Matrix.Identity(4) - + return Matrix.Rotation(angle, 4, cross) # normalize axis? - - diff --git a/curve_tools/Operators.py b/curve_tools/Operators.py index ac226e2ecb1f9e9f3ac31027a24a0f079e7d4524..6c9eed5a1c9a14e8e8f8c848c2701d0c5d11cfa7 100644 --- a/curve_tools/Operators.py +++ b/curve_tools/Operators.py @@ -16,34 +16,34 @@ class OperatorSelectionInfo(bpy.types.Operator): bl_idname = "curvetools2.operatorselectioninfo" bl_label = "Selection Info" bl_description = "Maintains a list of selected objects in the order they were selected" - - + + @classmethod def poll(cls, context): selectedObjectNames = Properties.CurveTools2SelectedObject.GetSelectedObjectNames() selectedBlenderObjectNames = Properties.CurveTools2SelectedObject.GetSelectedBlenderObjectNames() - + sleepTime = 0.02 - + lock = threading.Lock() lock_holder = threading.Thread(target = Properties.CurveTools2SelectedObject.UpdateThreadTarget, args=(lock, sleepTime, selectedObjectNames, selectedBlenderObjectNames), name='OperatorSelectionInfoThread') # lock_holder = threading.Thread(target = Properties.CurveTools2SelectedObject.UpdateThreadTarget2, args=(lock, sleepTime, selectedObjectNames, selectedBlenderObjectNames, context), name='OperatorSelectionInfoThread') lock_holder.setDaemon(True) lock_holder.start() - + return True - + def execute(self, context): nrSelectedObjects = bpy.context.scene.curvetools.NrSelectedObjects - + self.report({'INFO'}, "Selection Info: nrSelectedObjects: %d" % nrSelectedObjects) - + selectedObjects = bpy.context.scene.curvetools.SelectedObjects selectedObjectValues = selectedObjects.values() for i, selectedObject in enumerate(selectedObjectValues): print("--", "selected object %d of %d: %s" % (i + 1, nrSelectedObjects, selectedObject.name)) - + return {'FINISHED'} @@ -54,26 +54,26 @@ class OperatorCurveInfo(bpy.types.Operator): bl_idname = "curvetools2.operatorcurveinfo" bl_label = "Info" bl_description = "Displays general info about the active/selected curve" - - + + @classmethod def poll(cls, context): return Util.Selected1Curve() - + def execute(self, context): curve = Curves.Curve(context.active_object) - + nrSplines = len(curve.splines) nrSegments = 0 nrEmptySplines = 0 - for spline in curve.splines: + for spline in curve.splines: nrSegments += spline.nrSegments if spline.nrSegments < 1: nrEmptySplines += 1 - - + + self.report({'INFO'}, "nrSplines: %d; nrSegments: %d; nrEmptySplines: %d" % (nrSplines, nrSegments, nrEmptySplines)) - + return {'FINISHED'} @@ -82,18 +82,18 @@ class OperatorCurveLength(bpy.types.Operator): bl_idname = "curvetools2.operatorcurvelength" bl_label = "Length" bl_description = "Calculates the length of the active/selected curve" - - + + @classmethod def poll(cls, context): return Util.Selected1Curve() - + def execute(self, context): curve = Curves.Curve(context.active_object) - + context.scene.curvetools.CurveLength = curve.length - + return {'FINISHED'} @@ -102,31 +102,31 @@ class OperatorSplinesInfo(bpy.types.Operator): bl_idname = "curvetools2.operatorsplinesinfo" bl_label = "Info" bl_description = "Displays general info about the splines of the active/selected curve" - - + + @classmethod def poll(cls, context): return Util.Selected1Curve() - + def execute(self, context): curve = Curves.Curve(context.active_object) nrSplines = len(curve.splines) - + print("") - print("OperatorSplinesInfo:", "nrSplines:", nrSplines) - + print("OperatorSplinesInfo:", "nrSplines:", nrSplines) + nrEmptySplines = 0 for iSpline, spline in enumerate(curve.splines): - print("--", "spline %d of %d: nrSegments: %d" % (iSpline + 1, nrSplines, spline.nrSegments)) - - if spline.nrSegments < 1: + print("--", "spline %d of %d: nrSegments: %d" % (iSpline + 1, nrSplines, spline.nrSegments)) + + if spline.nrSegments < 1: nrEmptySplines += 1 - print("--", "--", "## WARNING: spline has no segments and will therefor be ignored in any further calculations") - - + print("--", "--", "## WARNING: spline has no segments and will therefor be ignored in any further calculations") + + self.report({'INFO'}, "nrSplines: %d; nrEmptySplines: %d" % (nrSplines, nrEmptySplines) + " -- more info: see console") - + return {'FINISHED'} @@ -135,39 +135,39 @@ class OperatorSegmentsInfo(bpy.types.Operator): bl_idname = "curvetools2.operatorsegmentsinfo" bl_label = "Info" bl_description = "Displays general info about the segments of the active/selected curve" - - + + @classmethod def poll(cls, context): return Util.Selected1Curve() - + def execute(self, context): curve = Curves.Curve(context.active_object) nrSplines = len(curve.splines) nrSegments = 0 - + print("") - print("OperatorSegmentsInfo:", "nrSplines:", nrSplines) - + print("OperatorSegmentsInfo:", "nrSplines:", nrSplines) + nrEmptySplines = 0 for iSpline, spline in enumerate(curve.splines): nrSegmentsSpline = spline.nrSegments - print("--", "spline %d of %d: nrSegments: %d" % (iSpline + 1, nrSplines, nrSegmentsSpline)) - - if nrSegmentsSpline < 1: + print("--", "spline %d of %d: nrSegments: %d" % (iSpline + 1, nrSplines, nrSegmentsSpline)) + + if nrSegmentsSpline < 1: nrEmptySplines += 1 print("--", "--", "## WARNING: spline has no segments and will therefor be ignored in any further calculations") continue - + for iSegment, segment in enumerate(spline.segments): - print("--", "--", "segment %d of %d coefficients:" % (iSegment + 1, nrSegmentsSpline)) + print("--", "--", "segment %d of %d coefficients:" % (iSegment + 1, nrSegmentsSpline)) print("--", "--", "--", "C0: %.6f, %.6f, %.6f" % (segment.coeff0.x, segment.coeff0.y, segment.coeff0.z)) - + nrSegments += nrSegmentsSpline - + self.report({'INFO'}, "nrSplines: %d; nrSegments: %d; nrEmptySplines: %d" % (nrSplines, nrSegments, nrEmptySplines)) - + return {'FINISHED'} @@ -176,31 +176,31 @@ class OperatorOriginToSpline0Start(bpy.types.Operator): bl_idname = "curvetools2.operatororigintospline0start" bl_label = "OriginToSpline0Start" bl_description = "Sets the origin of the active/selected curve to the starting point of the (first) spline. Nice for curve modifiers." - - + + @classmethod def poll(cls, context): return Util.Selected1Curve() - + def execute(self, context): blCurve = context.active_object blSpline = blCurve.data.splines[0] newOrigin = blCurve.matrix_world * blSpline.bezier_points[0].co - + origOrigin = bpy.context.scene.cursor_location.copy() print("--", "origOrigin: %.6f, %.6f, %.6f" % (origOrigin.x, origOrigin.y, origOrigin.z)) print("--", "newOrigin: %.6f, %.6f, %.6f" % (newOrigin.x, newOrigin.y, newOrigin.z)) - + bpy.context.scene.cursor_location = newOrigin bpy.ops.object.origin_set(type='ORIGIN_CURSOR') bpy.context.scene.cursor_location = origOrigin - + self.report({'INFO'}, "TODO: OperatorOriginToSpline0Start") - + return {'FINISHED'} - + # 2 CURVES SELECTED # ################# @@ -208,35 +208,35 @@ class OperatorIntersectCurves(bpy.types.Operator): bl_idname = "curvetools2.operatorintersectcurves" bl_label = "Intersect" bl_description = "Intersects selected curves" - - + + @classmethod def poll(cls, context): return Util.Selected2Curves() - + def execute(self, context): print("### TODO: OperatorIntersectCurves.execute()") - + algo = context.scene.curvetools.IntersectCurvesAlgorithm print("-- algo:", algo) - - + + mode = context.scene.curvetools.IntersectCurvesMode print("-- mode:", mode) # if mode == 'Split': # self.report({'WARNING'}, "'Split' mode is not implemented yet -- <<STOPPING>>") # return {'CANCELLED'} - + affect = context.scene.curvetools.IntersectCurvesAffect print("-- affect:", affect) - - + + curveIntersector = CurveIntersections.CurvesIntersector.FromSelection() rvIntersectionNrs = curveIntersector.CalcAndApplyIntersections() - + self.report({'INFO'}, "Active curve points: %d; other curve points: %d" % (rvIntersectionNrs[0], rvIntersectionNrs[1])) - + return {'FINISHED'} @@ -245,21 +245,21 @@ class OperatorLoftCurves(bpy.types.Operator): bl_idname = "curvetools2.operatorloftcurves" bl_label = "Loft" bl_description = "Lofts selected curves" - - + + @classmethod def poll(cls, context): return Util.Selected2Curves() - + def execute(self, context): #print("### TODO: OperatorLoftCurves.execute()") - + loftedSurface = Surfaces.LoftedSurface.FromSelection() loftedSurface.AddToScene() - + self.report({'INFO'}, "OperatorLoftCurves.execute()") - + return {'FINISHED'} @@ -268,24 +268,24 @@ class OperatorSweepCurves(bpy.types.Operator): bl_idname = "curvetools2.operatorsweepcurves" bl_label = "Sweep" bl_description = "Sweeps the active curve along to other curve (rail)" - - + + @classmethod def poll(cls, context): return Util.Selected2Curves() - + def execute(self, context): #print("### TODO: OperatorSweepCurves.execute()") - + sweptSurface = Surfaces.SweptSurface.FromSelection() sweptSurface.AddToScene() - + self.report({'INFO'}, "OperatorSweepCurves.execute()") - + return {'FINISHED'} - + # 3 CURVES SELECTED # ################# @@ -293,77 +293,77 @@ class OperatorBirail(bpy.types.Operator): bl_idname = "curvetools2.operatorbirail" bl_label = "Birail" bl_description = "Generates a birailed surface from 3 selected curves -- in order: rail1, rail2 and profile" - - + + @classmethod def poll(cls, context): return Util.Selected3Curves() - - def execute(self, context): + + def execute(self, context): birailedSurface = Surfaces.BirailedSurface.FromSelection() birailedSurface.AddToScene() - + self.report({'INFO'}, "OperatorBirail.execute()") - + return {'FINISHED'} - + # 1 OR MORE CURVES SELECTED # ######################### class OperatorSplinesSetResolution(bpy.types.Operator): bl_idname = "curvetools2.operatorsplinessetresolution" bl_label = "SplinesSetResolution" bl_description = "Sets the resolution of all splines" - - + + @classmethod def poll(cls, context): return Util.Selected1OrMoreCurves() - + def execute(self, context): splRes = context.scene.curvetools.SplineResolution selCurves = Util.GetSelectedCurves() - + for blCurve in selCurves: for spline in blCurve.data.splines: spline.resolution_u = splRes - + return {'FINISHED'} - - - + + + class OperatorSplinesRemoveZeroSegment(bpy.types.Operator): bl_idname = "curvetools2.operatorsplinesremovezerosegment" bl_label = "SplinesRemoveZeroSegment" bl_description = "Removes splines with no segments -- they seem to creep up, sometimes.." - - + + @classmethod def poll(cls, context): return Util.Selected1OrMoreCurves() - + def execute(self, context): selCurves = Util.GetSelectedCurves() - + for blCurve in selCurves: curve = Curves.Curve(blCurve) nrSplines = curve.nrSplines - + splinesToRemove = [] for spline in curve.splines: if len(spline.segments) < 1: splinesToRemove.append(spline) - nrRemovedSplines = len(splinesToRemove) - + nrRemovedSplines = len(splinesToRemove) + for spline in splinesToRemove: curve.splines.remove(spline) - + if nrRemovedSplines > 0: curve.RebuildInScene() - + self.report({'INFO'}, "Removed %d of %d splines" % (nrRemovedSplines, nrSplines)) - + return {'FINISHED'} @@ -372,26 +372,26 @@ class OperatorSplinesRemoveShort(bpy.types.Operator): bl_idname = "curvetools2.operatorsplinesremoveshort" bl_label = "SplinesRemoveShort" bl_description = "Removes splines with a length smaller than the threshold" - - + + @classmethod def poll(cls, context): return Util.Selected1OrMoreCurves() - + def execute(self, context): threshold = context.scene.curvetools.SplineRemoveLength selCurves = Util.GetSelectedCurves() - + for blCurve in selCurves: curve = Curves.Curve(blCurve) nrSplines = curve.nrSplines - + nrRemovedSplines = curve.RemoveShortSplines(threshold) if nrRemovedSplines > 0: curve.RebuildInScene() - + self.report({'INFO'}, "Removed %d of %d splines" % (nrRemovedSplines, nrSplines)) - + return {'FINISHED'} @@ -400,27 +400,27 @@ class OperatorSplinesJoinNeighbouring(bpy.types.Operator): bl_idname = "curvetools2.operatorsplinesjoinneighbouring" bl_label = "SplinesJoinNeighbouring" bl_description = "Joins neighbouring splines within a distance smaller than the threshold" - - + + @classmethod def poll(cls, context): return Util.Selected1OrMoreCurves() - + def execute(self, context): selCurves = Util.GetSelectedCurves() - + for blCurve in selCurves: curve = Curves.Curve(blCurve) nrSplines = curve.nrSplines - + threshold = context.scene.curvetools.SplineJoinDistance startEnd = context.scene.curvetools.SplineJoinStartEnd mode = context.scene.curvetools.SplineJoinMode - + nrJoins = curve.JoinNeighbouringSplines(startEnd, threshold, mode) if nrJoins > 0: curve.RebuildInScene() - + self.report({'INFO'}, "Applied %d joins on %d splines; resulting nrSplines: %d" % (nrJoins, nrSplines, curve.nrSplines)) - + return {'FINISHED'} diff --git a/curve_tools/Properties.py b/curve_tools/Properties.py index 94811846d4adc710cc7846e8067c3fd250d2c7fa..84c469f30f6d7cdb0e142063c22d757db5ef578e 100644 --- a/curve_tools/Properties.py +++ b/curve_tools/Properties.py @@ -8,20 +8,20 @@ from bpy.props import * class CurveTools2SelectedObjectHeader(bpy.types.Header): bl_label = "Selection" bl_space_type = "VIEW_3D" - + def __init__(self): self.update() - + def update(self): blenderSelectedObjects = bpy.context.selected_objects selectedObjects = bpy.context.scene.curvetools.SelectedObjects - + selectedObjectsToRemove = [] for selectedObject in selectedObjects: if not selectedObject.IsElementOf(blenderSelectedObjects): selectedObjectsToRemove.append(selectedObject) for selectedObject in selectedObjectsToRemove: selectedObjects.remove(selectedObject) - + blenderObjectsToAdd = [] for blenderObject in blenderSelectedObjects: if not CurveTools2SelectedObject.ListContains(selectedObjects, blenderObject): blenderObjectsToAdd.append(blenderObject) @@ -29,11 +29,11 @@ class CurveTools2SelectedObjectHeader(bpy.types.Header): newSelectedObject = CurveTools2SelectedObject(blenderObject) selectedObjects.append(newSelectedObject) - + def draw(self, context): selectedObjects = bpy.context.scene.curvetools.SelectedObjects nrSelectedObjects = len(selectedObjects) - + layout = self.layout row = layout.row() row.label("Sel:", nrSelectedObjects) @@ -42,24 +42,24 @@ class CurveTools2SelectedObjectHeader(bpy.types.Header): class CurveTools2SelectedObject(bpy.types.PropertyGroup): name = StringProperty(name = "name", default = "??") - + @staticmethod def UpdateThreadTarget(lock, sleepTime, selectedObjectNames, selectedBlenderObjectNames): time.sleep(sleepTime) - + newSelectedObjectNames = [] - + for name in selectedObjectNames: if name in selectedBlenderObjectNames: newSelectedObjectNames.append(name) - + for name in selectedBlenderObjectNames: if not (name in selectedObjectNames): newSelectedObjectNames.append(name) - + # sometimes it still complains about the context try: nrNewSelectedObjects = len(newSelectedObjectNames) bpy.context.scene.curvetools.NrSelectedObjects = nrNewSelectedObjects - + selectedObjects = bpy.context.scene.curvetools.SelectedObjects selectedObjects.clear() for i in range(nrNewSelectedObjects): selectedObjects.add() @@ -67,24 +67,23 @@ class CurveTools2SelectedObject(bpy.types.PropertyGroup): selectedObjects[i].name = newSelectedObjectName except: pass - + @staticmethod def GetSelectedObjectNames(): selectedObjects = bpy.context.scene.curvetools.SelectedObjects - + rvNames = [] selectedObjectValues = selectedObjects.values() for selectedObject in selectedObjectValues: rvNames.append(selectedObject.name) - + return rvNames - - + + @staticmethod def GetSelectedBlenderObjectNames(): blenderSelectedObjects = bpy.context.selected_objects - + rvNames = [] for blObject in blenderSelectedObjects: rvNames.append(blObject.name) - + return rvNames - diff --git a/curve_tools/Surfaces.py b/curve_tools/Surfaces.py index 7e31a6efdb380743a3b77718e4dfbb8e4309d80f..cfbf59c44e787ae2abe25e708a7e404c595b4588 100644 --- a/curve_tools/Surfaces.py +++ b/curve_tools/Surfaces.py @@ -10,115 +10,115 @@ class LoftedSplineSurface: def __init__(self, activeSpline, otherSpline, bMesh, vert0Index, resolution): self.splineA = activeSpline self.splineO = otherSpline - + self.bMesh = bMesh self.vert0Index = vert0Index self.resolution = resolution - + def Apply(self, worldMatrixA, worldMatrixO): #deltaPar = 1.0 / float(self.resolution - 1) - + par = 0.0 pointA = worldMatrixA * self.splineA.CalcPoint(par) pointO = worldMatrixO * self.splineO.CalcPoint(par) self.bMesh.verts[self.vert0Index].co = pointA self.bMesh.verts[self.vert0Index + 1].co = pointO - + fltResm1 = float(self.resolution - 1) for i in range(1, self.resolution): par = float(i) / fltResm1 - + pointA = worldMatrixA * self.splineA.CalcPoint(par) pointO = worldMatrixO * self.splineO.CalcPoint(par) self.bMesh.verts[self.vert0Index + 2 * i].co = pointA self.bMesh.verts[self.vert0Index + 2 * i + 1].co = pointO - + def AddFaces(self): currIndexA = self.vert0Index currIndexO = self.vert0Index + 1 - + bmVerts = self.bMesh.verts bmVerts.ensure_lookup_table() for i in range(1, self.resolution): nextIndexA = self.vert0Index + 2 * i nextIndexO = nextIndexA + 1 - + self.bMesh.faces.new([bmVerts[currIndexA], bmVerts[currIndexO], bmVerts[nextIndexO], bmVerts[nextIndexA]]) - + currIndexA = nextIndexA currIndexO = nextIndexO - + class LoftedSurface: @staticmethod def FromSelection(): selObjects = bpy.context.selected_objects if len(selObjects) != 2: raise Exception("len(selObjects) != 2") # shouldn't be possible - + blenderActiveCurve = bpy.context.active_object blenderOtherCurve = selObjects[0] if blenderActiveCurve == blenderOtherCurve: blenderOtherCurve = selObjects[1] - + aCurve = Curves.Curve(blenderActiveCurve) oCurve = Curves.Curve(blenderOtherCurve) - + name = "TODO: autoname" - + return LoftedSurface(aCurve, oCurve, name) - + def __init__(self, activeCurve, otherCurve, name = "LoftedSurface"): self.curveA = activeCurve self.curveO = otherCurve self.name = name - + self.nrSplines = self.curveA.nrSplines if self.curveO.nrSplines < self.nrSplines: self.nrSplines = self.curveO.nrSplines - + self.bMesh = bmesh.new() - + self.splineSurfaces = self.SetupSplineSurfaces() - + self.Apply() - - + + def SetupSplineSurfaces(self): rvSplineSurfaces = [] - + currV0Index = 0 for i in range(self.nrSplines): splineA = self.curveA.splines[i] splineO = self.curveO.splines[i] - + res = splineA.resolution if splineO.resolution < res: res = splineO.resolution - + for iv in range(2 * res): self.bMesh.verts.new() - + splSurf = LoftedSplineSurface(splineA, splineO, self.bMesh, currV0Index, res) splSurf.AddFaces() rvSplineSurfaces.append(splSurf) - + currV0Index += 2 * res - + return rvSplineSurfaces - - + + def Apply(self): for splineSurface in self.splineSurfaces: splineSurface.Apply(self.curveA.worldMatrix, self.curveO.worldMatrix) - - + + def AddToScene(self): mesh = bpy.data.meshes.new("Mesh" + self.name) - + self.bMesh.to_mesh(mesh) mesh.update() - + meshObject = bpy.data.objects.new(self.name, mesh) - + bpy.context.scene.objects.link(meshObject) @@ -128,13 +128,13 @@ class SweptSplineSurface: def __init__(self, activeSpline, otherSpline, bMesh, vert0Index, resolutionA, resolutionO): self.splineA = activeSpline self.splineO = otherSpline - + self.bMesh = bMesh self.vert0Index = vert0Index self.resolutionA = resolutionA self.resolutionO = resolutionO - + def Apply(self, worldMatrixA, worldMatrixO): localPointsA = [] fltResAm1 = float(self.resolutionA - 1) @@ -143,132 +143,132 @@ class SweptSplineSurface: pointA = self.splineA.CalcPoint(par) localPointsA.append(pointA) - + worldPointsO = [] localDerivativesO = [] fltResOm1 = float(self.resolutionO - 1) for i in range(self.resolutionO): par = float(i) / fltResOm1 - + pointO = self.splineO.CalcPoint(par) worldPointsO.append(worldMatrixO * pointO) - + derivativeO = self.splineO.CalcDerivative(par) localDerivativesO.append(derivativeO) - - + + currWorldMatrixA = worldMatrixA worldMatrixOInv = worldMatrixO.inverted() prevDerivativeO = localDerivativesO[0] for iO in range(self.resolutionO): currDerivativeO = localDerivativesO[iO] localRotMatO = Math.CalcRotationMatrix(prevDerivativeO, currDerivativeO) - - currLocalAToLocalO = worldMatrixOInv * currWorldMatrixA + + currLocalAToLocalO = worldMatrixOInv * currWorldMatrixA worldPointsA = [] for iA in range(self.resolutionA): pointALocalToO = currLocalAToLocalO * localPointsA[iA] rotatedPointA = localRotMatO * pointALocalToO worldPointsA.append(worldMatrixO * rotatedPointA) - + worldOffsetsA = [] worldPoint0A = worldPointsA[0] for i in range(self.resolutionA): worldOffsetsA.append(worldPointsA[i] - worldPoint0A) - - + + for iA in range(self.resolutionA): iVert = self.vert0Index + (self.resolutionA * iO) + iA currVert = worldPointsO[iO] + worldOffsetsA[iA] self.bMesh.verts[iVert].co = currVert - + prevDerivativeO = currDerivativeO currWorldMatrixA = worldMatrixO * localRotMatO * currLocalAToLocalO - + def AddFaces(self): bmVerts = self.bMesh.verts bmVerts.ensure_lookup_table() - + for iO in range(self.resolutionO - 1): for iA in range(self.resolutionA - 1): currIndexA1 = self.vert0Index + (self.resolutionA * iO) + iA currIndexA2 = currIndexA1 + 1 nextIndexA1 = self.vert0Index + (self.resolutionA * (iO + 1)) + iA nextIndexA2 = nextIndexA1 + 1 - + self.bMesh.faces.new([bmVerts[currIndexA1], bmVerts[currIndexA2], bmVerts[nextIndexA2], bmVerts[nextIndexA1]]) - - + + class SweptSurface: @staticmethod def FromSelection(): selObjects = bpy.context.selected_objects if len(selObjects) != 2: raise Exception("len(selObjects) != 2") # shouldn't be possible - + blenderActiveCurve = bpy.context.active_object blenderOtherCurve = selObjects[0] if blenderActiveCurve == blenderOtherCurve: blenderOtherCurve = selObjects[1] - + aCurve = Curves.Curve(blenderActiveCurve) oCurve = Curves.Curve(blenderOtherCurve) - + name = "TODO: autoname" - + return SweptSurface(aCurve, oCurve, name) - + def __init__(self, activeCurve, otherCurve, name = "SweptSurface"): self.curveA = activeCurve self.curveO = otherCurve self.name = name - + self.nrSplines = self.curveA.nrSplines if self.curveO.nrSplines < self.nrSplines: self.nrSplines = self.curveO.nrSplines - + self.bMesh = bmesh.new() - + self.splineSurfaces = self.SetupSplineSurfaces() - + self.Apply() - - + + def SetupSplineSurfaces(self): rvSplineSurfaces = [] - + currV0Index = 0 for i in range(self.nrSplines): splineA = self.curveA.splines[i] splineO = self.curveO.splines[i] - + resA = splineA.resolution resO = splineO.resolution - + for iv in range(resA * resO): self.bMesh.verts.new() - + splSurf = SweptSplineSurface(splineA, splineO, self.bMesh, currV0Index, resA, resO) splSurf.AddFaces() rvSplineSurfaces.append(splSurf) - + currV0Index += resA * resO - + return rvSplineSurfaces - - + + def Apply(self): for splineSurface in self.splineSurfaces: splineSurface.Apply(self.curveA.worldMatrix, self.curveO.worldMatrix) - - + + def AddToScene(self): mesh = bpy.data.meshes.new("Mesh" + self.name) - + self.bMesh.to_mesh(mesh) mesh.update() - + meshObject = bpy.data.objects.new(self.name, mesh) - + bpy.context.scene.objects.link(meshObject) - + # profileSpline is swept over rail1Spline and scaled/rotated to have its endpoint on rail2Spline @@ -277,13 +277,13 @@ class BirailedSplineSurface: self.rail1Spline = rail1Spline self.rail2Spline = rail2Spline self.profileSpline = profileSpline - + self.bMesh = bMesh self.vert0Index = vert0Index self.resolutionRails = resolutionRails self.resolutionProfile = resolutionProfile - + def Apply(self, worldMatrixRail1, worldMatrixRail2, worldMatrixProfile): localPointsProfile = [] fltResProfilem1 = float(self.resolutionProfile - 1) @@ -292,86 +292,86 @@ class BirailedSplineSurface: pointProfile = self.profileSpline.CalcPoint(par) localPointsProfile.append(pointProfile) - + worldPointsRail1 = [] localDerivativesRail1 = [] worldPointsRail2 = [] fltResRailsm1 = float(self.resolutionRails - 1) for i in range(self.resolutionRails): par = float(i) / fltResRailsm1 - + pointRail1 = self.rail1Spline.CalcPoint(par) worldPointsRail1.append(worldMatrixRail1 * pointRail1) - + derivativeRail1 = self.rail1Spline.CalcDerivative(par) localDerivativesRail1.append(derivativeRail1) - + pointRail2 = self.rail2Spline.CalcPoint(par) worldPointsRail2.append(worldMatrixRail2 * pointRail2) - - + + currWorldMatrixProfile = worldMatrixProfile worldMatrixRail1Inv = worldMatrixRail1.inverted() prevDerivativeRail1 = localDerivativesRail1[0] for iRail in range(self.resolutionRails): currDerivativeRail1 = localDerivativesRail1[iRail] localRotMatRail1 = Math.CalcRotationMatrix(prevDerivativeRail1, currDerivativeRail1) - - currLocalProfileToLocalRail1 = worldMatrixRail1Inv * currWorldMatrixProfile + + currLocalProfileToLocalRail1 = worldMatrixRail1Inv * currWorldMatrixProfile worldPointsProfileRail1 = [] for iProfile in range(self.resolutionProfile): pointProfileLocalToRail1 = currLocalProfileToLocalRail1 * localPointsProfile[iProfile] rotatedPointProfile = localRotMatRail1 * pointProfileLocalToRail1 worldPointsProfileRail1.append(worldMatrixRail1 * rotatedPointProfile) - + worldOffsetsProfileRail1 = [] worldPoint0ProfileRail1 = worldPointsProfileRail1[0] for iProfile in range(self.resolutionProfile): worldOffsetsProfileRail1.append(worldPointsProfileRail1[iProfile] - worldPoint0ProfileRail1) - + worldStartPointProfileRail1 = worldPointsRail1[iRail] worldEndPointProfileRail1 = worldStartPointProfileRail1 + worldOffsetsProfileRail1[-1] v3From = worldEndPointProfileRail1 - worldStartPointProfileRail1 v3To = worldPointsRail2[iRail] - worldStartPointProfileRail1 scaleFactorRail2 = v3To.magnitude / v3From.magnitude rotMatRail2 = Math.CalcRotationMatrix(v3From, v3To) - + worldOffsetsProfileRail2 = [] for iProfile in range(self.resolutionProfile): offsetProfileRail1 = worldOffsetsProfileRail1[iProfile] worldOffsetsProfileRail2.append(rotMatRail2 * (offsetProfileRail1 * scaleFactorRail2)) - - + + for iProfile in range(self.resolutionProfile): iVert = self.vert0Index + (self.resolutionProfile * iRail) + iProfile currVert = worldPointsRail1[iRail] + worldOffsetsProfileRail2[iProfile] self.bMesh.verts[iVert].co = currVert - + prevDerivativeRail1 = currDerivativeRail1 currWorldMatrixProfile = worldMatrixRail1 * localRotMatRail1 * currLocalProfileToLocalRail1 - + def AddFaces(self): bmVerts = self.bMesh.verts bmVerts.ensure_lookup_table() - + for iRail in range(self.resolutionRails - 1): for iProfile in range(self.resolutionProfile - 1): currIndex1 = self.vert0Index + (self.resolutionProfile * iRail) + iProfile currIndex2 = currIndex1 + 1 nextIndex1 = self.vert0Index + (self.resolutionProfile * (iRail + 1)) + iProfile nextIndex2 = nextIndex1 + 1 - + self.bMesh.faces.new([bmVerts[currIndex1], bmVerts[currIndex2], bmVerts[nextIndex2], bmVerts[nextIndex1]]) - - + + class BirailedSurface: @staticmethod def FromSelection(): nrSelectedObjects = bpy.context.scene.curvetools.NrSelectedObjects if nrSelectedObjects != 3: raise Exception("nrSelectedObjects != 3") # shouldn't be possible - - + + selectedObjects = bpy.context.scene.curvetools.SelectedObjects selectedObjectValues = selectedObjects.values() @@ -392,70 +392,68 @@ class BirailedSurface: try: profileBlenderCurve = bpy.data.objects[curveName] except: profileBlenderCurve = None if profileBlenderCurve is None: raise Exception("profileBlenderCurve is None") - - + + rail1Curve = Curves.Curve(rail1BlenderCurve) rail2Curve = Curves.Curve(rail2BlenderCurve) profileCurve = Curves.Curve(profileBlenderCurve) - + name = "TODO: autoname" - + return BirailedSurface(rail1Curve, rail2Curve, profileCurve, name) - + def __init__(self, rail1Curve, rail2Curve, profileCurve, name = "BirailedSurface"): self.rail1Curve = rail1Curve self.rail2Curve = rail2Curve self.profileCurve = profileCurve self.name = name - + self.nrSplines = self.rail1Curve.nrSplines if self.rail2Curve.nrSplines < self.nrSplines: self.nrSplines = self.rail2Curve.nrSplines if self.profileCurve.nrSplines < self.nrSplines: self.nrSplines = self.profileCurve.nrSplines - + self.bMesh = bmesh.new() - + self.splineSurfaces = self.SetupSplineSurfaces() - + self.Apply() - - + + def SetupSplineSurfaces(self): rvSplineSurfaces = [] - + currV0Index = 0 for i in range(self.nrSplines): splineRail1 = self.rail1Curve.splines[i] splineRail2 = self.rail2Curve.splines[i] splineProfile = self.profileCurve.splines[i] - + resProfile = splineProfile.resolution resRails = splineRail1.resolution if splineRail2.resolution < resRails: resRails = splineRail2.resolution - + for iv in range(resProfile * resRails): self.bMesh.verts.new() - + splSurf = BirailedSplineSurface(splineRail1, splineRail2, splineProfile, self.bMesh, currV0Index, resRails, resProfile) splSurf.AddFaces() rvSplineSurfaces.append(splSurf) - + currV0Index += resProfile * resRails - + return rvSplineSurfaces - - + + def Apply(self): for splineSurface in self.splineSurfaces: splineSurface.Apply(self.rail1Curve.worldMatrix, self.rail2Curve.worldMatrix, self.profileCurve.worldMatrix) - - + + def AddToScene(self): mesh = bpy.data.meshes.new("Mesh" + self.name) - + self.bMesh.to_mesh(mesh) mesh.update() - + meshObject = bpy.data.objects.new(self.name, mesh) - - bpy.context.scene.objects.link(meshObject) - + bpy.context.scene.objects.link(meshObject) diff --git a/curve_tools/Util.py b/curve_tools/Util.py index 731460c429f99a20decf7c73d2b296263437075d..6ebd20b75f7dfa7e1d0cd827ed2b78f3e484106b 100644 --- a/curve_tools/Util.py +++ b/curve_tools/Util.py @@ -4,118 +4,116 @@ from mathutils import * def GetSelectedCurves(): rvList = [] - + for obj in bpy.context.selected_objects: if obj.type == "CURVE": rvList.append(obj) - + return rvList def Selected1Curve(): if len(GetSelectedCurves()) == 1: return (bpy.context.active_object.type == "CURVE") - + return False def Selected1SingleSplineCurve(): if Selected1Curve(): return (len(bpy.context.active_object.data.splines) == 1) - + return False def Selected2Curves(): if len(GetSelectedCurves()) == 2: return (bpy.context.active_object.type == "CURVE") - + return False def Selected3Curves(): if len(GetSelectedCurves()) == 3: return (bpy.context.active_object.type == "CURVE") - + return False def Selected1OrMoreCurves(): if len(GetSelectedCurves()) > 0: return (bpy.context.active_object.type == "CURVE") - + return False - + def GetToolsRegion(): for area in bpy.context.screen.areas: if area.type == 'VIEW_3D': for region in area.regions: if region.type == 'TOOLS': return region - + return None - + def GetFirstRegionView3D(): for area in bpy.context.screen.areas: if area.type == 'VIEW_3D': return area.spaces[0].region_3d - + return None - - + + def LogFirstRegionView3D(): print("LogFirstRegionView3D()") regionView3D = GetFirstRegionView3D() if regionView3D is None: print("--", "ERROR:", "regionView3D is None") return - + print("--", "view_matrix:") print("--", "--", regionView3D.view_matrix) print("--", "view_location:") print("--", "--", regionView3D.view_location) - - + + class Intersection: # listIP: list of BezierSplineIntersectionPoint # return: list of splines @staticmethod def GetBezierSplines(listIP): rvList = [] - + for ip in listIP: if not (ip.spline in rvList): rvList.append(ip.spline) - + return rvList - + # listIP: list of BezierSplineIntersectionPoint # return: list of segments @staticmethod def GetBezierSegments(listIP, spline): rvList = [] - + for ip in listIP: if not ip.spline is spline: continue - + segIP = ip.bezierSegmentIntersectionPoint if not (segIP.segment in rvList): rvList.append(segIP.segment) - + return rvList - + # listIP: list of BezierSplineIntersectionPoint # return: list of floats (not necessarily ordered) @staticmethod def GetBezierSegmentParameters(listIP, segment): rvList = [] - + for ip in listIP: segIP = ip.bezierSegmentIntersectionPoint if not segIP.segment is segment: continue - + rvList.append(segIP.parameter) - - return rvList - \ No newline at end of file + return rvList diff --git a/curve_tools/auto_loft.py b/curve_tools/auto_loft.py index 5b1808e0e997c106e48504ef1d01d249442400e1..70ecc4c83de91218a8873e4de71721e9ca420df5 100644 --- a/curve_tools/auto_loft.py +++ b/curve_tools/auto_loft.py @@ -10,28 +10,28 @@ class OperatorAutoLoftCurves(Operator): bl_idname = "curvetools2.create_auto_loft" bl_label = "Loft" bl_description = "Lofts selected curves" - - + + @classmethod def poll(cls, context): return Util.Selected2Curves() - + def execute(self, context): #print("### TODO: OperatorLoftCurves.execute()") scene = context.scene mesh = bpy.data.meshes.new("LoftMesh") - + curve0 = context.selected_objects[0] - curve1 = context.selected_objects[1] + curve1 = context.selected_objects[1] - ls = LoftedSurface(Curve(curve0), Curve(curve1), "AutoLoft") + ls = LoftedSurface(Curve(curve0), Curve(curve1), "AutoLoft") + + ls.bMesh.to_mesh(mesh) - ls.bMesh.to_mesh(mesh) - loftobj = bpy.data.objects.new(self.name, mesh) - - scene.objects.link(loftobj) + + scene.objects.link(loftobj) loftobj["autoloft"] = True if loftobj.get('_RNA_UI') is None: loftobj['_RNA_UI'] = {} @@ -42,10 +42,10 @@ class OperatorAutoLoftCurves(Operator): "curve1": curve1.name} print(loftobj['_RNA_UI'].to_dict()) self.report({'INFO'}, "OperatorAutoLoftCurves.execute()") - + return {'FINISHED'} - + class AutoLoftModalOperator(Operator): """Auto Loft""" bl_idname = "wm.auto_loft_curve" @@ -57,14 +57,14 @@ class AutoLoftModalOperator(Operator): def poll(cls, context): # two curves selected. return True - + def modal(self, context, event): scene = context.scene wm = context.window_manager if event.type in {'ESC'}: wm.auto_loft = False - - if not wm.auto_loft: + + if not wm.auto_loft: self.cancel(context) return {'CANCELLED'} @@ -81,13 +81,13 @@ class AutoLoftModalOperator(Operator): if curve0 and curve1: ls = LoftedSurface(Curve(curve0), Curve(curve1), loftmesh.name) ls.bMesh.to_mesh(loftmesh.data) - + return {'PASS_THROUGH'} def execute(self, context): wm = context.window_manager self._timer = wm.event_timer_add(0.1, context.window) - wm.modal_handler_add(self) + wm.modal_handler_add(self) return {'RUNNING_MODAL'} def cancel(self, context): @@ -108,14 +108,14 @@ def register(): name="Auto Loft", update=run_auto_loft) bpy.context.window_manager.auto_loft = False - + def unregister(): bpy.utils.unregister_class(AutoLoftModalOperator) bpy.utils.unregister_class(OperatorAutoLoftCurves) if __name__ == "__main__": register() - - + + # test call #bpy.ops.wm.modal_timer_operator() diff --git a/curve_tools/curve_outline.py b/curve_tools/curve_outline.py index 8dcf60fa0a14b50f71b23aefafea687ca854cd6d..6be15ff0f39db3b3ab7b57355e5f95f508944817 100644 --- a/curve_tools/curve_outline.py +++ b/curve_tools/curve_outline.py @@ -1,22 +1,22 @@ ''' by Yann Bertrand, january 2014. - + BEGIN GPL LICENSE BLOCK - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - + END GPL LICENCE BLOCK ''' @@ -39,44 +39,44 @@ def createOutline(curve, outline): for spline in curve.data.splines[:]: p = spline.bezier_points out = [] - + n = ((p[0].handle_right-p[0].co).normalized()-(p[0].handle_left-p[0].co).normalized()).normalized() n = Vector((-n[1], n[0], n[2])) o = p[0].co+outline*n out.append(o) - + for i in range(1,len(p)): n = ((p[i].handle_right-p[i].co).normalized()-(p[i].handle_left-p[i].co).normalized()).normalized() n = Vector((-n[1], n[0], n[2])) o = intersect_line_line(out[-1], (out[-1]+p[i].co-p[i-1].co), p[i].co, p[i].co+n)[0] out.append(o) - + curve.data.splines.new('BEZIER') if spline.use_cyclic_u: curve.data.splines[-1].use_cyclic_u = True p_out = curve.data.splines[-1].bezier_points p_out.add(len(out)-1) - + for i in range(len(out)): - p_out[i].handle_left_type = 'FREE' + p_out[i].handle_left_type = 'FREE' p_out[i].handle_right_type = 'FREE' - + p_out[i].co = out[i] - + if i<len(out)-1: l = (p[i+1].co-p[i].co).length l2 = (out[i]-out[i+1]).length - + if i==0: p_out[i].handle_left = out[i] + ((p[i].handle_left-p[i].co)*l2/l) if i<len(out)-1: p_out[i+1].handle_left = out[i+1] + ((p[i+1].handle_left-p[i+1].co)*l2/l) p_out[i].handle_right = out[i] + ((p[i].handle_right-p[i].co)*l2/l) - + for i in range(len(p)): p_out[i].handle_left_type = p[i].handle_left_type p_out[i].handle_right_type = p[i].handle_right_type - + return @@ -86,7 +86,7 @@ class CurveOutline(bpy.types.Operator): bl_label = "Create Outline" bl_options = {'REGISTER', 'UNDO'} outline = bpy.props.FloatProperty(name="Amount", default=0.1, min=-10, max=10) - + @classmethod def poll(cls, context): return (context.object is not None and @@ -98,10 +98,10 @@ class CurveOutline(bpy.types.Operator): def invoke(self, context, event): return context.window_manager.invoke_props_popup(self, event) - + def menu_func(self, context): self.layout.operator(CurveOutline.bl_idname) - + def register(): bpy.utils.register_class(CurveOutline) diff --git a/data_overrides/__init__.py b/data_overrides/__init__.py index 08f6bb13110381934ebee98651f43a9b5601500f..2998bcf7d8ed0fce79eadee8cee231dc2d2236a9 100644 --- a/data_overrides/__init__.py +++ b/data_overrides/__init__.py @@ -33,7 +33,7 @@ bl_info = { import bpy from data_overrides import override, ui - + def register(): override.register() ui.register() diff --git a/data_overrides/override.py b/data_overrides/override.py index 11585763fa9f5cf974afa55b6e1fb401efb1d687..a15e9c6b5a7904ab21263b0298bdc91e627c062a 100644 --- a/data_overrides/override.py +++ b/data_overrides/override.py @@ -81,7 +81,7 @@ class Override(PropertyGroup): row = layout.row(align=True) row.label(prop.name, icon='DOT') row.prop(prop, '["{}"]'.format(escape_identifier("value")), text="") - + row = layout.row() row.operator_context = 'INVOKE_SCREEN' row.context_pointer_set("id_data_override", self) diff --git a/data_overrides/ui.py b/data_overrides/ui.py index 81ca1be8f33a495572c75929d5e5933e3d6451a4..e518cfe2b0a5666d28f90bf86f239d9e38b33d95 100644 --- a/data_overrides/ui.py +++ b/data_overrides/ui.py @@ -99,7 +99,7 @@ class SCENE_OT_Override_Add(Operator): id_data = id_data_from_enum(self.id_block) add_override(scene, id_data) - + return {'FINISHED'} diff --git a/data_overrides/util.py b/data_overrides/util.py index 4c2cec0de39bc9b747679579cfdeef8c29b70cf9..a22cddbdb0c9faa1c142fc54b1c1603fd6be6005 100644 --- a/data_overrides/util.py +++ b/data_overrides/util.py @@ -84,14 +84,14 @@ class OperatorCallContext(): # store active/selected state to restore it after operator execution self.curact = scene.objects.active self.cursel = { ob : ob.select for ob in scene.objects } - + # undo can store files a lot when running operators internally, # disable since we only need one undo step after main operators anyway self.use_global_undo = prefs.edit.use_global_undo prefs.edit.use_global_undo = False return (self.curact, self.cursel) - + def __exit__(self, exc_type, exc_value, traceback): scene = bpy.context.scene prefs = bpy.context.user_preferences @@ -105,7 +105,7 @@ class OperatorCallContext(): def select_single_object(ob): scene = bpy.context.scene - + scene.objects.active = ob for tob in scene.objects: tob.select = (tob == ob) diff --git a/io_atomblend_utilities/io_atomblend_utilities.py b/io_atomblend_utilities/io_atomblend_utilities.py index da88cf41074e0d8f18cf6a07b06daf259424ec16..ef77962fe9c88b804a085e1a4c1d3bd28d34002c 100644 --- a/io_atomblend_utilities/io_atomblend_utilities.py +++ b/io_atomblend_utilities/io_atomblend_utilities.py @@ -149,7 +149,7 @@ ELEMENTS_DEFAULT = ( # The list 'ELEMENTS' contains all data of the elements and will be used during # runtime. The list will be initialized with the fixed -# data from above via the class below (ElementProp). One fixed list (above), +# data from above via the class below (ElementProp). One fixed list (above), # which cannot be changed, and a list of classes with same data (ELEMENTS) exist. # The list 'ELEMENTS' can be modified by e.g. loading a separate custom # data file. @@ -181,10 +181,10 @@ def distance(): for v in bm.verts: if v.select: locations.append(atom.matrix_world * v.co) - + if len(locations) > 1: location1 = locations[0] - location2 = locations[1] + location2 = locations[1] else: return "N.A" # In the 'OBJECT' mode @@ -201,15 +201,15 @@ def distance(): pos = str.find(dist, ".") dist = dist[:pos+4] dist = dist + " A" - + return dist -def choose_objects(action_type, - who, - radius_all, - radius_pm, - radius_type, +def choose_objects(action_type, + who, + radius_all, + radius_pm, + radius_type, radius_type_ionic, sticks_all): @@ -220,23 +220,23 @@ def choose_objects(action_type, for i, layer in enumerate(bpy.context.scene.layers): if layer == True: layers.append(i) - + # Put all objects, which are in the layers, into a list. change_objects_all = [] for atom in bpy.context.scene.objects: for layer in layers: if atom.layers[layer] == True: - change_objects_all.append(atom) - # For selected objects of the visible layer + change_objects_all.append(atom) + # For selected objects of the visible layer elif who == "ALL_ACTIVE": change_objects_all = [] # Note all selected objects first. for atom in bpy.context.selected_objects: - change_objects_all.append(atom) - - # This is very important now: If there are dupliverts structures, note - # only the parents and NOT the children! Otherwise the double work is - # done or the system can even crash if objects are deleted. - The + change_objects_all.append(atom) + + # This is very important now: If there are dupliverts structures, note + # only the parents and NOT the children! Otherwise the double work is + # done or the system can even crash if objects are deleted. - The # chidlren are accessed anyways (see below). change_objects = [] for atom in change_objects_all: @@ -245,92 +245,92 @@ def choose_objects(action_type, for atom2 in change_objects: if atom2 == atom.parent: FLAG = True - if FLAG == False: + if FLAG == False: change_objects.append(atom) else: change_objects.append(atom) - + # And now, consider all objects, which are in the list 'change_objects'. for atom in change_objects: if len(atom.children) != 0: for atom_child in atom.children: - if atom_child.type in {'SURFACE', 'MESH', 'META'}: - modify_objects(action_type, + if atom_child.type in {'SURFACE', 'MESH', 'META'}: + modify_objects(action_type, atom_child, - radius_all, - radius_pm, + radius_all, + radius_pm, radius_type, radius_type_ionic, sticks_all) else: if atom.type in {'SURFACE', 'MESH', 'META'}: - modify_objects(action_type, - atom, - radius_all, - radius_pm, + modify_objects(action_type, + atom, + radius_all, + radius_pm, radius_type, radius_type_ionic, sticks_all) # Modifying the radius of a selected atom or stick -def modify_objects(action_type, - atom, - radius_all, - radius_pm, - radius_type, +def modify_objects(action_type, + atom, + radius_all, + radius_pm, + radius_type, radius_type_ionic, sticks_all): - # Modify atom radius (in pm) + # Modify atom radius (in pm) if action_type == "ATOM_RADIUS_PM" and "Stick" not in atom.name: if radius_pm[0] in atom.name: atom.scale = (radius_pm[1]/100,) * 3 - + # Modify atom radius (all selected) if action_type == "ATOM_RADIUS_ALL" and "Stick" not in atom.name: - atom.scale *= radius_all - - # Modify atom radius (type, van der Waals, atomic or ionic) + atom.scale *= radius_all + + # Modify atom radius (type, van der Waals, atomic or ionic) if action_type == "ATOM_RADIUS_TYPE" and "Stick" not in atom.name: - for element in ELEMENTS: + for element in ELEMENTS: if element.name in atom.name: # For ionic radii if radius_type == '3': charge_states = element.radii_ionic[::2] charge_radii = element.radii_ionic[1::2] charge_state_chosen = int(radius_type_ionic) - 4 - - find = (lambda searchList, elem: - [[i for i, x in enumerate(searchList) if x == e] + + find = (lambda searchList, elem: + [[i for i, x in enumerate(searchList) if x == e] for e in elem]) index = find(charge_states,[charge_state_chosen])[0] - # Is there a charge state? + # Is there a charge state? if index != []: atom.scale = (charge_radii[index[0]],) * 3 - + # For atomic and van der Waals radii. - else: + else: atom.scale = (element.radii[int(radius_type)],) * 3 - # Modify atom sticks - if action_type == "STICKS_RADIUS_ALL" and ('Sticks_Cups' in atom.name or + # Modify atom sticks + if action_type == "STICKS_RADIUS_ALL" and ('Sticks_Cups' in atom.name or 'Sticks_Cylinder' in atom.name or 'Stick_Cylinder' in atom.name): - + bpy.context.scene.objects.active = atom bpy.ops.object.mode_set(mode='EDIT', toggle=False) bm = bmesh.from_edit_mesh(atom.data) - + locations = [] for v in bm.verts: locations.append(v.co) center = Vector((0.0,0.0,0.0)) center = sum([location for location in locations], center)/len(locations) - - radius = sum([(loc[0]-center[0])**2+(loc[1]-center[1])**2 + + radius = sum([(loc[0]-center[0])**2+(loc[1]-center[1])**2 for loc in locations], 0) radius_new = radius * sticks_all @@ -345,51 +345,51 @@ def modify_objects(action_type, if action_type == "ATOM_REPLACE_OBJ" and "Stick" not in atom.name: scn = bpy.context.scene.atom_blend - - new_material = draw_obj_material(scn.replace_objs_material, + + new_material = draw_obj_material(scn.replace_objs_material, atom.active_material) - + # Special object (like halo, etc.) if scn.replace_objs_special != '0': new_atom = draw_obj_special(scn.replace_objs_special, atom) new_atom.parent = atom.parent - # Standard geomtrical objects + # Standard geomtrical objects else: # If the atom shape shall not be changed, then: if scn.replace_objs == '0': - atom.active_material = new_material + atom.active_material = new_material return {'FINISHED'} # If the atom shape shall change, then: else: new_atom = draw_obj(scn.replace_objs, atom) - new_atom.active_material = new_material + new_atom.active_material = new_material new_atom.parent = atom.parent - + if "_repl" not in atom.name: new_atom.name = atom.name + "_repl" else: - new_atom.name = atom.name - + new_atom.name = atom.name + # Delete the old object. bpy.ops.object.select_all(action='DESELECT') atom.select = True - bpy.ops.object.delete() - del(atom) + bpy.ops.object.delete() + del(atom) # Default shapes and colors for atoms if action_type == "ATOM_DEFAULT_OBJ" and "Stick" not in atom.name: - scn = bpy.context.scene.atom_blend + scn = bpy.context.scene.atom_blend # Create new material new_material = bpy.data.materials.new("tmp") - + # Create new object (NURBS sphere = '1b') new_atom = draw_obj('1b', atom) new_atom.active_material = new_material new_atom.parent = atom.parent - # Change size and color of the new object + # Change size and color of the new object for element in ELEMENTS: if element.name in atom.name: new_atom.scale = (element.radii[0],) * 3 @@ -406,22 +406,22 @@ def modify_objects(action_type, new_material.name = name+"_standard1" else: new_material.name = name+"_standard1" - + # Finally, delete the old object bpy.ops.object.select_all(action='DESELECT') atom.select = True - bpy.ops.object.delete() + bpy.ops.object.delete() # Separating atoms from a dupliverts strucutre. def separate_atoms(scn): atom = bpy.context.edit_object - + # Do nothing if it is not a dupliverts structure. if not atom.dupli_type == "VERTS": return {'FINISHED'} - + bm = bmesh.from_edit_mesh(atom.data) locations = [] for v in bm.verts: @@ -443,13 +443,13 @@ def separate_atoms(scn): # ... delete the new mesh including the separated vertex bpy.ops.object.select_all(action='DESELECT') new_object.select = True - bpy.ops.object.delete() + bpy.ops.object.delete() # Create new atoms/vacancies at the position of the old atoms # For all selected positions do: for location in locations: # Create a new object by duplication of the child of the dupliverts - # structure. <= this is done 'len(locations)' times. After each + # structure. <= this is done 'len(locations)' times. After each # duplication, move the new object onto the positions bpy.ops.object.select_all(action='DESELECT') atom.children[0].select = True @@ -458,8 +458,8 @@ def separate_atoms(scn): new_atom = bpy.context.scene.objects.active new_atom.parent = None new_atom.location = location - new_atom.name = atom.name + "_sep" - + new_atom.name = atom.name + "_sep" + bpy.context.scene.objects.active = atom @@ -468,11 +468,11 @@ def draw_obj_material(material_type, material): if material_type == '0': # Unchanged material_new = material - if material_type == '1': # Normal + if material_type == '1': # Normal material_new = bpy.data.materials.new(material.name + "_normal") - if material_type == '2': # Transparent + if material_type == '2': # Transparent material_new = bpy.data.materials.new(material.name + "_transparent") - material_new.use_transparency = True + material_new.use_transparency = True material_new.transparency_method = 'Z_TRANSPARENCY' material_new.alpha = 1.3 material_new.raytrace_transparency.fresnel = 1.6 @@ -480,13 +480,13 @@ def draw_obj_material(material_type, material): if material_type == '3': # Reflecting material_new = bpy.data.materials.new(material.name + "_reflecting") material_new.raytrace_mirror.use = True - material_new.raytrace_mirror.reflect_factor = 0.6 + material_new.raytrace_mirror.reflect_factor = 0.6 material_new.raytrace_mirror.fresnel = 0.0 - material_new.raytrace_mirror.fresnel_factor = 1.250 + material_new.raytrace_mirror.fresnel_factor = 1.250 material_new.raytrace_mirror.depth = 2 - material_new.raytrace_mirror.distance = 0.0 - material_new.raytrace_mirror.gloss_factor = 1.0 - if material_type == '4': # Transparent + reflecting + material_new.raytrace_mirror.distance = 0.0 + material_new.raytrace_mirror.gloss_factor = 1.0 + if material_type == '4': # Transparent + reflecting material_new = bpy.data.materials.new(material.name + "_trans+refl") material_new.use_transparency = True material_new.transparency_method = 'Z_TRANSPARENCY' @@ -494,16 +494,16 @@ def draw_obj_material(material_type, material): material_new.raytrace_transparency.fresnel = 1.6 material_new.raytrace_transparency.fresnel_factor = 1.6 material_new.raytrace_mirror.use = True - material_new.raytrace_mirror.reflect_factor = 0.6 + material_new.raytrace_mirror.reflect_factor = 0.6 material_new.raytrace_mirror.fresnel = 0.0 - material_new.raytrace_mirror.fresnel_factor = 1.250 + material_new.raytrace_mirror.fresnel_factor = 1.250 material_new.raytrace_mirror.depth = 2 - material_new.raytrace_mirror.distance = 0.0 - material_new.raytrace_mirror.gloss_factor = 1.0 - - # Always, when the material is changed, a new name is created. Note that - # this makes sense: Imagine, an other object uses the same material as the - # selected one. After changing the material of the selected object the old + material_new.raytrace_mirror.distance = 0.0 + material_new.raytrace_mirror.gloss_factor = 1.0 + + # Always, when the material is changed, a new name is created. Note that + # this makes sense: Imagine, an other object uses the same material as the + # selected one. After changing the material of the selected object the old # material should certainly not change and remain the same. if material_type in {'1','2','3','4'}: if "_repl" in material.name: @@ -515,8 +515,8 @@ def draw_obj_material(material_type, material): material_new.name = material.name+"_repl1" else: material_new.name = material.name+"_repl1" - material_new.diffuse_color = material.diffuse_color - + material_new.diffuse_color = material.diffuse_color + return material_new @@ -532,115 +532,115 @@ def draw_obj(atom_shape, atom): if atom_shape == '1a': #Sphere mesh bpy.ops.mesh.primitive_uv_sphere_add( segments=32, - ring_count=32, - size=1, - view_align=False, + ring_count=32, + size=1, + view_align=False, enter_editmode=False, location=atom.location, rotation=(0, 0, 0), layers=current_layers) if atom_shape == '1b': #Sphere NURBS bpy.ops.surface.primitive_nurbs_surface_sphere_add( - view_align=False, + view_align=False, enter_editmode=False, location=atom.location, rotation=(0.0, 0.0, 0.0), layers=current_layers) if atom_shape == '2': #Cube bpy.ops.mesh.primitive_cube_add( - view_align=False, + view_align=False, enter_editmode=False, location=atom.location, rotation=(0.0, 0.0, 0.0), layers=current_layers) - if atom_shape == '3': #Plane + if atom_shape == '3': #Plane bpy.ops.mesh.primitive_plane_add( - view_align=False, - enter_editmode=False, - location=atom.location, - rotation=(0.0, 0.0, 0.0), + view_align=False, + enter_editmode=False, + location=atom.location, + rotation=(0.0, 0.0, 0.0), layers=current_layers) if atom_shape == '4a': #Circle bpy.ops.mesh.primitive_circle_add( - vertices=32, - radius=1, - fill_type='NOTHING', - view_align=False, - enter_editmode=False, - location=atom.location, - rotation=(0, 0, 0), - layers=current_layers) + vertices=32, + radius=1, + fill_type='NOTHING', + view_align=False, + enter_editmode=False, + location=atom.location, + rotation=(0, 0, 0), + layers=current_layers) if atom_shape == '4b': #Circle NURBS bpy.ops.surface.primitive_nurbs_surface_circle_add( - view_align=False, - enter_editmode=False, - location=atom.location, - rotation=(0, 0, 0), + view_align=False, + enter_editmode=False, + location=atom.location, + rotation=(0, 0, 0), layers=current_layers) - if atom_shape in {'5a','5b','5c','5d','5e'}: #Icosphere - index = {'5a':1,'5b':2,'5c':3,'5d':4,'5e':5} + if atom_shape in {'5a','5b','5c','5d','5e'}: #Icosphere + index = {'5a':1,'5b':2,'5c':3,'5d':4,'5e':5} bpy.ops.mesh.primitive_ico_sphere_add( - subdivisions=int(index[atom_shape]), - size=1, - view_align=False, - enter_editmode=False, - location=atom.location, - rotation=(0, 0, 0), + subdivisions=int(index[atom_shape]), + size=1, + view_align=False, + enter_editmode=False, + location=atom.location, + rotation=(0, 0, 0), layers=current_layers) if atom_shape == '6a': #Cylinder bpy.ops.mesh.primitive_cylinder_add( - vertices=32, - radius=1, - depth=2, - end_fill_type='NGON', - view_align=False, - enter_editmode=False, - location=atom.location, - rotation=(0, 0, 0), + vertices=32, + radius=1, + depth=2, + end_fill_type='NGON', + view_align=False, + enter_editmode=False, + location=atom.location, + rotation=(0, 0, 0), layers=current_layers) if atom_shape == '6b': #Cylinder NURBS bpy.ops.surface.primitive_nurbs_surface_cylinder_add( - view_align=False, - enter_editmode=False, - location=atom.location, - rotation=(0, 0, 0), - layers=current_layers) + view_align=False, + enter_editmode=False, + location=atom.location, + rotation=(0, 0, 0), + layers=current_layers) if atom_shape == '7': #Cone bpy.ops.mesh.primitive_cone_add( - vertices=32, - radius1=1, - radius2=0, - depth=2, - end_fill_type='NGON', - view_align=False, - enter_editmode=False, - location=atom.location, - rotation=(0, 0, 0), + vertices=32, + radius1=1, + radius2=0, + depth=2, + end_fill_type='NGON', + view_align=False, + enter_editmode=False, + location=atom.location, + rotation=(0, 0, 0), layers=current_layers) if atom_shape == '8a': #Torus bpy.ops.mesh.primitive_torus_add( - rotation=(0, 0, 0), - location=atom.location, - view_align=False, - major_radius=1, - minor_radius=0.25, - major_segments=48, - minor_segments=12, - abso_major_rad=1, - abso_minor_rad=0.5) + rotation=(0, 0, 0), + location=atom.location, + view_align=False, + major_radius=1, + minor_radius=0.25, + major_segments=48, + minor_segments=12, + abso_major_rad=1, + abso_minor_rad=0.5) if atom_shape == '8b': #Torus NURBS bpy.ops.surface.primitive_nurbs_surface_torus_add( - view_align=False, - enter_editmode=False, - location=atom.location, - rotation=(0, 0, 0), + view_align=False, + enter_editmode=False, + location=atom.location, + rotation=(0, 0, 0), layers=current_layers) new_atom = bpy.context.scene.objects.active new_atom.scale = atom.scale + Vector((0.0,0.0,0.0)) - new_atom.name = atom.name + "_tmp" + new_atom.name = atom.name + "_tmp" new_atom.select = True - + return new_atom @@ -660,7 +660,7 @@ def draw_obj_special(atom_shape, atom): new_atom.location = atom.location material_new = bpy.data.materials.new(atom.active_material.name + "_sep") material_new.name = atom.name + "_halo" - material_new.diffuse_color = atom.active_material.diffuse_color + material_new.diffuse_color = atom.active_material.diffuse_color material_new.type = 'HALO' material_new.halo.size = atom.scale[0]*1.5 material_new.halo.hardness = 25 @@ -671,19 +671,19 @@ def draw_obj_special(atom_shape, atom): # F2+ center if atom_shape == '2': # Create first a cube - bpy.ops.mesh.primitive_cube_add(view_align=False, + bpy.ops.mesh.primitive_cube_add(view_align=False, enter_editmode=False, location=atom.location, rotation=(0.0, 0.0, 0.0), layers=current_layers) cube = bpy.context.scene.objects.active cube.scale = atom.scale + Vector((0.0,0.0,0.0)) - cube.name = atom.name + "_F2+-center" - cube.select = True + cube.name = atom.name + "_F2+-center" + cube.select = True # New material for this cube material_cube = bpy.data.materials.new(atom.name + "_F2+-center") - material_cube.diffuse_color = [0.8,0.0,0.0] - material_cube.use_transparency = True + material_cube.diffuse_color = [0.8,0.0,0.0] + material_cube.use_transparency = True material_cube.transparency_method = 'Z_TRANSPARENCY' material_cube.alpha = 1.0 material_cube.raytrace_transparency.fresnel = 1.6 @@ -692,32 +692,32 @@ def draw_obj_special(atom_shape, atom): # Put a nice point lamp inside the defect lamp_data = bpy.data.lamps.new(name="F2+_lamp", type="POINT") lamp_data.distance = atom.scale[0] * 2.0 - lamp_data.energy = 20.0 - lamp_data.use_sphere = True - lamp_data.color = [0.8,0.8,0.8] + lamp_data.energy = 20.0 + lamp_data.use_sphere = True + lamp_data.color = [0.8,0.8,0.8] lamp = bpy.data.objects.new("F2+_lamp", lamp_data) lamp.location = Vector((0.0, 0.0, 0.0)) lamp.layers = current_layers - bpy.context.scene.objects.link(lamp) + bpy.context.scene.objects.link(lamp) lamp.parent = cube - # The new 'atom' is the F2+ defect - new_atom = cube + # The new 'atom' is the F2+ defect + new_atom = cube # F+ center if atom_shape == '3': # Create first a cube - bpy.ops.mesh.primitive_cube_add(view_align=False, + bpy.ops.mesh.primitive_cube_add(view_align=False, enter_editmode=False, location=atom.location, rotation=(0.0, 0.0, 0.0), layers=current_layers) cube = bpy.context.scene.objects.active cube.scale = atom.scale + Vector((0.0,0.0,0.0)) - cube.name = atom.name + "_F+-center" - cube.select = True + cube.name = atom.name + "_F+-center" + cube.select = True # New material for this cube material_cube = bpy.data.materials.new(atom.name + "_F+-center") - material_cube.diffuse_color = [0.8,0.8,0.0] - material_cube.use_transparency = True + material_cube.diffuse_color = [0.8,0.8,0.0] + material_cube.use_transparency = True material_cube.transparency_method = 'Z_TRANSPARENCY' material_cube.alpha = 1.0 material_cube.raytrace_transparency.fresnel = 1.6 @@ -726,21 +726,21 @@ def draw_obj_special(atom_shape, atom): # Create now an electron scale = atom.scale / 10.0 bpy.ops.surface.primitive_nurbs_surface_sphere_add( - view_align=False, + view_align=False, enter_editmode=False, location=(0.0, 0.0, 0.0), rotation=(0.0, 0.0, 0.0), - layers=current_layers) + layers=current_layers) electron = bpy.context.scene.objects.active electron.scale = scale - electron.name = atom.name + "_F+_electron" - electron.parent = cube + electron.name = atom.name + "_F+_electron" + electron.parent = cube # New material for the electron material_electron = bpy.data.materials.new(atom.name + "_F+-center") material_electron.diffuse_color = [0.0,0.0,0.8] material_electron.specular_hardness = 200 material_electron.emit = 1.0 - material_electron.use_transparency = True + material_electron.use_transparency = True material_electron.transparency_method = 'Z_TRANSPARENCY' material_electron.alpha = 1.3 material_electron.raytrace_transparency.fresnel = 1.2 @@ -749,32 +749,32 @@ def draw_obj_special(atom_shape, atom): # Put a nice point lamp inside the electron lamp_data = bpy.data.lamps.new(name="F+_lamp", type="POINT") lamp_data.distance = atom.scale[0] * 2.0 - lamp_data.energy = 20.0 - lamp_data.use_sphere = True - lamp_data.color = [0.8,0.8,0.8] + lamp_data.energy = 20.0 + lamp_data.use_sphere = True + lamp_data.color = [0.8,0.8,0.8] lamp = bpy.data.objects.new("F+_lamp", lamp_data) lamp.location = Vector((0.0, 0.0, 0.0)) lamp.layers = current_layers - bpy.context.scene.objects.link(lamp) + bpy.context.scene.objects.link(lamp) lamp.parent = cube # The new 'atom' is the F+ defect complex + lamp new_atom = cube # F0 center if atom_shape == '4': # Create first a cube - bpy.ops.mesh.primitive_cube_add(view_align=False, + bpy.ops.mesh.primitive_cube_add(view_align=False, enter_editmode=False, location=atom.location, rotation=(0.0, 0.0, 0.0), layers=current_layers) cube = bpy.context.scene.objects.active cube.scale = atom.scale + Vector((0.0,0.0,0.0)) - cube.name = atom.name + "_F0-center" - cube.select = True + cube.name = atom.name + "_F0-center" + cube.select = True # New material for this cube material_cube = bpy.data.materials.new(atom.name + "_F0-center") - material_cube.diffuse_color = [0.8,0.8,0.8] - material_cube.use_transparency = True + material_cube.diffuse_color = [0.8,0.8,0.8] + material_cube.use_transparency = True material_cube.transparency_method = 'Z_TRANSPARENCY' material_cube.alpha = 1.0 material_cube.raytrace_transparency.fresnel = 1.6 @@ -783,31 +783,31 @@ def draw_obj_special(atom_shape, atom): # Create now two electrons scale = atom.scale / 10.0 bpy.ops.surface.primitive_nurbs_surface_sphere_add( - view_align=False, + view_align=False, enter_editmode=False, location=(scale[0]*1.5,0.0,0.0), rotation=(0.0, 0.0, 0.0), - layers=current_layers) + layers=current_layers) electron1 = bpy.context.scene.objects.active electron1.scale = scale - electron1.name = atom.name + "_F0_electron1" - electron1.parent = cube + electron1.name = atom.name + "_F0_electron1" + electron1.parent = cube bpy.ops.surface.primitive_nurbs_surface_sphere_add( - view_align=False, + view_align=False, enter_editmode=False, location=(-scale[0]*1.5,0.0,0.0), rotation=(0.0, 0.0, 0.0), - layers=current_layers) + layers=current_layers) electron2 = bpy.context.scene.objects.active electron2.scale = scale - electron2.name = atom.name + "_F0_electron2" - electron2.parent = cube + electron2.name = atom.name + "_F0_electron2" + electron2.parent = cube # New material for the electrons material_electron = bpy.data.materials.new(atom.name + "_F0-center") material_electron.diffuse_color = [0.0,0.0,0.8] material_electron.specular_hardness = 200 material_electron.emit = 1.0 - material_electron.use_transparency = True + material_electron.use_transparency = True material_electron.transparency_method = 'Z_TRANSPARENCY' material_electron.alpha = 1.3 material_electron.raytrace_transparency.fresnel = 1.2 @@ -817,30 +817,30 @@ def draw_obj_special(atom_shape, atom): # Put two nice point lamps inside the electrons lamp1_data = bpy.data.lamps.new(name="F0_lamp1", type="POINT") lamp1_data.distance = atom.scale[0] * 2.0 - lamp1_data.energy = 8.0 - lamp1_data.use_sphere = True - lamp1_data.color = [0.8,0.8,0.8] + lamp1_data.energy = 8.0 + lamp1_data.use_sphere = True + lamp1_data.color = [0.8,0.8,0.8] lamp1 = bpy.data.objects.new("F0_lamp", lamp1_data) lamp1.location = Vector((scale[0]*1.5, 0.0, 0.0)) lamp1.layers = current_layers - bpy.context.scene.objects.link(lamp1) + bpy.context.scene.objects.link(lamp1) lamp1.parent = cube lamp2_data = bpy.data.lamps.new(name="F0_lamp2", type="POINT") lamp2_data.distance = atom.scale[0] * 2.0 - lamp2_data.energy = 8.0 - lamp2_data.use_sphere = True - lamp2_data.color = [0.8,0.8,0.8] + lamp2_data.energy = 8.0 + lamp2_data.use_sphere = True + lamp2_data.color = [0.8,0.8,0.8] lamp2 = bpy.data.objects.new("F0_lamp", lamp2_data) lamp2.location = Vector((-scale[0]*1.5, 0.0, 0.0)) lamp2.layers = current_layers - bpy.context.scene.objects.link(lamp2) - lamp2.parent = cube + bpy.context.scene.objects.link(lamp2) + lamp2.parent = cube # The new 'atom' is the F0 defect complex + lamps new_atom = cube - + return new_atom - - + + # Initialization of the list 'ELEMENTS'. def read_elements(): @@ -853,7 +853,7 @@ def read_elements(): # The handling of the ionic radii will be done later. So far, it is an # empty list. radii_ionic = item[7:] - + li = ElementProp(item[0],item[1],item[2],item[3], radii,radii_ionic) ELEMENTS.append(li) @@ -935,4 +935,4 @@ def custom_datafile(path_datafile): data_file_p.close() - return True + return True diff --git a/io_directx_bel/__init__.py b/io_directx_bel/__init__.py index 8841e7275853ebc21397f0da6aa24e471b67810c..f8a346ea7fe3d89e667aa93bb6b950429a6358a6 100644 --- a/io_directx_bel/__init__.py +++ b/io_directx_bel/__init__.py @@ -292,4 +292,4 @@ def unregister(): #bpy.types.INFO_MT_file_export.remove(menu_func_export) if __name__ == "__main__": - register() \ No newline at end of file + register() diff --git a/io_directx_bel/bel/__init__.py b/io_directx_bel/bel/__init__.py index 6db2d817b0869a66f6ab2401d9fe5bd6ce7a0f5f..f8ce1d1a2aac93c048d489906296ab84fa5acffd 100644 --- a/io_directx_bel/bel/__init__.py +++ b/io_directx_bel/bel/__init__.py @@ -21,4 +21,4 @@ def nested(lst) : t = lst[0][0][0] return lst, True except : - return [lst], False \ No newline at end of file + return [lst], False diff --git a/io_directx_bel/bel/fs.py b/io_directx_bel/bel/fs.py index 169cae3d335754d71c5afbcd4bb11ad9916e6a19..07239a66254d0185f26512887f60a5c75e23b8da 100644 --- a/io_directx_bel/bel/fs.py +++ b/io_directx_bel/bel/fs.py @@ -10,7 +10,7 @@ def clean(path) : path = path.strip().replace('\\','/') if ('/') not in path : path = '//'+path return path - + ## test for existence of a file or a dir def exist(path) : if isfile(path) or isdir(path) : return True @@ -67,8 +67,7 @@ def saveOptions(op,operator_name, tokens, filename='last_run'): value = value[:] except: pass - + file_preset.write("op.%s = %r\n" % (key, value)) file_preset.close() - diff --git a/io_directx_bel/bel/group.py b/io_directx_bel/bel/group.py index a295d6e0c9e29b6139e0660d5540cf11fc7e727a..05f38461e1014dd132e9dab0ee523fe70cf41ffd 100644 --- a/io_directx_bel/bel/group.py +++ b/io_directx_bel/bel/group.py @@ -4,7 +4,7 @@ given name < 21 if material name exists : naming_method = 0 blender default (increment name) naming_method = 1 do nothing, abort creation and use existing -naming_method = 2 create new, rename existing, +naming_method = 2 create new, rename existing, naming_method = 3 create new, replace existing ''' @@ -53,7 +53,7 @@ def remove(ob,with_data=True) : and_data=False except : and_data=False # empties - + # odd (pre 2.60) : # ob=bpy.data.objects[ob.name] # if the ob (board) argument comes from bpy.data.groups['aGroup'].objects, @@ -72,4 +72,3 @@ def remove(ob,with_data=True) : # never wipe data before unlink the ex-user object of the scene else crash (2.58 3 770 2) if and_data : wipeOutData(data) - diff --git a/io_directx_bel/bel/image.py b/io_directx_bel/bel/image.py index 74f45b20c36205b1f9f036096442df34bef8ef79..9db42d963a5776cf1ce4c723f4cc46f0c5da9137 100644 --- a/io_directx_bel/bel/image.py +++ b/io_directx_bel/bel/image.py @@ -11,7 +11,7 @@ def dprint(str,l=2) : print(str) # create or retrieve a bdata image -# given its path +# given its path def new(path, name=False, relative = True) : path = fs.clean(path) # check file @@ -23,9 +23,9 @@ def new(path, name=False, relative = True) : try : path = bpy.path.relpath(path) path = fs.clean(path) - except : + except : print('cant turn path into relative one (.blend and img path drive letters ?) ') - + # retrieve paths to image file from existing image slot # returns img if paths match for img in bpy.data.images : @@ -34,7 +34,7 @@ def new(path, name=False, relative = True) : return img # create a unique name in image slot - if name == False : + if name == False : name = bpy.path.basename(path) name = bel.bpyname(name,bpy.data.images.keys()) @@ -52,7 +52,7 @@ def applyShader(mat,config) : texslot = mat.texture_slots[0] tex = texslot.texture img = tex.image - + #config = shaders[shadername] alpha = True if 'alpha' in config else False @@ -184,12 +184,12 @@ def BSshader(nodes,pointer) : for key in RenderMaterial.keys() : if key not in ['DiffuseColor','SpecularColor','AmbientColor','EmissionColor','Shininess','Transparency'] : print('NEW RENDERMATERIAL PROP ! : %s'%key) - + #print(AmbientColor) if DiffuseColor : mat.diffuse_color = Color(DiffuseColor) #[0][0],DiffuseColor[0][1],DiffuseColor[0][2]) if SpecularColor : mat.specular_color = Color(SpecularColor)#[0][0],SpecularColor[0][1],SpecularColor[0][2]) - if AmbientColor : mat.ambient = AmbientColor[0] # source value is a vector3f with x=y=z - if EmissionColor : mat.emit = EmissionColor[0] # source value is a vector3f with x=y=z + if AmbientColor : mat.ambient = AmbientColor[0] # source value is a vector3f with x=y=z + if EmissionColor : mat.emit = EmissionColor[0] # source value is a vector3f with x=y=z #if Shininess : mat. #alpha is a boolean, whereas Transparency is a float or False if Transparency : @@ -221,7 +221,7 @@ def BSshader(nodes,pointer) : imgname = imgpath.split('/')[-1] imgpath = tkm.path_archives+'/Images/Q=Tex032M/'+imgpath - if imgname not in bpy.data.images : + if imgname not in bpy.data.images : if os.path.isfile(imgpath+'.png') : ext = '.png' elif os.path.isfile(imgpath+'.jp2') : ext = '.jp2' else : @@ -231,13 +231,13 @@ def BSshader(nodes,pointer) : img = bpy.data.images.load(filepath=imgpath+ext) img.name = imgname else : img = bpy.data.images[imgname] - + ''' texslot = mat.texture_slots[0] mat.texture_slots[0] tex = texslot.texture tex.type = 'IMAGE' - img = tex.image + img = tex.image img.name ''' #img = bpy.data.images.new(name='imgname',width=640, height=512) @@ -256,4 +256,4 @@ def BSshader(nodes,pointer) : texslot.use_map_alpha = alpha texslot.alpha_factor = 1.0 - return mat \ No newline at end of file + return mat diff --git a/io_directx_bel/bel/material.py b/io_directx_bel/bel/material.py index 048dfc3cfe18fd46dd23b49a89b89c2991c78a09..0f6d823631e104f0ceff4376c19ca33d6ab85f97 100644 --- a/io_directx_bel/bel/material.py +++ b/io_directx_bel/bel/material.py @@ -5,24 +5,24 @@ given name < 21 if material name exists : naming_method = 0 blender default (increment name) naming_method = 1 do nothing, abort creation and use existing -naming_method = 2 create new, rename existing, +naming_method = 2 create new, rename existing, naming_method = 3 create new, replace existing ''' def new(name, naming_method=0) : if name not in bpy.data.materials or naming_method == 0: return bpy.data.materials.new(name=name) - + elif naming_method == 1 : return bpy.data.materials[name] - + mat = bpy.data.materials.new(name=name) - + if naming_method == 2 : mat.name = name return mat - - # naming_method = 3 : replace + + # naming_method = 3 : replace prevmat = bpy.data.materials[name] for ob in bpy.data.objects : for matslot in ob.material_slots : @@ -30,4 +30,3 @@ def new(name, naming_method=0) : matslot.material = mat bpy.data.materials.remove(prevmat) return mat - diff --git a/io_directx_bel/bel/mesh.py b/io_directx_bel/bel/mesh.py index 5c60746034cc3e27d358f9a3ddfabe90a9b7606e..af290326f7f4448a21724a81223ae9e6e30bac36 100644 --- a/io_directx_bel/bel/mesh.py +++ b/io_directx_bel/bel/mesh.py @@ -16,9 +16,9 @@ no : create yes : naming_method = 0 blender default (increment name) naming_method = 1 do nothing, abort creation and use existing - naming_method = 2 create new, rename existing, + naming_method = 2 create new, rename existing, naming_method = 3 create new, remove existing - + for now, and mesh data, 0 2 or 3 ''' @@ -27,7 +27,7 @@ given name < 21 if material name exists : naming_method = 0 blender default (increment name) naming_method = 1 do nothing, abort creation and use existing -naming_method = 2 create new, rename existing, +naming_method = 2 create new, rename existing, naming_method = 3 create new, replace existing ''' @@ -42,7 +42,7 @@ def new(name, naming_method=0) : me = bpy.data.meshes.new(name=name) me.name = name return me - + # naming_method = 3 : replace, keep users me = bpy.data.meshes[name] bm = bmesh.new() @@ -51,15 +51,15 @@ def new(name, naming_method=0) : ## material listed in matslots must exist before creation of material slots -def write(obname,name, - verts=[], edges=[], faces=[], - matslots=[], mats=[], uvs=[], +def write(obname,name, + verts=[], edges=[], faces=[], + matslots=[], mats=[], uvs=[], groupnames=[], vindices=[], vweights=[], smooth=False, naming_method = 0, ) : - + obj = bpy.data.objects[obname] if obname in bpy.data.objects else False me = bpy.data.meshes[name] if name in bpy.data.meshes else False @@ -69,19 +69,19 @@ def write(obname,name, if naming_method == 1 and me and obj and obj.data == me : #print('%s and %s exist, reuse'%(obj.name,me.name)) return obj - + if naming_method == 3 : - if obj : + if obj : #print('remove ob %s'%obj.name) bob.remove(obj,False) if me : #print('remove me %s'%me.name) bob.removeData(me) - + me = bpy.data.meshes.new(name) if naming_method == 2 : me.name = name - + me.from_pydata(verts, edges, faces) me.update() @@ -126,26 +126,26 @@ def write(obname,name, obj = bpy.data.objects.new(name=obname, object_data=me) if naming_method != 0 : obj.name = obname - + ''' else : ob = bpy.data.objects[name] ob.data = me - if naming_method == 2 : ob.name = + if naming_method == 2 : ob.name = ob.parent = None ob.matrix_local = Matrix() print(' reuse object %s'%ob.name) ''' - + # vertexgroups if len(groupnames) > 0 : for gpi, groupname in enumerate(groupnames) : weightsadd(obj, groupname, vindices[gpi], vweights[gpi]) - + # scene link check if obj.name not in bpy.context.scene.objects.keys() : bpy.context.scene.objects.link(obj) - + return obj def shadesmooth(me,lst=True) : @@ -155,7 +155,7 @@ def shadesmooth(me,lst=True) : else : for fi,face in enumerate(me.polygons) : face.use_smooth = True - + def shadeflat(me,lst=True) : if type(lst) == list : for fi in lst : @@ -185,7 +185,7 @@ def objectBuild(elm, verts, edges=[], faces=[], matslots=[], mats=[], uvs=[] ) : city = bpy.context.scene.city # apply current scale verts = metersToBu(verts) - + if type(elm) != str : obname = elm.objectName() if obname == 'not built' : @@ -232,5 +232,3 @@ def materialsCheck(bld) : method = 'random' mat.diffuse_color=( random.uniform(0.0,1.0),random.uniform(0.0,1.0),random.uniform(0.0,1.0)) dprint('Created missing material %s (%s)'%(matname,method),2) - - diff --git a/io_directx_bel/bel/ob.py b/io_directx_bel/bel/ob.py index 486bced1550d408d19469137f049494b81c32972..52e6352efc3232fe53a923c6523a8ef62f8c6e3f 100644 --- a/io_directx_bel/bel/ob.py +++ b/io_directx_bel/bel/ob.py @@ -53,7 +53,7 @@ def remove(ob,with_data=True) : and_data=False except : and_data=False # empties - + # odd (pre 2.60) : # ob=bpy.data.objects[ob.name] # if the ob (board) argument comes from bpy.data.groups['aGroup'].objects, @@ -78,12 +78,12 @@ def remove(ob,with_data=True) : ## or rename it _dead if there's still users def removeData(data) : #print('%s has %s user(s) !'%(data.name,data.users)) - + if data.users <= 0 : #data.user_clear() data_type = type(data) - + # mesh if data_type == Mesh : bpy.data.meshes.remove(data) @@ -113,4 +113,3 @@ def removeData(data) : else : #print(' not done, %s has %s user'%(data.name,data.users)) data.name = '_dead' - \ No newline at end of file diff --git a/io_directx_bel/bel/uv.py b/io_directx_bel/bel/uv.py index 28278190622e95ac458d6f97f5702c756a7d3a36..9b21bb979bec02c2f04ae6f5032b1299090bde1a 100644 --- a/io_directx_bel/bel/uv.py +++ b/io_directx_bel/bel/uv.py @@ -3,7 +3,7 @@ from .__init__ import * from time import clock # uvs : -# +# def write(me, uvs, matimage = False) : t = clock() uvs, nest = nested(uvs) @@ -13,9 +13,9 @@ def write(me, uvs, matimage = False) : uv = me.uv_textures.new() uv.name = 'UV%s'%uvi - + uvlayer = me.uv_layers[-1].data - + for uvfi, uvface in enumerate(uvlist) : #uv.data[uvfi].use_twoside = True # 2.60 changes mat ways mslotid = me.polygons[uvfi].material_index @@ -24,17 +24,17 @@ def write(me, uvs, matimage = False) : if matimage[mslotid] : img = matimage[mslotid] uv.data[uvfi].image=img - + vi = 0 for fi in me.polygons[uvfi].loop_indices : uvlayer[fi].uv = Vector((uvface[vi],uvface[vi+1])) vi += 2 - + newuvs.append(uv) print('uvs in ',clock() - t) if nest : return newuvs return newuvs[0] - + ## WAY faster def flatwrite(me, uvs, matimage = False) : #t = clock() @@ -56,7 +56,7 @@ def flatwrite(me, uvs, matimage = False) : #print('uvs in ',clock() - t) return newuvs -# face are squared or rectangular, +# face are squared or rectangular, # any orientation # vert order width then height 01 and 23 = x 12 and 03 = y # normal default when face has been built @@ -106,4 +106,4 @@ def asFlatList(uvlist,faces) : for vi in f : uv.extend(uvlist[vi]) #print('uvs convert in %s len : %s'%(str(clock() - t),len(uv))) - return uv \ No newline at end of file + return uv diff --git a/io_directx_bel/import_x.py b/io_directx_bel/import_x.py index f96dc7e5123e537018131deca70598595a3a2388..895af3a6b4f4978f67e07a5374ce2c7a074ba071 100644 --- a/io_directx_bel/import_x.py +++ b/io_directx_bel/import_x.py @@ -77,13 +77,13 @@ def load(operator, context, filepath, use_image_search=True, global_matrix=None, ): - - + + if quickmode : parented = False - + bone_minlength = bone_maxlength / 100.0 - + #global templates, tokens rootTokens = [] namelookup = {} @@ -102,7 +102,7 @@ def load(operator, context, filepath, ''' ''' with * : defined in dXdata - + WORD 16 bits * DWORD 32 bits * FLOAT IEEE float @@ -147,13 +147,13 @@ BINARY FORMAT #define TOKEN_UNICODE 50 #define TOKEN_CSTRING 51 #define TOKEN_ARRAY 52 - + ''' - + # COMMON REGEX space = '[\ \t]{1,}' # at least one space / tab space0 = '[\ \t]{0,}' # zero or more space / tab - + # DIRECTX REGEX TOKENS r_template = r'template' + space + '[\w]*' + space0 + '\{' if quickmode : @@ -162,10 +162,10 @@ BINARY FORMAT r_sectionname = r'[\w]*' + space + '[\w-]*' + space0 + '\{' r_refsectionname = r'\{' + space0 + '[\w-]*' + space0 + '\}' r_endsection = r'\{|\}' - + # dX comments r_ignore = r'#|//' - + #r_frame = r'Frame' + space + '[\w]*' #r_matrix = r'FrameTransformMatrix' + space + '\{[\s\d.,-]*' #r_mesh = r'Mesh' + space + '[\W]*' @@ -173,7 +173,7 @@ BINARY FORMAT ################### ## STEP 1 FUNCTIONS ################### - + ## HEADER # returns header values or False if directx reco tag is missing # assuming there's never comment header and that xof if the 1st @@ -183,9 +183,9 @@ BINARY FORMAT 4 Magic Number (required) "xof " 2 Minor Version 03 2 Major Version 02 - 4 Format Type (required) + 4 Format Type (required) "txt " Text File - "bin " Binary File + "bin " Binary File "tzip" MSZip Compressed Text File "bzip" MSZip Compressed Binary File 4 Float Accuracy "0032" 32 bit or "0064" 64 bit @@ -202,8 +202,8 @@ BINARY FORMAT accuracy = int(data.read(4).decode()) data.seek(0) return ( minor, major, format, accuracy ) - - + + ## def dXtree(data,quickmode = False) : tokens = {} @@ -221,7 +221,7 @@ BINARY FORMAT lines, trunkated = nextFileChunk(data,trunkated) if lines == None : break for l in lines : - + # compute pointer position ptr += eol c += 1 @@ -230,16 +230,16 @@ BINARY FORMAT #if l != '' : print('***',l) #if l == '' : break l = l.strip() - + # remove blank and comment lines if l == '' or re.match(r_ignore,l) : continue - + # one line token cases level switch if previouslvl : lvl -= 1 previouslvl = False - + #print('%s lines in %.2f\''%(c,time.clock()-t),end='\r') #print(c,len(l)+1,ptr,data.tell()) if '{' in l : @@ -248,14 +248,14 @@ BINARY FORMAT elif '}' in l : lvl -= 1 #print(c,lvl,tree) - + if quickmode == False : ## look for templates if re.match(r_template,l) : tname = l.split(' ')[1] templates[tname] = {'pointer' : ptr, 'line' : c} continue - + ## look for {references} if re.match(r_refsectionname,l) : refname = namelookup[ l[1:-1].strip() ] @@ -271,7 +271,7 @@ BINARY FORMAT if 'user' not in tokens[refname] : tokens[refname]['users'] = [parent] else : tokens[refname]['users'].append(parent) continue - + ## look for any token or only Mesh token in quickmode if re.match(r_sectionname,l) : tokenname = getName(l,tokens) @@ -289,7 +289,7 @@ BINARY FORMAT tokens[tokenname]['parent'] = parent tokens[tokenname]['childs'] = [] tokens[tokenname]['type'] = typ - + else : tokens[tokenname] = {'pointer': ptr, 'line' : c, 'parent' : parent, @@ -300,9 +300,9 @@ BINARY FORMAT tree.append(tokenname) if lvl > 1 and quickmode == False : tokens[parent]['childs'].append(tokenname) - + return tokens, templates, tokentypes - + ## returns file binary chunks def nextFileChunk(data,trunkated=False,chunksize=1024) : if chunksize == 0 : chunk = data.read() @@ -312,7 +312,7 @@ BINARY FORMAT #if stream : return lines.replace('\r','').replace('\n','') lines = lines.replace('\r','\n').split('\n') if trunkated : lines[0] = trunkated + lines[0] - if len(lines) == 1 : + if len(lines) == 1 : if lines[0] == '' : return None, None return lines, False return lines, lines.pop() @@ -323,28 +323,28 @@ BINARY FORMAT w = chunk[word:word+4] print(word,w,struct.unpack("<l", w),binascii.unhexlify(w)) - + # name unnamed tokens, watchout for x duplicate # for blender, referenced token in x should be named and unique.. def getName(l,tokens) : xnam = l.split(' ')[1].strip() - + #if xnam[0] == '{' : xnam = '' if xnam and xnam[-1] == '{' : xnam = xnam[:-1] - + name = xnam if len(name) == 0 : name = l.split(' ')[0].strip() - + namelookup[xnam] = bel.bpyname(name,tokens,4) return namelookup[xnam] - - + + ################### ## STEP 2 FUNCTIONS ################### # once the internal dict is populated the functions below can be used - + ## from a list of tokens, displays every child, users and references ''' walk_dxtree( [ 'Mesh01', 'Mesh02' ] ) # for particular pieces @@ -357,21 +357,21 @@ BINARY FORMAT tokenname = tokenname[1:] ref = 'ref: ' else : ref = False - + frame_type = tokens[tokenname]['type'] line = ('{:7}'.format(tokens[tokenname]['line'])) log = ' %s%s (%s)'%( ref if ref else '', tokenname, frame_type ) print('%s.%s%s'%(line, tab, log)) if fi == len(field) - 1 : tab = tab[:-3] + ' ' - + if ref == False : for user in tokens[tokenname]['users'] : print('%s.%s |__ user: %s'%(line, tab.replace('_',' '), user)) walk_dXtree(tokens[tokenname]['childs'],lvl+1,tab.replace('_',' ')+' |__') - + if fi == len(field) - 1 and len(tokens[tokenname]['childs']) == 0 : print('%s.%s'%(line,tab)) - + ## remove eol, comments, spaces from a raw block of datas def cleanBlock(block) : while '//' in block : @@ -384,7 +384,7 @@ BINARY FORMAT block = block[0:s] + block[e:] block = block.replace('\n','').replace(' ','').replace('\t ','') return block - + def readToken(tokenname) : token = tokens[tokenname] datatype = token['type'].lower() @@ -401,7 +401,7 @@ BINARY FORMAT if datatype in templatesConvert : fields = eval( templatesConvert[datatype] ) return fields - + def dXtemplateData(tpl,block,ptr=0) : #print('dxTPL',block[ptr]) pack = [] @@ -422,14 +422,14 @@ BINARY FORMAT else : length = 1 datavalue, ptr = dXdata(block, datatype, length, ptr) - + #if len(str(datavalue)) > 50 : dispvalue = str(datavalue[0:25]) + ' [...] ' + str(datavalue[-25:]) #else : dispvalue = str(datavalue) #print('%s : %s %s'%(dataname,dispvalue,type(datavalue))) exec('%s = datavalue'%(dataname)) pack.append( datavalue ) return pack, ptr + 1 - + def dXdata(block,datatype,length,s=0,eof=';') : #print('dxDTA',block[s]) # at last, the data we need @@ -458,7 +458,7 @@ BINARY FORMAT if datatype in templatesConvert : fields = eval( templatesConvert[datatype] ) return fields, ptr - + def dXarray(block, datatype, length, s=0) : #print('dxARR',block[s]) lst = [] @@ -468,7 +468,7 @@ BINARY FORMAT if i+1 == length : eoi = ';' datavalue, s = dXdata(block,datatype,1,s,eoi) lst.append( datavalue ) - + else : eoi = ';,' for i in range(length) : @@ -480,7 +480,7 @@ BINARY FORMAT lst.append( datavalue ) s = e + 2 return lst, s - + ################################################### ## populate a template with its datas @@ -495,7 +495,7 @@ BINARY FORMAT go = True while go : lines, trunkated = nextFileChunk(data,trunkated,chunksize) # stream ? - if lines == None : + if lines == None : break for l in lines : #l = data.readline().decode().strip() @@ -503,21 +503,21 @@ BINARY FORMAT if '}' in l : go = False break - + uuid = re.search(r'<.+>',block).group() templates[tpl_name]['uuid'] = uuid.lower() templates[tpl_name]['members'] = [] templates[tpl_name]['restriction'] = 'closed' - + members = re.search(r'>.+',block).group()[1:-1].split(';') for member in members : if member == '' : continue if member[0] == '[' : templates[tpl_name]['restriction'] = member - continue + continue templates[tpl_name]['members'].append( member.split(' ') ) - - if display : + + if display : print('\ntemplate %s :'%tpl_name) for k,v in templates[tpl_name].items() : if k != 'members' : @@ -525,7 +525,7 @@ BINARY FORMAT else : for member in v : print(' %s'%str(member)[1:-1].replace(',',' ').replace("'",'')) - + if tpl_name in defaultTemplates : defaultTemplates[tpl_name]['line'] = templates[tpl_name]['line'] defaultTemplates[tpl_name]['pointer'] = templates[tpl_name]['pointer'] @@ -543,8 +543,8 @@ BINARY FORMAT # print(' %s'%str(member)[1:-1].replace(',',' ').replace("'",'')) else : print('MATCHES BUILTIN TEMPLATE') - - + + ## read any kind of token data block # by default the block is cleaned from inline comment space etc to allow data parsing # useclean = False (retrieve all bytes) if you need to compute a file byte pointer @@ -572,7 +572,7 @@ BINARY FORMAT block = block[s:e] if clean : block = cleanBlock(block) return block - + def getChilds(tokenname) : childs = [] # '*' in childname means it's a reference. always perform this test @@ -581,12 +581,12 @@ BINARY FORMAT if childname[0] == '*' : childname = childname[1:] childs.append( childname ) return childs - + # the input nested list of [bonename, matrix, [child0,child1..]] is given by import_dXtree() def buildArm(armdata, child,lvl=0,parent_matrix=False) : - + bonename, bonemat, bonechilds = child - + if lvl == 0 : armname = armdata armdata = bpy.data.armatures.new(name=armname) @@ -596,7 +596,7 @@ BINARY FORMAT bpy.context.scene.objects.active = arm bpy.ops.object.mode_set(mode='EDIT') parent_matrix = Matrix() - + bone = armdata.edit_bones.new(name=bonename) bonematW = parent_matrix * bonemat bone.head = bonematW.to_translation() @@ -611,10 +611,10 @@ BINARY FORMAT bpy.ops.object.mode_set(mode='OBJECT') return arm return bone - + def import_dXtree(field,lvl=0) : tab = ' '*lvl*2 - if field == [] : + if field == [] : if show_geninfo : print('%s>> no childs, return False'%(tab)) return False ob = False @@ -622,14 +622,14 @@ BINARY FORMAT is_root = False frames = [] obs = [] - + parentname = tokens[field[0]]['parent'] if show_geninfo : print('%s>>childs in frame %s :'%(tab,parentname)) - + for tokenname in field : tokentype = tokens[tokenname]['type'] - + # frames can contain more than one mesh if tokentype == 'mesh' : # object and mesh naming : @@ -638,35 +638,35 @@ BINARY FORMAT if parentname : meshcount = 0 for child in getChilds(parentname) : - if tokens[child]['type'] == 'mesh' : + if tokens[child]['type'] == 'mesh' : meshcount += 1 if meshcount == 2 : parentname = tokenname break else : parentname = tokenname - + ob = getMesh(parentname,tokenname) obs.append(ob) if show_geninfo : print('%smesh : %s'%(tab,tokenname)) - + # frames contain one matrix (empty or bone) elif tokentype == 'frametransformmatrix' : [mat] = readToken(tokenname) if show_geninfo : print('%smatrix : %s'%(tab,tokenname)) - + # frames can contain 0 or more frames elif tokentype == 'frame' : frames.append(tokenname) if show_geninfo : print('%sframe : %s'%(tab,tokenname)) - - # matrix is used for mesh transform if some mesh(es) exist(s) + + # matrix is used for mesh transform if some mesh(es) exist(s) if ob : is_root = True if mat == False : mat = Matrix() if show_geninfo : print('%smesh token without matrix, set it to default\n%splease report in bug tracker if you read this !'%(tab,tab)) - if parentname == '' : + if parentname == '' : mat = mat * global_matrix if len(obs) == 1 : ob.matrix_world = mat @@ -675,7 +675,7 @@ BINARY FORMAT ob.matrix_world = mat for child in obs : child.parent = ob - + # matrix only, store it as a list as we don't know if # it's a bone or an empty yet elif mat : @@ -687,25 +687,25 @@ BINARY FORMAT if show_geninfo : print('%snothing here'%(tab)) childs = [] - + for tokenname in frames : if show_geninfo : print('%s<Begin %s :'%(tab,tokenname)) - + # child is either False, empty, object, or a list or undefined name matrices hierarchy child = import_dXtree(getChilds(tokenname),lvl+1) if child and type(child) != list : is_root = True childs.append( [tokenname, child] ) if show_geninfo : print('%sEnd %s>'%(tab,tokenname)) - + if is_root and parentname != '' : - + if show_geninfo : print('%send of tree a this point'%(tab)) if type(ob) == list : mat = ob[1] ob = bel.ob.new(parentname, None, naming_method) ob.matrix_world = mat - + for tokenname, child in childs : if show_geninfo : print('%sbegin2 %s>'%(tab,tokenname)) # returned a list of object(s) or matrice(s) @@ -718,14 +718,14 @@ BINARY FORMAT if type(child) == list : if show_geninfo : print('%sconvert to armature %s'%(tab,tokenname)) child = buildArm(tokenname, child) - + # parent the obj/empty/arm to current # or apply the global user defined matrix to the object root if parentname != '' : child.parent = ob else : child.matrix_world = global_matrix - + # returned a list of parented matrices. append it in childs list elif type(child[0]) == str : ob[2].append(child) @@ -735,7 +735,7 @@ BINARY FORMAT #print(' child data type: %s'%type(child.data)) child.parent = ob #print('%s parented to %s'%(child.name,ob.name)) - + # returned False else : if show_geninfo : print('%sreturned %s, nothing'%(tab,child)) @@ -745,9 +745,9 @@ BINARY FORMAT # build from mesh token type def getMesh(obname,tokenname,debug = False): - + if debug : print('\nmesh name : %s'%tokenname) - + verts = [] edges = [] faces = [] @@ -758,36 +758,36 @@ BINARY FORMAT groupindices = [] groupweights = [] - nVerts, verts, nFaces, faces = readToken(tokenname) + nVerts, verts, nFaces, faces = readToken(tokenname) if debug : print('verts : %s %s\nfaces : %s %s'%(nVerts, len(verts),nFaces, len(faces))) - + #for childname in token['childs'] : for childname in getChilds(tokenname) : - + tokentype = tokens[childname]['type'] - + # UV if tokentype == 'meshtexturecoords' : uv = readToken(childname) #uv = bel.uv.asVertsLocation(uv, faces) uv = bel.uv.asFlatList(uv, faces) uvs.append(uv) - + if debug : print('uv : %s'%(len(uv))) - + # MATERIALS elif tokentype == 'meshmateriallist' : nbslots, facemats = readToken(childname) - + if debug : print('facemats : %s'%(len(facemats))) - + # mat can exist but with no datas so we prepare the mat slot # with dummy ones for slot in range(nbslots) : matslots.append('dXnoname%s'%slot ) - + # length does not match (could be tuned more, need more cases) if len(facemats) != len(faces) : facemats = [ facemats[0] for i in faces ] @@ -795,14 +795,14 @@ BINARY FORMAT # seek for materials then textures if any mapped in this mesh. # no type test, only one option type in token meshmateriallist : 'Material' for slotid, matname in enumerate(getChilds(childname)) : - + # rename dummy mats with the right name matslots[slotid] = matname # blender material creation (need tuning) mat = bel.material.new(matname,naming_method) matslots[slotid] = mat.name - + if naming_method != 1 : #print('matname : %s'%matname) (diffuse_color,alpha), power, specCol, emitCol = readToken(matname) @@ -811,9 +811,9 @@ BINARY FORMAT mat.diffuse_intensity = power mat.specular_color = specCol # dX emit don't use diffuse color but is a color itself - # convert it to a kind of intensity + # convert it to a kind of intensity mat.emit = (emitCol[0] + emitCol[1] + emitCol[2] ) / 3 - + if alpha != 1.0 : mat.use_transparency = True mat.transparency_method = 'Z_TRANSPARENCY' @@ -821,29 +821,29 @@ BINARY FORMAT mat.specular_alpha = 0 transp = True else : transp = False - + # texture # only 'TextureFilename' can be here, no type test - # textures have no name in .x so we build + # textures have no name in .x so we build # image and texture names from the image file name # bdata texture slot name = bdata image name btexnames = [] for texname in getChilds(matname) : - + # create/rename/reuse etc corresponding data image # (returns False if not found) [filename] = readToken(texname) img = bel.image.new(path+'/'+filename) - + if img == False : imgname = 'not_found' else : imgname = img.name - + #print('texname : %s'%texname) #print('filename : %s'%filename) #print('btex/img name : %s'%imgname) - + # associated texture (no naming check.. maybe tune more) # tex and texslot are created even if img not found if imgname in bpy.data.textures and ( img == False or bpy.data.textures[imgname].image == img ) : @@ -851,10 +851,10 @@ BINARY FORMAT else : tex = bpy.data.textures.new(name=imgname,type='IMAGE') if img : tex.image = img - + tex.use_alpha = transp tex.use_preview_alpha = transp - + # then create texture slot texslot = mat.texture_slots.create(index=0) texslot.texture = tex @@ -868,35 +868,35 @@ BINARY FORMAT if matname not in bpy.data.materials : mat = bel.material.new(matname,naming_method) matslots[slotid] = mat.name - + if debug : print('matslots : %s'%matslots) - + # VERTICES GROUPS/WEIGHTS elif tokentype == 'skinweights' : groupname, nverts, vindices, vweights, mat = readToken(childname) groupname = namelookup[groupname] - if debug : + if debug : print('vgroup : %s (%s/%s verts) %s'%(groupname,len(vindices),len(vweights),'bone' if groupname in tokens else '')) #if debug : print('matrix : %s\n%s'%(type(mat),mat)) - + groupnames.append(groupname) groupindices.append(vindices) groupweights.append(vweights) - - ob = bel.mesh.write(obname,tokenname, - verts, edges, faces, - matslots, facemats, uvs, + + ob = bel.mesh.write(obname,tokenname, + verts, edges, faces, + matslots, facemats, uvs, groupnames, groupindices, groupweights, use_smooth_groups, naming_method) - + return ob - + ## here we go - + file = os.path.basename(filepath) - + print('\nimporting %s...'%file) start = time.clock() path = os.path.dirname(filepath) @@ -909,7 +909,7 @@ BINARY FORMAT if header : minor, major, format, accuracy = header - + if show_geninfo : print('\n%s directX header'%file) print(' minor : %s'%(minor)) @@ -934,9 +934,9 @@ BINARY FORMAT if show_tree : print('\nDirectX Data Tree :\n') walk_dXtree(tokens.keys()) - + ## DATA IMPORTATION - if show_geninfo : + if show_geninfo : #print(tokens) print('Root frames :\n %s'%rootTokens) if parented : @@ -950,7 +950,7 @@ BINARY FORMAT if obname : meshcount = 0 for child in getChilds(obname) : - if tokens[child]['type'] == 'mesh' : + if tokens[child]['type'] == 'mesh' : meshcount += 1 if meshcount == 2 : obname = tokenname @@ -959,13 +959,12 @@ BINARY FORMAT ob = getMesh(obname,tokenname,show_geninfo) ob.matrix_world = global_matrix - + print('done in %.2f\''%(time.clock()-start)) # ,end='\r') - + else : print('only .x files in text format are currently supported') print('please share your file to make the importer evolve') return {'FINISHED'} - \ No newline at end of file diff --git a/io_import_BrushSet.py b/io_import_BrushSet.py index 0abe7edddd9ef76e11e24da9df8bc5bd73568ccc..fd8cfe430e4ed2f385f016f279befa8b3eacba02 100644 --- a/io_import_BrushSet.py +++ b/io_import_BrushSet.py @@ -104,18 +104,18 @@ class BrushSetImporter(bpy.types.Operator): bl_idname = "import_image.brushset" bl_label = "Import BrushSet" - filename = StringProperty(name = "File Name", - description = "filepath", - default = "", - maxlen = 1024, - options = {'ANIMATABLE'}, + filename = StringProperty(name = "File Name", + description = "filepath", + default = "", + maxlen = 1024, + options = {'ANIMATABLE'}, subtype = 'NONE') - - filepath = StringProperty(name = "File Name", - description = "filepath", - default = "", - maxlen = 1024, - options = {'ANIMATABLE'}, + + filepath = StringProperty(name = "File Name", + description = "filepath", + default = "", + maxlen = 1024, + options = {'ANIMATABLE'}, subtype = 'NONE') def execute(self, context): diff --git a/io_import_sound_to_anim.py b/io_import_sound_to_anim.py index 9c3b54605e2554b8f6e0d58d9c48576814f21a86..851da57a734cda81d1e986e31f03e51137d50e5c 100644 --- a/io_import_sound_to_anim.py +++ b/io_import_sound_to_anim.py @@ -1924,7 +1924,3 @@ def unregister(): if __name__ == "__main__": register() - - - - diff --git a/io_mesh_gwyddion/import_gwyddion.py b/io_mesh_gwyddion/import_gwyddion.py index 896a3f3aae33fa3909a2808dbcfed34a125ffd86..f880d158f01f586904ba95eda40283dfe027cd48 100644 --- a/io_mesh_gwyddion/import_gwyddion.py +++ b/io_mesh_gwyddion/import_gwyddion.py @@ -26,12 +26,12 @@ import struct # All data for the images. Basically, each variable is a list with a length, # which equals the number of images. # Some of the variables are still not used. However, I keep them for purposes -# in future. +# in future. class AFMData(object): - def __init__(self, date, x_size, y_size, x_pixel, y_pixel, x_off, y_off, - voltage, feedback, gain, speed, amplitude, angle, datfile, - channel, unit, z_factor, spec_x_unit, spec_x_label, spec_y_unit, - spec_y_label, spec_y_factor, spec_points, spec_feedback, + def __init__(self, date, x_size, y_size, x_pixel, y_pixel, x_off, y_off, + voltage, feedback, gain, speed, amplitude, angle, datfile, + channel, unit, z_factor, spec_x_unit, spec_x_label, spec_y_unit, + spec_y_label, spec_y_factor, spec_points, spec_feedback, spec_acquisition, spec_delay): self.date = date self.x_size = x_size @@ -50,58 +50,58 @@ class AFMData(object): self.channel = channel self.unit = unit self.z_factor = z_factor - self.spec_x_unit = spec_x_unit - self.spec_x_label = spec_x_label + self.spec_x_unit = spec_x_unit + self.spec_x_label = spec_x_label self.spec_y_unit = spec_y_unit self.spec_y_label = spec_y_label - self.spec_y_factor = spec_y_factor + self.spec_y_factor = spec_y_factor self.spec_points = spec_points self.spec_feedback = spec_feedback self.spec_acquisition = spec_acquisition - self.spec_delay = spec_delay - + self.spec_delay = spec_delay -# For loading the Gwyddion images. I basically have followed rules described + +# For loading the Gwyddion images. I basically have followed rules described # here: http://gwyddion.net/documentation/user-guide-en/gwyfile-format.html def load_gwyddion_images(data_file, channels): - + if not os.path.isfile(data_file): - return False + return False AFMdata = AFMData([],[],[],[],[],[],[], [],[],[],[],[],[],[], [],[],[],[],[],[],[], [],[],[],[],[]) AFMdata.datfile = data_file - + datafile = open(data_file, 'rb') data = datafile.read() - datafile.close() - + datafile.close() + # Search the title of each image - for a in list(re.finditer(b"data/title\x00", data)): - + for a in list(re.finditer(b"data/title\x00", data)): + pos = a.start() channel_number = int(data[pos-2:pos-1]) - + if channels[channel_number] == False: continue - + pos1 = data[pos:].find(b"\x00") + pos + len("\x00") + 1 pos2 = data[pos1:].find(b"\x00") + pos1 channel_name = data[pos1:pos2].decode("utf-8") - - AFMdata.channel.append([channel_number, channel_name]) - - # Search important parameters and finally the image data. - images = [] + + AFMdata.channel.append([channel_number, channel_name]) + + # Search important parameters and finally the image data. + images = [] for a in list(re.finditer(b"/data\x00", data)): - - pos = a.start() + + pos = a.start() channel_number = int(data[pos-1:pos]) - + if channels[channel_number] == False: continue @@ -122,16 +122,16 @@ def load_gwyddion_images(data_file, channels): size_y_real = struct.unpack("d",data[pos1+2:pos1+8+2])[0] # If it is a z image, multiply with 10^9 nm - factor = 1.0 + factor = 1.0 pos1 = data[pos:].find(b"si_unit_z") + pos unit = data[pos1+34:pos1+36].decode("utf-8") if "m" in unit: factor = 1000000000.0 - + # Now, find the image data and store it pos1 = data[pos:].find(b"\x00data\x00") + pos + len("\x00data\x00") + 5 - image = [] + image = [] for i in range(size_y_pixel): line = [] for j in range(size_x_pixel): @@ -139,47 +139,47 @@ def load_gwyddion_images(data_file, channels): k = pos1 + (i*size_x_pixel+j) * 8 l = pos1 + (i*size_x_pixel+j+1) * 8 line.append(struct.unpack("d",data[k:l])[0]*factor) - image.append(line) - + image.append(line) + images.append(image) - + # Note all parameters of the image. AFMdata.x_pixel.append(int(size_x_pixel)) AFMdata.y_pixel.append(int(size_y_pixel)) AFMdata.x_size.append(size_x_real * 1000000000.0) AFMdata.y_size.append(size_y_real * 1000000000.0) - + return (images, AFMdata) # Routine to create the mesh and finally the image -def create_mesh(data_list, - AFMdata, - use_smooth, +def create_mesh(data_list, + AFMdata, + use_smooth, scale_size, scale_height, use_camera, use_lamp): - # This is for the image name. - path_list = AFMdata.datfile.strip('/').split('/') + # This is for the image name. + path_list = AFMdata.datfile.strip('/').split('/') number_img = len(data_list) image_x_offset_gap = 10.0 * scale_size - image_x_all = sum(AFMdata.x_size)*scale_size + image_x_all = sum(AFMdata.x_size)*scale_size image_x_offset = -(image_x_all+image_x_offset_gap*(number_img-1)) / 2.0 - + # For each image do: for k, data in enumerate(data_list): - + size_x = AFMdata.x_pixel[k] size_y = AFMdata.y_pixel[k] - - image_scale = AFMdata.x_size[k] / float(AFMdata.x_pixel[k]) - image_scale = image_scale * scale_size - image_x_size = AFMdata.x_size[k] * scale_size + + image_scale = AFMdata.x_size[k] / float(AFMdata.x_pixel[k]) + image_scale = image_scale * scale_size + image_x_size = AFMdata.x_size[k] * scale_size image_x_offset += image_x_size / 2.0 - + image_name = path_list[-1] + "_" + AFMdata.channel[k][1] - + data_mesh = [] data_faces = [] @@ -187,27 +187,27 @@ def create_mesh(data_list, for i, line in enumerate(data): for j, pixel in enumerate(line): - + # The vertices - data_mesh.append(Vector((float(i) * image_scale, - float(j) * image_scale, + data_mesh.append(Vector((float(i) * image_scale, + float(j) * image_scale, float(pixel)*scale_height))) - + # The faces if i < size_y-1 and j < size_x-1: - data_faces.append( [size_x*i+j , size_x*(i+1)+j, - size_x*(i+1)+j+1, size_x*i+j+1 ]) + data_faces.append( [size_x*i+j , size_x*(i+1)+j, + size_x*(i+1)+j+1, size_x*i+j+1 ]) #print("passed - create_mesh ---- 2") - + # Build the mesh surface_mesh = bpy.data.meshes.new("Mesh") surface_mesh.from_pydata(data_mesh, [], data_faces) surface_mesh.update() surface = bpy.data.objects.new(image_name, surface_mesh) bpy.context.scene.objects.link(surface) - bpy.ops.object.select_all(action='DESELECT') - surface.select = True + bpy.ops.object.select_all(action='DESELECT') + surface.select = True bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY') # sum((v.co for v in mesh.vertices), Vector()) / len(mesh.vertices) @@ -216,21 +216,21 @@ def create_mesh(data_list, for polygon in surface.data.polygons: polygon.use_smooth = True - surface.location = Vector((0.0, image_x_offset, 0.0)) + surface.location = Vector((0.0, image_x_offset, 0.0)) image_x_offset += image_x_size / 2.0 + image_x_offset_gap #print("passed - create_mesh ---- 3") - + object_center_vec = Vector((0.0,0.0,0.0)) - object_size = (sum(AFMdata.x_size) * scale_size + object_size = (sum(AFMdata.x_size) * scale_size +image_x_offset_gap * (len(data_list)-1)) # ------------------------------------------------------------------------ # CAMERA AND LAMP camera_factor = 20.0 - + # If chosen a camera is put into the scene. if use_camera == True: @@ -245,14 +245,14 @@ def create_mesh(data_list, camera_xyz_vec = object_center_vec + object_camera_vec # Create the camera - current_layers=bpy.context.scene.layers + current_layers=bpy.context.scene.layers camera_data = bpy.data.cameras.new("A_camera") camera_data.lens = 45 camera_data.clip_end = 50000.0 camera = bpy.data.objects.new("A_camera", camera_data) camera.location = camera_xyz_vec camera.layers = current_layers - bpy.context.scene.objects.link(camera) + bpy.context.scene.objects.link(camera) # Here the camera is rotated such it looks towards the center of # the object. The [0.0, 0.0, 1.0] vector along the z axis @@ -267,8 +267,8 @@ def create_mesh(data_list, # Rotate the camera around its axis by 90° such that we have a nice # camera position and view onto the object. - bpy.ops.object.select_all(action='DESELECT') - camera.select = True + bpy.ops.object.select_all(action='DESELECT') + camera.select = True bpy.ops.transform.rotate(value=(90.0*2*pi/360.0), axis=object_camera_vec, constraint_axis=(False, False, False), @@ -299,11 +299,11 @@ def create_mesh(data_list, lamp_data = bpy.data.lamps.new(name="A_lamp", type="POINT") lamp_data.distance = 5000.0 lamp_data.energy = 3.0 - lamp_data.shadow_method = 'RAY_SHADOW' + lamp_data.shadow_method = 'RAY_SHADOW' lamp = bpy.data.objects.new("A_lamp", lamp_data) lamp.location = lamp_xyz_vec lamp.layers = current_layers - bpy.context.scene.objects.link(lamp) + bpy.context.scene.objects.link(lamp) bpy.context.scene.world.light_settings.use_ambient_occlusion = True - bpy.context.scene.world.light_settings.ao_factor = 0.1 + bpy.context.scene.world.light_settings.ao_factor = 0.1 diff --git a/io_mesh_xyz/export_xyz.py b/io_mesh_xyz/export_xyz.py index 093d6e91361592d7ee08041b4a0f8ca43d43a7e1..eba9273c0ebf5fc4bad32439fcfa346a32a7a1ac 100644 --- a/io_mesh_xyz/export_xyz.py +++ b/io_mesh_xyz/export_xyz.py @@ -20,7 +20,7 @@ import bpy from . import import_xyz -class AtomsExport(object): +class AtomsExport(object): __slots__ = ('element', 'location') def __init__(self, element, location): self.element = element @@ -32,13 +32,13 @@ def export_xyz(obj_type, filepath_xyz): list_atoms = [] counter = 0 for obj in bpy.context.selected_objects: - + if "Stick" in obj.name: continue - + if obj.type not in {'MESH', 'SURFACE', 'META'}: - continue - + continue + name = "" for element in import_xyz.ELEMENTS_DEFAULT: if element[1] in obj.name: @@ -46,7 +46,7 @@ def export_xyz(obj_type, filepath_xyz): name = "X" else: name = element[2] - + if name == "": if obj_type == "0": name = "?" @@ -57,12 +57,12 @@ def export_xyz(obj_type, filepath_xyz): for vertex in obj.data.vertices: location = obj.matrix_world*vertex.co list_atoms.append(AtomsExport(name, location)) - counter += 1 + counter += 1 else: if not obj.parent: location = obj.location - list_atoms.append(AtomsExport(name, location)) - counter += 1 + list_atoms.append(AtomsExport(name, location)) + counter += 1 xyz_file_p = open(filepath_xyz, "w") xyz_file_p.write("%d\n" % counter) @@ -82,4 +82,3 @@ def export_xyz(obj_type, filepath_xyz): xyz_file_p.close() return True - diff --git a/io_mesh_xyz/import_xyz.py b/io_mesh_xyz/import_xyz.py index 9a575f233bb0a50bb974eeff7be354922ad62ad5..eedd5c3eba779232e0c28ef3308a7b85dc1c32ec 100644 --- a/io_mesh_xyz/import_xyz.py +++ b/io_mesh_xyz/import_xyz.py @@ -153,8 +153,8 @@ ELEMENTS_DEFAULT = ( # custom data file for instance. ELEMENTS = [] -# This is the list, which contains all atoms of all frames! Each item is a -# list which contains the atoms of a single frame. It is a list of +# This is the list, which contains all atoms of all frames! Each item is a +# list which contains the atoms of a single frame. It is a list of # 'AtomProp'. ALL_FRAMES = [] @@ -174,7 +174,7 @@ class ElementProp(object): self.radii_ionic = radii_ionic # This is the class, which stores the properties of one atom. -class AtomProp(object): +class AtomProp(object): __slots__ = ('element', 'name', 'location', 'radius', 'color', 'material') def __init__(self, element, name, location, radius, color, material): self.element = element @@ -186,7 +186,7 @@ class AtomProp(object): # ----------------------------------------------------------------------------- -# Some basic routines +# Some basic routines def read_elements(): @@ -230,12 +230,12 @@ def read_xyz_file(filepath_xyz,radiustype): if len(split_list) == 1: number_atoms = int(split_list[0]) FLAG = True - + if FLAG == True: - + line = filepath_xyz_p.readline() line = line.rstrip() - + all_atoms= [] for i in range(number_atoms): @@ -246,18 +246,18 @@ def read_xyz_file(filepath_xyz,radiustype): # may increase (or decrease). If it decreases, the addon crashes. # If it increases, only the tot number of atoms of the first frame # is used. - # By time, I will allow varying atom numbers ... but this takes - # some time ... + # By time, I will allow varying atom numbers ... but this takes + # some time ... if number_frames != 0: if i >= total_number_atoms: break - - + + line = filepath_xyz_p.readline() line = line.rstrip() split_list = line.rsplit() short_name = str(split_list[0]) - + # Go through all elements and find the element of the current atom. FLAG_FOUND = False for element in ELEMENTS: @@ -270,7 +270,7 @@ def read_xyz_file(filepath_xyz,radiustype): color = element.color FLAG_FOUND = True break - + # Is it a vacancy or an 'unknown atom' ? if FLAG_FOUND == False: # Give this atom also a name. If it is an 'X' then it is a @@ -287,44 +287,44 @@ def read_xyz_file(filepath_xyz,radiustype): name = str.upper(short_name) radius = float(ELEMENTS[-2].radii[int(radiustype)]) color = ELEMENTS[-2].color - + x = float(split_list[1]) y = float(split_list[2]) z = float(split_list[3]) - + location = Vector((x,y,z)) - + all_atoms.append([short_name, name, location, radius, color]) - - # We note here all elements. This needs to be done only once. + + # We note here all elements. This needs to be done only once. if number_frames == 0: - + # This is a guarantee that only the total number of atoms of the # first frame is used. Condition is, so far, that the number of # atoms in a xyz file is constant. However, sometimes the number # may increase (or decrease). If it decreases, the addon crashes. # If it increases, only the tot number of atoms of the first frame # is used. - # By time, I will allow varying atom numbers ... but this takes + # By time, I will allow varying atom numbers ... but this takes # some time ... total_number_atoms = number_atoms - - + + elements = [] for atom in all_atoms: FLAG_FOUND = False for element in elements: - # If the atom name is already in the list, + # If the atom name is already in the list, # FLAG on 'True'. if element == atom[1]: FLAG_FOUND = True break # No name in the current list has been found? => New entry. if FLAG_FOUND == False: - # Stored are: Atom label (e.g. 'Na'), the corresponding + # Stored are: Atom label (e.g. 'Na'), the corresponding # atom name (e.g. 'Sodium') and its color. elements.append(atom[1]) - + # Sort the atoms: create lists of atoms of one type structure = [] for element in elements: @@ -343,7 +343,7 @@ def read_xyz_file(filepath_xyz,radiustype): FLAG = False filepath_xyz_p.close() - + return total_number_atoms @@ -356,7 +356,7 @@ def import_xyz(Ball_type, Ball_radius_factor, radiustype, Ball_distance_factor, - put_to_center, + put_to_center, put_to_center_all, use_camera, use_lamp, @@ -373,9 +373,9 @@ def import_xyz(Ball_type, # ------------------------------------------------------------------------ # READING DATA OF ATOMS - Number_of_total_atoms = read_xyz_file(filepath_xyz, + Number_of_total_atoms = read_xyz_file(filepath_xyz, radiustype) - + # We show the atoms of the first frame. first_frame = ALL_FRAMES[0] @@ -441,7 +441,7 @@ def import_xyz(Ball_type, if put_to_center_all == True: # For all frames - for frame in ALL_FRAMES: + for frame in ALL_FRAMES: sum_vec = Vector((0.0,0.0,0.0)) @@ -454,7 +454,7 @@ def import_xyz(Ball_type, # may increase (or decrease). If it decreases, the addon crashes. # If it increases, only the tot number of atoms of the first frame # is used. - # By time, I will allow varying atom numbers ... but this takes + # By time, I will allow varying atom numbers ... but this takes # some time ... if i >= Number_of_total_atoms: break @@ -469,7 +469,7 @@ def import_xyz(Ball_type, for atom in atoms_of_one_type: atom.location -= sum_vec - + # ------------------------------------------------------------------------ # SCALING @@ -477,7 +477,7 @@ def import_xyz(Ball_type, for atoms_of_one_type in first_frame: for atom in atoms_of_one_type: atom.location *= Ball_distance_factor - + # ------------------------------------------------------------------------ # DETERMINATION OF SOME GEOMETRIC PROPERTIES @@ -521,14 +521,14 @@ def import_xyz(Ball_type, camera_xyz_vec = object_center_vec + object_camera_vec # Create the camera - current_layers=bpy.context.scene.layers + current_layers=bpy.context.scene.layers camera_data = bpy.data.cameras.new("A_camera") camera_data.lens = 45 camera_data.clip_end = 500.0 camera = bpy.data.objects.new("A_camera", camera_data) camera.location = camera_xyz_vec camera.layers = current_layers - bpy.context.scene.objects.link(camera) + bpy.context.scene.objects.link(camera) # Here the camera is rotated such it looks towards the center of # the object. The [0.0, 0.0, 1.0] vector along the z axis @@ -543,8 +543,8 @@ def import_xyz(Ball_type, # Rotate the camera around its axis by 90° such that we have a nice # camera position and view onto the object. - bpy.ops.object.select_all(action='DESELECT') - camera.select = True + bpy.ops.object.select_all(action='DESELECT') + camera.select = True bpy.ops.transform.rotate(value=(90.0*2*pi/360.0), axis=object_camera_vec, constraint_axis=(False, False, False), @@ -575,15 +575,15 @@ def import_xyz(Ball_type, lamp_data = bpy.data.lamps.new(name="A_lamp", type="POINT") lamp_data.distance = 500.0 lamp_data.energy = 3.0 - lamp_data.shadow_method = 'RAY_SHADOW' + lamp_data.shadow_method = 'RAY_SHADOW' lamp = bpy.data.objects.new("A_lamp", lamp_data) lamp.location = lamp_xyz_vec lamp.layers = current_layers - bpy.context.scene.objects.link(lamp) + bpy.context.scene.objects.link(lamp) bpy.context.scene.world.light_settings.use_ambient_occlusion = True bpy.context.scene.world.light_settings.ao_factor = 0.2 - + # ------------------------------------------------------------------------ # DRAWING THE ATOMS @@ -634,8 +634,8 @@ def import_xyz(Ball_type, layers=current_layers) # Meta balls elif Ball_type == "2": - bpy.ops.object.metaball_add(type='BALL', view_align=False, - enter_editmode=False, location=(0, 0, 0), + bpy.ops.object.metaball_add(type='BALL', view_align=False, + enter_editmode=False, location=(0, 0, 0), rotation=(0, 0, 0), layers=current_layers) ball = bpy.context.scene.objects.active @@ -654,7 +654,7 @@ def import_xyz(Ball_type, # ------------------------------------------------------------------------ # SELECT ALL LOADED OBJECTS - + bpy.ops.object.select_all(action='DESELECT') obj = None for obj in STRUCTURE: @@ -669,71 +669,68 @@ def build_frames(frame_delta, frame_skip): scn = bpy.context.scene - # Introduce the basis for all elements that appear in the structure. + # Introduce the basis for all elements that appear in the structure. for element in STRUCTURE: - - bpy.ops.object.select_all(action='DESELECT') + + bpy.ops.object.select_all(action='DESELECT') bpy.context.scene.objects.active = element element.select = True bpy.ops.object.shape_key_add(True) - - frame_skip += 1 - # Introduce the keys and reference the atom positions for each key. + frame_skip += 1 + + # Introduce the keys and reference the atom positions for each key. i = 0 - for j, frame in enumerate(ALL_FRAMES): - + for j, frame in enumerate(ALL_FRAMES): + if j % frame_skip == 0: - + for elements_frame, elements_structure in zip(frame,STRUCTURE): - + key = elements_structure.shape_key_add() - + for atom_frame, atom_structure in zip(elements_frame, key.data): - - atom_structure.co = (atom_frame.location + + atom_structure.co = (atom_frame.location - elements_structure.location) - - key.name = atom_frame.name + "_frame_" + str(i) + + key.name = atom_frame.name + "_frame_" + str(i) i += 1 num_frames = i - + scn.frame_start = 0 scn.frame_end = frame_delta * num_frames # Manage the values of the keys for element in STRUCTURE: - - scn.frame_current = 0 + + scn.frame_current = 0 element.data.shape_keys.key_blocks[1].value = 1.0 element.data.shape_keys.key_blocks[2].value = 0.0 - element.data.shape_keys.key_blocks[1].keyframe_insert("value") - element.data.shape_keys.key_blocks[2].keyframe_insert("value") + element.data.shape_keys.key_blocks[1].keyframe_insert("value") + element.data.shape_keys.key_blocks[2].keyframe_insert("value") scn.frame_current += frame_delta number = 0 - + for number in range(num_frames)[2:]:#-1]: - + element.data.shape_keys.key_blocks[number-1].value = 0.0 element.data.shape_keys.key_blocks[number].value = 1.0 element.data.shape_keys.key_blocks[number+1].value = 0.0 - element.data.shape_keys.key_blocks[number-1].keyframe_insert("value") - element.data.shape_keys.key_blocks[number].keyframe_insert("value") - element.data.shape_keys.key_blocks[number+1].keyframe_insert("value") - + element.data.shape_keys.key_blocks[number-1].keyframe_insert("value") + element.data.shape_keys.key_blocks[number].keyframe_insert("value") + element.data.shape_keys.key_blocks[number+1].keyframe_insert("value") + scn.frame_current += frame_delta - - number += 1 - - element.data.shape_keys.key_blocks[number].value = 1.0 - element.data.shape_keys.key_blocks[number-1].value = 0.0 - element.data.shape_keys.key_blocks[number].keyframe_insert("value") - element.data.shape_keys.key_blocks[number-1].keyframe_insert("value") - + number += 1 + element.data.shape_keys.key_blocks[number].value = 1.0 + element.data.shape_keys.key_blocks[number-1].value = 0.0 + element.data.shape_keys.key_blocks[number].keyframe_insert("value") + element.data.shape_keys.key_blocks[number-1].keyframe_insert("value") diff --git a/io_points_pcd/__init__.py b/io_points_pcd/__init__.py index 1cf1689a6c9a52bf9b7e6146bb1571c526e3a809..b5ca0dd029e0923cf6bff8defc23a53ee7bf3878 100644 --- a/io_points_pcd/__init__.py +++ b/io_points_pcd/__init__.py @@ -1,130 +1,129 @@ -# ##### BEGIN GPL LICENSE BLOCK ##### -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software Foundation, -# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# ##### END GPL LICENSE BLOCK ##### - -bl_info = { - "name": "PCD", - "author": "Aurel Wildfellner", - "version": (0, 2), - "blender": (2, 57, 0), - "location": "File > Import-Export > Point Cloud Data", - "description": "Imports and Exports PCD (Point Cloud Data) files. PCD files are the default format used by pcl (Point Cloud Library).", - "warning": "", - "wiki_url": "http://wiki.blender.org/index.php?title=Extensions:2.6/Py/Scripts/Import-Export/Point_Cloud_Data_IO", - "tracker_url": "https://developer.blender.org/maniphest/task/edit/form/2/", -# "support": 'OFFICAL', - "category": "Import-Export"} - - -if "bpy" in locals(): - import imp - imp.reload(pcd_utils) -else: - from . import pcd_utils - -import itertools -import os - - -import bpy -from bpy.props import * -from bpy_extras.io_utils import ExportHelper, ImportHelper - - -class ImportPCD(bpy.types.Operator, ImportHelper): - """Load PCD (Point Cloud Data) files""" - bl_idname = "import_points.stl" - bl_label = "Import PCD" - - filename_ext = ".pcd" - - filter_glob = StringProperty(default="*.pcd", options={'HIDDEN'}) - object_name = StringProperty(default="", options={'HIDDEN'}) - - files = CollectionProperty(name="File Path", - description="File path used for importing " - "the PCD file", - type=bpy.types.OperatorFileListElement) - - directory = StringProperty(subtype='DIR_PATH') - - def execute(self, context): - paths = [os.path.join(self.directory, name.name) for name in self.files] - if not paths: - paths.append(self.filepath) - - for path in paths: - - objname = "" - - if self.object_name == "": - # name the object with the filename exluding .pcd - objname = os.path.basename(path)[:-4] - else: - # use name set by calling the operator with the arg - objname = self.object_name - - pcd_utils.import_pcd(path, objname) - - return {'FINISHED'} - - - - -class ExportPCD(bpy.types.Operator, ExportHelper): - """Save PCD (Point Cloud Data) files""" - bl_idname = "export_points.pcd" - bl_label = "Export PCD" - - filename_ext = ".pcd" - - filter_glob = StringProperty(default="*.pcd", options={'HIDDEN'}) - - - def execute(self, context): - pcd_utils.export_pcd(self.filepath) - - return {'FINISHED'} - - - - -def menu_func_import(self, context): - self.layout.operator(ImportPCD.bl_idname, text="Point Cloud Data (.pcd)").filepath = "*.pcd" - - -def menu_func_export(self, context): - self.layout.operator(ExportPCD.bl_idname, text="Point Cloud Data (.pcd)") - - -def register(): - bpy.utils.register_module(__name__) - - bpy.types.INFO_MT_file_import.append(menu_func_import) - bpy.types.INFO_MT_file_export.append(menu_func_export) - - -def unregister(): - bpy.utils.unregister_module(__name__) - - bpy.types.INFO_MT_file_import.remove(menu_func_import) - bpy.types.INFO_MT_file_export.remove(menu_func_export) - - -if __name__ == "__main__": - register() - +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### + +bl_info = { + "name": "PCD", + "author": "Aurel Wildfellner", + "version": (0, 2), + "blender": (2, 57, 0), + "location": "File > Import-Export > Point Cloud Data", + "description": "Imports and Exports PCD (Point Cloud Data) files. PCD files are the default format used by pcl (Point Cloud Library).", + "warning": "", + "wiki_url": "http://wiki.blender.org/index.php?title=Extensions:2.6/Py/Scripts/Import-Export/Point_Cloud_Data_IO", + "tracker_url": "https://developer.blender.org/maniphest/task/edit/form/2/", +# "support": 'OFFICAL', + "category": "Import-Export"} + + +if "bpy" in locals(): + import imp + imp.reload(pcd_utils) +else: + from . import pcd_utils + +import itertools +import os + + +import bpy +from bpy.props import * +from bpy_extras.io_utils import ExportHelper, ImportHelper + + +class ImportPCD(bpy.types.Operator, ImportHelper): + """Load PCD (Point Cloud Data) files""" + bl_idname = "import_points.stl" + bl_label = "Import PCD" + + filename_ext = ".pcd" + + filter_glob = StringProperty(default="*.pcd", options={'HIDDEN'}) + object_name = StringProperty(default="", options={'HIDDEN'}) + + files = CollectionProperty(name="File Path", + description="File path used for importing " + "the PCD file", + type=bpy.types.OperatorFileListElement) + + directory = StringProperty(subtype='DIR_PATH') + + def execute(self, context): + paths = [os.path.join(self.directory, name.name) for name in self.files] + if not paths: + paths.append(self.filepath) + + for path in paths: + + objname = "" + + if self.object_name == "": + # name the object with the filename exluding .pcd + objname = os.path.basename(path)[:-4] + else: + # use name set by calling the operator with the arg + objname = self.object_name + + pcd_utils.import_pcd(path, objname) + + return {'FINISHED'} + + + + +class ExportPCD(bpy.types.Operator, ExportHelper): + """Save PCD (Point Cloud Data) files""" + bl_idname = "export_points.pcd" + bl_label = "Export PCD" + + filename_ext = ".pcd" + + filter_glob = StringProperty(default="*.pcd", options={'HIDDEN'}) + + + def execute(self, context): + pcd_utils.export_pcd(self.filepath) + + return {'FINISHED'} + + + + +def menu_func_import(self, context): + self.layout.operator(ImportPCD.bl_idname, text="Point Cloud Data (.pcd)").filepath = "*.pcd" + + +def menu_func_export(self, context): + self.layout.operator(ExportPCD.bl_idname, text="Point Cloud Data (.pcd)") + + +def register(): + bpy.utils.register_module(__name__) + + bpy.types.INFO_MT_file_import.append(menu_func_import) + bpy.types.INFO_MT_file_export.append(menu_func_export) + + +def unregister(): + bpy.utils.unregister_module(__name__) + + bpy.types.INFO_MT_file_import.remove(menu_func_import) + bpy.types.INFO_MT_file_export.remove(menu_func_export) + + +if __name__ == "__main__": + register() diff --git a/io_points_pcd/pcd_utils.py b/io_points_pcd/pcd_utils.py index c38a14f109b065b4d68b4e833ce65865f8764a9b..b2e94abdad959c74e916a91718e5e335721dbfe6 100644 --- a/io_points_pcd/pcd_utils.py +++ b/io_points_pcd/pcd_utils.py @@ -1,97 +1,95 @@ -# ##### BEGIN GPL LICENSE BLOCK ##### -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software Foundation, -# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# ##### END GPL LICENSE BLOCK ##### - -import bpy - -import os -import subprocess -import tempfile - -from . import pcdparser - - -def create_and_link_mesh(name, points): - """ - Create a blender mesh and object called name from a list of - *points* and link it in the current scene. - """ - - mesh = bpy.data.meshes.new(name) - mesh.from_pydata(points, [], []) - - # update mesh to allow proper display - mesh.validate() - mesh.update() - - scene = bpy.context.scene - - obj = bpy.data.objects.new(name, mesh) - scene.objects.link(obj) - obj.select = True - - -def import_pcd(filepath, name="new_pointcloud"): - # check if the file is binary compressed - parser = pcdparser.PCDParser.factory(filepath, pcdparser.PointXYZ) - parser.onlyParseHeader() - is_binary_compressed = parser.datatype == 'BINARY_COMPRESSED' - - # create a temp uncompressed pcd file - if (is_binary_compressed): - tmpdir = tempfile.TemporaryDirectory() - tmpfilepath = tmpdir.name + "blender_pcd_io_tmp.pcd" - try: - subprocess.call(["pcl_convert_pcd_ascii_binary", filepath, tmpfilepath, "1"]) - except FileNotFoundError: - print("[ERROR] Can't read BINARY COMPRESSED PCD. No pcl_convert_pcd_ascii_binary found! Have you installed libPCL?") - return - filepath = tmpfilepath - - - # do actual parsing - parser = pcdparser.PCDParser.factory(filepath, pcdparser.PointXYZ) - parser.parseFile() - points = parser.getPoints() - - blender_points = [] - for point in points: - blender_points.append((point.x, point.y, point.z)) - - create_and_link_mesh(name, blender_points) - - -def export_pcd(filepath): - obj = bpy.context.active_object - - # apply object transformation and modifiers - mesh = obj.to_mesh(bpy.context.scene, True, "PREVIEW") - objmat = obj.matrix_world - - points = [] - for vert in mesh.vertices: - co = objmat * vert.co - point = pcdparser.PointXYZ() - point.x = co.x - point.y = co.y - point.z = co.z - points.append(point) - - writer = pcdparser.PCDWriter(points) - writer.write(filepath) - - +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### + +import bpy + +import os +import subprocess +import tempfile + +from . import pcdparser + + +def create_and_link_mesh(name, points): + """ + Create a blender mesh and object called name from a list of + *points* and link it in the current scene. + """ + + mesh = bpy.data.meshes.new(name) + mesh.from_pydata(points, [], []) + + # update mesh to allow proper display + mesh.validate() + mesh.update() + + scene = bpy.context.scene + + obj = bpy.data.objects.new(name, mesh) + scene.objects.link(obj) + obj.select = True + + +def import_pcd(filepath, name="new_pointcloud"): + # check if the file is binary compressed + parser = pcdparser.PCDParser.factory(filepath, pcdparser.PointXYZ) + parser.onlyParseHeader() + is_binary_compressed = parser.datatype == 'BINARY_COMPRESSED' + + # create a temp uncompressed pcd file + if (is_binary_compressed): + tmpdir = tempfile.TemporaryDirectory() + tmpfilepath = tmpdir.name + "blender_pcd_io_tmp.pcd" + try: + subprocess.call(["pcl_convert_pcd_ascii_binary", filepath, tmpfilepath, "1"]) + except FileNotFoundError: + print("[ERROR] Can't read BINARY COMPRESSED PCD. No pcl_convert_pcd_ascii_binary found! Have you installed libPCL?") + return + filepath = tmpfilepath + + + # do actual parsing + parser = pcdparser.PCDParser.factory(filepath, pcdparser.PointXYZ) + parser.parseFile() + points = parser.getPoints() + + blender_points = [] + for point in points: + blender_points.append((point.x, point.y, point.z)) + + create_and_link_mesh(name, blender_points) + + +def export_pcd(filepath): + obj = bpy.context.active_object + + # apply object transformation and modifiers + mesh = obj.to_mesh(bpy.context.scene, True, "PREVIEW") + objmat = obj.matrix_world + + points = [] + for vert in mesh.vertices: + co = objmat * vert.co + point = pcdparser.PointXYZ() + point.x = co.x + point.y = co.y + point.z = co.z + points.append(point) + + writer = pcdparser.PCDWriter(points) + writer.write(filepath) diff --git a/io_points_pcd/pcdparser.py b/io_points_pcd/pcdparser.py index 269cf15e62badb080374901d605832450862f698..78277856d5dbdd201ecbf1caa88f2c31219de11c 100644 --- a/io_points_pcd/pcdparser.py +++ b/io_points_pcd/pcdparser.py @@ -1,419 +1,418 @@ -# ##### BEGIN GPL LICENSE BLOCK ##### -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software Foundation, -# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# ##### END GPL LICENSE BLOCK ##### - - -import struct -import io - -try: - import lzf - GOT_LZF_MODULE=True -except: - GOT_LZF_MODULE=False - - - -def dumpHexData(data): - for byte in data: - print(hex(byte) + " ", end="") - print() - - -def encodeASCIILine(line): - return line.decode(encoding='ASCII') - - - -class Point: - - def __init__(self): - pass - - - def setField(self, fieldname, values): - pass - - - - -class PointXYZ(Point): - - def __init__(self): - super().__init__() - self.x = 0 - self.y = 0 - self.z = 0 - - - def setField(self, fieldname, values): - value = values[0] - if fieldname == 'x': - self.x = value - elif fieldname == 'y': - self.y = value - elif fieldname == 'z': - self.z = value - - - - -class PCDParser: - - filepath = '' - file = None - - points = [] - PointClass = None - - headerEnd = False - - - @staticmethod - def factory(filepath, PointClass): - version = 'NO_VERSION_NUMBER' - with open(filepath, 'rb') as f: - for b in f: - line = encodeASCIILine(b) - line_split = line.split() - if line_split[0] == 'VERSION' and len(line_split) > 1: - version = line_split[1] - break - - if version == ".7" or version == "0.7": - return PCDParser_v0_7(filepath, PointClass) - else: - return None - - - def __init__(self, filepath, PointClass): - self.filepath = filepath - self.PointClass = PointClass - - self.file = None - self.headerEnd = False - self.points = [] - - - def parserWarning(self, msg): - print("[WARNING] ", msg) - - - def rmComment(self, line): - return line[:line.find('#')] - - - def parseFile(self): - with open(self.filepath, 'rb') as self.file: - self.parseHeader() - self.parsePoints() - - def onlyParseHeader(self): - with open(self.filepath, 'rb') as self.file: - self.parseHeader() - - - def parseHeader(self): - for b in self.file: - line = encodeASCIILine(b) - line = self.rmComment(line) - - split = line.split() - if len(split) > 0: - self.parseHeaderLine(split) - - if self.headerEnd: - self.finalizeHeader() - break - - - def parseHeaderLine(self, split): - keyword = split[0] - self.parserWarning("Uknown header Keyword '" + keyword + "' gets ignored") - - - def finalizeHeader(self): - pass - - - def parsePoints(self): - pass - - - def getPoints(self): - return self.points - - - def version(self): - return 'NO_VERSION_NUMBER' - - - - -class PCDParser_v0_7(PCDParser): - - fields = [] - - def __init__(self, filepath, PointClass): - super().__init__(filepath, PointClass) - self.fields = [] - - - def version(self): - return '.7' - - - def parseHeaderLine(self, split): - keyword = split[0] - if keyword == 'VERSION': - self.parseVERSION(split[1:]) - elif keyword == 'FIELDS': - self.parseFIELDS(split[1:]) - elif keyword == 'SIZE': - self.parseSIZE(split[1:]) - elif keyword == 'TYPE': - self.parseTYPE(split[1:]) - elif keyword == 'COUNT': - self.parseCOUNT(split[1:]) - elif keyword == 'WIDTH': - self.parseWIDTH(split[1:]) - elif keyword == 'HEIGHT': - self.parseHEIGHT(split[1:]) - elif keyword == 'POINTS': - self.parsePOINTS(split[1:]) - elif keyword == 'DATA': - self.parseDATA(split[1:]) - else: - super().parseHeaderLine(split) - - - def parseVERSION(self, split): - pass - - - def parseFIELDS(self, split): - print("SPLIT FIELDS:", split) - for field in split: - self.fields.append([field, None, None, None]) - print("FIELDS, after parsing:", self.fields) - - - def parseSIZE(self, split): - for i, size in enumerate(split): - self.fields[i][1] = int(size) - - - def parseTYPE(self, split): - for i, type in enumerate(split): - self.fields[i][2] = type - - - def parseCOUNT(self, split): - for i, count in enumerate(split): - self.fields[i][3] = int(count) - - - def parseWIDTH(self, split): - self.width = int(split[0]) - - - def parseHEIGHT(self, split): - self.height = int(split[0]) - - - def parsePOINTS(self, split): - pass - - - def parseDATA(self, split): - if split[0] == "ascii": - self.datatype = 'ASCII' - elif split[0] == "binary": - self.datatype = 'BINARY' - elif split[0] == "binary_compressed": - self.datatype = 'BINARY_COMPRESSED' - self.headerEnd = True - - - def finalizeHeader(self): - self.numPoints = self.width * self.height - print("FIELDS - finalized", self.fields) - - - def parsePoints(self): - if self.datatype == 'ASCII': - self.parseASCII() - elif self.datatype == 'BINARY': - self.parseBINARY() - elif self.datatype == 'BINARY_COMPRESSED': - if not GOT_LZF_MODULE: - print("[ERROR] No support for BINARY COMPRESSED data format.") - return - else: - self.parseBINARY_COMPRESSED() - - - def parseASCII(self): - parsedPoints = 0 - while parsedPoints < self.numPoints: - - try: - b = self.file.readline() - line = encodeASCIILine(b) - except: - self.parserError("Unexpected end of data") - return - line = self.rmComment(line) - split = line.split() - - if (len(split) == 0): - continue - else: - parsedPoints += 1 - - point = self.PointClass() - - for field in self.fields: - fieldname = field[0] - fieldtype = field[2] - fieldcount = field[3] - - values = [] - for i in range(fieldcount): - vs = split.pop(0) - if fieldtype == 'F': - values.append(float(vs)) - elif fieldtype in ['U', 'I']: - values.append(int(vs)) - - point.setField(fieldname, values) - - self.points.append(point) - - - def parseBINARY_COMPRESSED(self): - """ BROKEN!!! - There seem to be uncompatiblities - with pcl LZF and liblzf""" - max_size = 1024**3 # 1GB - fs = '<i' - compressed_len = struct.unpack('<i', self.file.read(4))[0] - decompressed_len = struct.unpack('<i', self.file.read(4))[0] - - compressed_body = self.file.read(compressed_len) - decompressed_body = lzf.decompress(compressed_body, max_size) - - fobj = io.BytesIO(decompressed_body) - self.parseBINARY(fobj) - - - - def parseBINARY(self, infile=""): - - if infile == "": - infile = self.file - - for pointi in range(self.numPoints): - point = self.PointClass() - - for field in self.fields: - fieldname = field[0] - fieldsize = field[1] - fieldtype = field[2] - fieldcount = field[3] - - values = [] - for i in range(fieldcount): - - fs = None - if fieldtype == 'F': - if fieldsize == 4: #float - fs = '<f' - elif fieldsize == 8: #double - fs = '<d' - elif fieldtype == 'U': - if fieldsize == 1: #unsinged char - fs = '<B' - elif fieldsize == 2: #unsinged short - fs = '<H' - elif fieldsize == 4: #unsinged int - fs = '<I' - elif fieldtype == 'I': - if fieldsize == 1: #char - fs = '<c' - elif fieldsize == 2: #short - fs = '<h' - elif fieldsize == 4: #signed int - fs = '<i' - - raw = infile.read(fieldsize) - if (fs): - data = struct.unpack(fs, raw) - values.append(data[0]) - - point.setField(fieldname, values) - - self.points.append(point) - - - - -class PCDWriter: - - def __init__(self, points): - self.points = points - - - def _header(self): - header = "# .PCD v0.7 - Point Cloud Data file format\n" - header += "VERSION 0.7\n" - header += "FIELDS x y z\n" - header += "SIZE 4 4 4\n" - header += "TYPE F F F\n" - header += "COUNT 1 1 1\n" - header += "WIDTH " + str(len(self.points)) + "\n" - header += "HEIGHT 1\n" - header += "VIEWPOINT 0 0 0 1 0 0 0\n" - header += "POINTS " + str(len(self.points)) + "\n" - header += "DATA ascii\n" - - return header - - - def write(self, filepath): - - with open(filepath, "w") as f: - f.write(self._header()) - for point in self.points: - f.write(str(point.x)) - f.write(" ") - f.write(str(point.y)) - f.write(" ") - f.write(str(point.z)) - f.write("\n") - - - -def test(): - parser = PCDParser.factory('test.pcd', PointXYZ) - if parser: - parser.parseFile() - points = parser.getPoints() - for point in points: - print(point.x, point.y, point.z) - else: - print("Can't create parser for this file") - +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### + + +import struct +import io + +try: + import lzf + GOT_LZF_MODULE=True +except: + GOT_LZF_MODULE=False + + + +def dumpHexData(data): + for byte in data: + print(hex(byte) + " ", end="") + print() + + +def encodeASCIILine(line): + return line.decode(encoding='ASCII') + + + +class Point: + + def __init__(self): + pass + + + def setField(self, fieldname, values): + pass + + + + +class PointXYZ(Point): + + def __init__(self): + super().__init__() + self.x = 0 + self.y = 0 + self.z = 0 + + + def setField(self, fieldname, values): + value = values[0] + if fieldname == 'x': + self.x = value + elif fieldname == 'y': + self.y = value + elif fieldname == 'z': + self.z = value + + + + +class PCDParser: + + filepath = '' + file = None + + points = [] + PointClass = None + + headerEnd = False + + + @staticmethod + def factory(filepath, PointClass): + version = 'NO_VERSION_NUMBER' + with open(filepath, 'rb') as f: + for b in f: + line = encodeASCIILine(b) + line_split = line.split() + if line_split[0] == 'VERSION' and len(line_split) > 1: + version = line_split[1] + break + + if version == ".7" or version == "0.7": + return PCDParser_v0_7(filepath, PointClass) + else: + return None + + + def __init__(self, filepath, PointClass): + self.filepath = filepath + self.PointClass = PointClass + + self.file = None + self.headerEnd = False + self.points = [] + + + def parserWarning(self, msg): + print("[WARNING] ", msg) + + + def rmComment(self, line): + return line[:line.find('#')] + + + def parseFile(self): + with open(self.filepath, 'rb') as self.file: + self.parseHeader() + self.parsePoints() + + def onlyParseHeader(self): + with open(self.filepath, 'rb') as self.file: + self.parseHeader() + + + def parseHeader(self): + for b in self.file: + line = encodeASCIILine(b) + line = self.rmComment(line) + + split = line.split() + if len(split) > 0: + self.parseHeaderLine(split) + + if self.headerEnd: + self.finalizeHeader() + break + + + def parseHeaderLine(self, split): + keyword = split[0] + self.parserWarning("Uknown header Keyword '" + keyword + "' gets ignored") + + + def finalizeHeader(self): + pass + + + def parsePoints(self): + pass + + + def getPoints(self): + return self.points + + + def version(self): + return 'NO_VERSION_NUMBER' + + + + +class PCDParser_v0_7(PCDParser): + + fields = [] + + def __init__(self, filepath, PointClass): + super().__init__(filepath, PointClass) + self.fields = [] + + + def version(self): + return '.7' + + + def parseHeaderLine(self, split): + keyword = split[0] + if keyword == 'VERSION': + self.parseVERSION(split[1:]) + elif keyword == 'FIELDS': + self.parseFIELDS(split[1:]) + elif keyword == 'SIZE': + self.parseSIZE(split[1:]) + elif keyword == 'TYPE': + self.parseTYPE(split[1:]) + elif keyword == 'COUNT': + self.parseCOUNT(split[1:]) + elif keyword == 'WIDTH': + self.parseWIDTH(split[1:]) + elif keyword == 'HEIGHT': + self.parseHEIGHT(split[1:]) + elif keyword == 'POINTS': + self.parsePOINTS(split[1:]) + elif keyword == 'DATA': + self.parseDATA(split[1:]) + else: + super().parseHeaderLine(split) + + + def parseVERSION(self, split): + pass + + + def parseFIELDS(self, split): + print("SPLIT FIELDS:", split) + for field in split: + self.fields.append([field, None, None, None]) + print("FIELDS, after parsing:", self.fields) + + + def parseSIZE(self, split): + for i, size in enumerate(split): + self.fields[i][1] = int(size) + + + def parseTYPE(self, split): + for i, type in enumerate(split): + self.fields[i][2] = type + + + def parseCOUNT(self, split): + for i, count in enumerate(split): + self.fields[i][3] = int(count) + + + def parseWIDTH(self, split): + self.width = int(split[0]) + + + def parseHEIGHT(self, split): + self.height = int(split[0]) + + + def parsePOINTS(self, split): + pass + + + def parseDATA(self, split): + if split[0] == "ascii": + self.datatype = 'ASCII' + elif split[0] == "binary": + self.datatype = 'BINARY' + elif split[0] == "binary_compressed": + self.datatype = 'BINARY_COMPRESSED' + self.headerEnd = True + + + def finalizeHeader(self): + self.numPoints = self.width * self.height + print("FIELDS - finalized", self.fields) + + + def parsePoints(self): + if self.datatype == 'ASCII': + self.parseASCII() + elif self.datatype == 'BINARY': + self.parseBINARY() + elif self.datatype == 'BINARY_COMPRESSED': + if not GOT_LZF_MODULE: + print("[ERROR] No support for BINARY COMPRESSED data format.") + return + else: + self.parseBINARY_COMPRESSED() + + + def parseASCII(self): + parsedPoints = 0 + while parsedPoints < self.numPoints: + + try: + b = self.file.readline() + line = encodeASCIILine(b) + except: + self.parserError("Unexpected end of data") + return + line = self.rmComment(line) + split = line.split() + + if (len(split) == 0): + continue + else: + parsedPoints += 1 + + point = self.PointClass() + + for field in self.fields: + fieldname = field[0] + fieldtype = field[2] + fieldcount = field[3] + + values = [] + for i in range(fieldcount): + vs = split.pop(0) + if fieldtype == 'F': + values.append(float(vs)) + elif fieldtype in ['U', 'I']: + values.append(int(vs)) + + point.setField(fieldname, values) + + self.points.append(point) + + + def parseBINARY_COMPRESSED(self): + """ BROKEN!!! - There seem to be uncompatiblities + with pcl LZF and liblzf""" + max_size = 1024**3 # 1GB + fs = '<i' + compressed_len = struct.unpack('<i', self.file.read(4))[0] + decompressed_len = struct.unpack('<i', self.file.read(4))[0] + + compressed_body = self.file.read(compressed_len) + decompressed_body = lzf.decompress(compressed_body, max_size) + + fobj = io.BytesIO(decompressed_body) + self.parseBINARY(fobj) + + + + def parseBINARY(self, infile=""): + + if infile == "": + infile = self.file + + for pointi in range(self.numPoints): + point = self.PointClass() + + for field in self.fields: + fieldname = field[0] + fieldsize = field[1] + fieldtype = field[2] + fieldcount = field[3] + + values = [] + for i in range(fieldcount): + + fs = None + if fieldtype == 'F': + if fieldsize == 4: #float + fs = '<f' + elif fieldsize == 8: #double + fs = '<d' + elif fieldtype == 'U': + if fieldsize == 1: #unsinged char + fs = '<B' + elif fieldsize == 2: #unsinged short + fs = '<H' + elif fieldsize == 4: #unsinged int + fs = '<I' + elif fieldtype == 'I': + if fieldsize == 1: #char + fs = '<c' + elif fieldsize == 2: #short + fs = '<h' + elif fieldsize == 4: #signed int + fs = '<i' + + raw = infile.read(fieldsize) + if (fs): + data = struct.unpack(fs, raw) + values.append(data[0]) + + point.setField(fieldname, values) + + self.points.append(point) + + + + +class PCDWriter: + + def __init__(self, points): + self.points = points + + + def _header(self): + header = "# .PCD v0.7 - Point Cloud Data file format\n" + header += "VERSION 0.7\n" + header += "FIELDS x y z\n" + header += "SIZE 4 4 4\n" + header += "TYPE F F F\n" + header += "COUNT 1 1 1\n" + header += "WIDTH " + str(len(self.points)) + "\n" + header += "HEIGHT 1\n" + header += "VIEWPOINT 0 0 0 1 0 0 0\n" + header += "POINTS " + str(len(self.points)) + "\n" + header += "DATA ascii\n" + + return header + + + def write(self, filepath): + + with open(filepath, "w") as f: + f.write(self._header()) + for point in self.points: + f.write(str(point.x)) + f.write(" ") + f.write(str(point.y)) + f.write(" ") + f.write(str(point.z)) + f.write("\n") + + + +def test(): + parser = PCDParser.factory('test.pcd', PointXYZ) + if parser: + parser.parseFile() + points = parser.getPoints() + for point in points: + print(point.x, point.y, point.z) + else: + print("Can't create parser for this file") diff --git a/io_scene_cod/export_xanim.py b/io_scene_cod/export_xanim.py index c3d00fc6dbb3bbf56dafa6216277b3265ccf7688..39fdef2f345d258ab6e068f1e5cf3f14f57cef88 100644 --- a/io_scene_cod/export_xanim.py +++ b/io_scene_cod/export_xanim.py @@ -154,7 +154,7 @@ def save(self, context, filepath="", b_tail = a_matrix * bone.tail file.write("OFFSET %.6f %.6f %.6f\n" % (b_tail[0], b_tail[1], b_tail[2])) file.write("SCALE 1.000000 1.000000 1.000000\n") # Is this even supported by CoD? - + file.write("X %.6f %.6f %.6f\n" % (bone.matrix[0][0], bone.matrix[1][0], bone.matrix[2][0])) file.write("Y %.6f %.6f %.6f\n" % (bone.matrix[0][1], bone.matrix[1][1], bone.matrix[2][1])) file.write("Z %.6f %.6f %.6f\n\n" % (bone.matrix[0][2], bone.matrix[1][2], bone.matrix[2][2])) diff --git a/io_scene_cod/export_xmodel.py b/io_scene_cod/export_xmodel.py index 72874c24fc74570c051fc996915570ac9b6c677a..5ad05add11c25690e38f97fd8e7fdf872362ce1e 100644 --- a/io_scene_cod/export_xmodel.py +++ b/io_scene_cod/export_xmodel.py @@ -371,7 +371,7 @@ def _write(self, context, filepath, b_matrix = a_matrix * bone.matrix_local #from mathutils import Matrix #b_matrix = bone.matrix_local * a_matrix * Matrix(((1,-0,0),(0,0,-1),(-0,1,0))) - + if use_version == '5': file.write("OFFSET %.6f %.6f %.6f\n" % (b_tail[0], b_tail[1], b_tail[2])) file.write("SCALE 1.000000 1.000000 1.000000\n") # Is this even supported by CoD? @@ -401,7 +401,7 @@ def _write(self, context, filepath, use_weight_min, use_weight_min_threshold ) - # Get bones by vertex_group names, bind to root if can't find one + # Get bones by vertex_group names, bind to root if can't find one groupIndices = [bone_mapping.get(g, -1) for g in groupNames] weight_group_list = [] @@ -427,7 +427,7 @@ def _write(self, context, filepath, mesh_matrix[2][1] * v.co[1] + \ mesh_matrix[2][2] * v.co[2] + \ mesh_matrix[2][3] - + #print("%.6f %.6f %.6f single calced xyz\n%.6f %.6f %.6f mat mult" % (x, y, z, )) file.write("VERT %i\n" % (i_vert + v_count)) @@ -541,7 +541,7 @@ def _write(self, context, filepath, uv1 = uv.data[f.index].uv[vi][0] uv2 = 1 - uv.data[f.index].uv[vi][1] # Flip! - #if 0 > uv1 > 1 + #if 0 > uv1 > 1 # TODO: Warn if accidentally tiling ( uv <0 or >1 ) # Remap vert indices used by face @@ -673,7 +673,7 @@ def _write(self, context, filepath, # Remove meshes, which were made by to_mesh() for mesh in meshes: mesh.user_clear() - bpy.data.meshes.remove(mesh) + bpy.data.meshes.remove(mesh) # Quit with no errors return diff --git a/io_scene_cod/import_xmodel.py b/io_scene_cod/import_xmodel.py index 6f862e0b300e8650316491dc09daf4d4b2756852..616ad4be59447e7643ce7078b08c942b64edc4aa 100644 --- a/io_scene_cod/import_xmodel.py +++ b/io_scene_cod/import_xmodel.py @@ -157,13 +157,13 @@ def load(self, context, filepath=""): """ m_col = [] m_col.append((float(line_split[1]), float(line_split[2]), float(line_split[3]))) - + state = 8 elif state == 8 and line_split[0] == "Y": line_split = line.replace(",", "").split() bone_table[bone_i][3][1] = Vector((float(line_split[1]), float(line_split[2]), float(line_split[3]))) - + m_col.append((float(line_split[1]), float(line_split[2]), float(line_split[3]))) state = 9 @@ -173,11 +173,11 @@ def load(self, context, filepath=""): vec_roll = Vector((float(line_split[1]), float(line_split[2]), float(line_split[3]))) ##bone_table[bone_i][3][2] = vec_roll #print("bone_table: %s" % bone_table[bone_i][3][2]) - + m_col.append((float(line_split[1]), float(line_split[2]), float(line_split[3]))) #test_3.append(Vector(vec_roll)) - + test_3.append(m_col) #print("test_3: %s\n\n" % test_3[:]) @@ -227,26 +227,26 @@ def load(self, context, filepath=""): elif state == 15 and line_split[0] == "NUMFACES": numfaces = int(line_split[1]) state = 16 - + elif state == 16: #and line_split[0] == "TRI": #face_i += 1 face_tmp = [] state = 17 - + elif (state == 17 or state == 21 or state == 25) and line_split[0] == "VERT": #print("face_tmp length: %i" % len(face_tmp)) face_tmp.append(int(line_split[1])) state += 1 - + elif (state == 18 or state == 22 or state == 26) and line_split[0] == "NORMAL": state += 1 - + elif (state == 19 or state == 23 or state == 27) and line_split[0] == "COLOR": state += 1 - + elif (state == 20 or state == 24 or state == 28) and line_split[0] == "UV": state += 1 - + elif state == 29: #print("Adding face: %s\n%i faces so far (of %i)\n" % (str(face_tmp), face_i, numfaces)) @@ -257,11 +257,11 @@ def load(self, context, filepath=""): face_i += 1 face_tmp = [] state = 17 - + elif state > 15 and state < 30 and line_split[0] == "NUMOBJECTS": print("Bad numfaces, terminated loop\n") state = 30 - + elif state == 30: print("Adding mesh!") me = bpy.data.meshes.new("pymesh") @@ -269,7 +269,7 @@ def load(self, context, filepath=""): me.update() ob = bpy.data.objects.new("Py-Mesh", me) bpy.context.scene.objects.link(ob) - + state = 31 else: #elif state == 16: @@ -295,7 +295,7 @@ def load(self, context, filepath=""): # Create armature and object bpy.ops.object.add( - type='ARMATURE', + type='ARMATURE', enter_editmode=True, location=origin) ob = bpy.context.object @@ -347,7 +347,7 @@ def createRig(context, name, origin, boneTable): # Create armature and object bpy.ops.object.add( - type='ARMATURE', + type='ARMATURE', enter_editmode=True, location=origin) ob = bpy.context.object diff --git a/io_scene_map/__init__.py b/io_scene_map/__init__.py index c8964ef1c075f75fddc5977a16d26e78007859dd..12aded59ad2b457733628a6b67fcb102fd392b19 100644 --- a/io_scene_map/__init__.py +++ b/io_scene_map/__init__.py @@ -57,7 +57,7 @@ class ExportMAP(bpy.types.Operator, ExportHelper): name="Doom 3 Format", description="Export to Doom3 MAP Format", default=True) - + face_thickness = FloatProperty( name="Face Thickness", description=("Thickness given to geometry which can't be " diff --git a/io_scene_map/export_map.py b/io_scene_map/export_map.py index d8e69e5ba36f9d2f6fd8972b539733806d8c54ba..5c310f7a760a14239dfd61d0f245090235ec47fb 100644 --- a/io_scene_map/export_map.py +++ b/io_scene_map/export_map.py @@ -276,7 +276,7 @@ def write_quake_brush_face(fw, ob, face): # reuse face vertices f_vertices = [me.vertices[vi] for vi in face.vertices] - + # original verts as tuples for writing orig_vco = tuple(round_vec(v.co) for v in f_vertices) @@ -342,7 +342,7 @@ def write_doom_brush(fw, ob, me): image_text = material.name # reuse face vertices - plane = poly_to_doom(me, p, radius) + plane = poly_to_doom(me, p, radius) if plane is None: print(" ERROR: Could not create the plane from polygon!"); elif doom_check_plane(done_planes, plane): @@ -401,7 +401,7 @@ def split_objects(context, objects): for i, ob in enumerate(objects): print("Splitting object: %d/%d" % (i, tot_ob)) ob.select = True - + if ob.type == "MESH": scene.objects.active = ob bpy.ops.object.mode_set(mode='EDIT') @@ -427,7 +427,7 @@ def split_objects(context, objects): bpy.ops.mesh.region_to_loop() bpy.ops.mesh.fill_holes(sides=8) slot_idx = 0 - for slot_idx, m in enumerate(split_ob.material_slots): + for slot_idx, m in enumerate(split_ob.material_slots): if m.name == "textures/common/caulk": break #if m.name != "textures/common/caulk": @@ -507,7 +507,7 @@ def export_map(context, filepath): if obs_mesh or obs_surf: if PREF_DOOM3_FORMAT: fw('Version 2') - + # brushes and surf's must be under worldspan fw('\n// entity 0\n') fw('{\n') @@ -687,7 +687,7 @@ def save(operator, PREF_DEF_TEX_OPTS = texture_opts PREF_GRID_SNAP = grid_snap PREF_DOOM3_FORMAT = doom3_format - + if (PREF_DOOM3_FORMAT): PREF_DEF_TEX_OPTS = '0 0 0' else: @@ -695,4 +695,4 @@ def save(operator, export_map(context, filepath) - return {'FINISHED'} \ No newline at end of file + return {'FINISHED'} diff --git a/mesh_copy_uvs_from_joined.py b/mesh_copy_uvs_from_joined.py index 8a934d493eb8001fcfa16d6ff327f179a6c135da..0ce86b6ae258c5ed246d193215f7af43eef01846 100644 --- a/mesh_copy_uvs_from_joined.py +++ b/mesh_copy_uvs_from_joined.py @@ -197,9 +197,9 @@ def menu_func(self, context): def register(): bpy.utils.register_module(__name__) - + bpy.types.VIEW3D_MT_make_links.append(menu_func) - + def unregister(): bpy.utils.unregister_module(__name__) diff --git a/mesh_insert_edge_ring.py b/mesh_insert_edge_ring.py index 6f758e18ab1cb8b8faabb4b613d06b13f5fc1a8c..af55c4a82f40e3847a22c78702cdb1fe5107748f 100644 --- a/mesh_insert_edge_ring.py +++ b/mesh_insert_edge_ring.py @@ -374,4 +374,4 @@ def unregister(): break if __name__ == "__main__": - register() \ No newline at end of file + register() diff --git a/mesh_ktools.py b/mesh_ktools.py index 73b61f3be6538d4669eca22dc6be67b13d9bb9eb..7a18485e634d0d8360fa2dedc90611988340e33d 100644 --- a/mesh_ktools.py +++ b/mesh_ktools.py @@ -31,7 +31,7 @@ bl_info = { } -import bpy, bmesh +import bpy, bmesh from bpy.props import ( StringProperty, IntProperty, @@ -44,12 +44,12 @@ from bpy.props import ( def testPrint(): - + print('Hello') - - + + def checkScale(): # check if scale is 0 on any of the axis, if it is then set it to 0.01 - + y = -1 for x in bpy.context.object.scale: y += 1 @@ -57,13 +57,13 @@ def checkScale(): # check if scale is 0 on any of the axis, if it is then set it bpy.context.object.scale[y] = 0.01 -#Adds "Lattice to Selection" to the Addon +#Adds "Lattice to Selection" to the Addon class lattice_to_selection(bpy.types.Operator): - """Add a lattice deformer to the selection""" - bl_idname = "object.lattice_to_selection" - bl_label = "Lattice to Selection" - bl_options = {'REGISTER', 'UNDO'} - + """Add a lattice deformer to the selection""" + bl_idname = "object.lattice_to_selection" + bl_label = "Lattice to Selection" + bl_options = {'REGISTER', 'UNDO'} + apply_rot = BoolProperty( name = "Local", description = "Orient the lattice to the active object", @@ -84,14 +84,14 @@ class lattice_to_selection(bpy.types.Operator): seg_u = IntProperty( name = "Lattice U", default = 2, soft_min = 2) seg_v = IntProperty( name = "Lattice V", default = 2, soft_min = 2 ) seg_w = IntProperty( name = "Lattice W", default = 2, soft_min = 2 ) - + def execute(self, context): - - apply_rot = not self.apply_rot # Global vs Local + + apply_rot = not self.apply_rot # Global vs Local parent_to = self.parent_to # Parents all the objects to the Lattice move_first = self.move_first # moves the lattice modifier to be first in the stack interpolation = self.interpolation - + # check if there exists an active object if bpy.context.scene.objects.active: active_obj = bpy.context.scene.objects.active.name @@ -101,38 +101,38 @@ class lattice_to_selection(bpy.types.Operator): bpy.context.scene.objects.active = bpy.data.objects[x.name] active_obj = bpy.context.scene.objects.active.name break - - - + + + if bpy.data.objects[active_obj].type != 'MESH': self.report({'ERROR'}, "Make sure the active object is a Mesh") return {'CANCELLED'} - + mode = bpy.context.active_object.mode - - + + if mode == 'OBJECT': - - + + # check if object type is not MESH and then deselect it for x in bpy.context.selected_objects: if bpy.data.objects[x.name].type != 'MESH': bpy.data.objects[x.name].select = False - - + + org_objs = bpy.context.selected_objects - - + + bpy.ops.object.duplicate() - + # remove any modifiers if bpy.context.object.modifiers: for x in bpy.context.object.modifiers: bpy.ops.object.modifier_remove(modifier=x.name) - + if len(bpy.context.selected_objects) > 1: bpy.ops.object.join() - + # create tmp:object and store its location, rotation and dimensions bpy.ops.object.transform_apply(location=False, rotation=apply_rot, scale=True) bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY', center='BOUNDS') @@ -149,19 +149,19 @@ class lattice_to_selection(bpy.types.Operator): # set dimensions / bounding box size bpy.context.object.scale = bbox_size - + bpy.ops.object.select_all(action='DESELECT') # select and delete the tmp_object bpy.data.objects[tmp_obj].select = True bpy.ops.object.delete(use_global=False) - # select all the original objects and assign the lattice deformer + # select all the original objects and assign the lattice deformer for i in org_objs: if bpy.data.objects[i.name].type == 'MESH' : bpy.context.scene.objects.active = bpy.data.objects[i.name] bpy.data.objects[i.name].select = True - + bpy.ops.object.modifier_add(type='LATTICE') lattice_name = bpy.context.object.modifiers[len(bpy.context.object.modifiers)-1].name bpy.context.object.modifiers[lattice_name].object = lattice_obj @@ -170,44 +170,44 @@ class lattice_to_selection(bpy.types.Operator): bpy.ops.object.modifier_move_up(modifier=lattice_name) else: bpy.data.objects[i.name].select = True - - + + if parent_to: - + bpy.data.objects[lattice_obj.name].select = True bpy.context.scene.objects.active = bpy.data.objects[lattice_obj.name] - + bpy.ops.object.parent_set(type='OBJECT', keep_transform=True) else: - + bpy.ops.object.select_all(action='DESELECT') bpy.data.objects[lattice_obj.name].select = True bpy.context.scene.objects.active = bpy.data.objects[lattice_obj.name] - + bpy.context.object.data.interpolation_type_u = interpolation bpy.context.object.data.interpolation_type_v = interpolation bpy.context.object.data.interpolation_type_w = interpolation - + bpy.context.object.data.points_u = self.seg_u bpy.context.object.data.points_v = self.seg_v bpy.context.object.data.points_w = self.seg_w - + checkScale() - + elif mode == 'EDIT': - - - + + + org_objs = bpy.context.selected_objects - + # Add vertex group and store its name in a variable bpy.ops.object.vertex_group_assign_new() v_id = len(bpy.context.object.vertex_groups)-1 bpy.context.object.vertex_groups[v_id].name = 'tmp_lattice_to_selection' v_group = bpy.context.object.vertex_groups[v_id].name - + bpy.ops.mesh.duplicate() bpy.ops.mesh.separate(type='SELECTED') @@ -218,17 +218,17 @@ class lattice_to_selection(bpy.types.Operator): if x not in org_objs: tmp_obj = x.name print(tmp_obj) - + bpy.ops.object.select_all(action='DESELECT') - + bpy.context.scene.objects.active = bpy.data.objects[tmp_obj] bpy.data.objects[tmp_obj].select = True - - + + if bpy.context.object.modifiers: for x in bpy.context.object.modifiers: bpy.ops.object.modifier_remove(modifier=x.name) - + bpy.ops.object.transform_apply(location=False, rotation=apply_rot, scale=True) bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY', center='BOUNDS') @@ -254,36 +254,36 @@ class lattice_to_selection(bpy.types.Operator): bpy.context.scene.objects.active = bpy.data.objects[active_obj] bpy.data.objects[active_obj].select = True - + bpy.ops.object.modifier_add(type='LATTICE') lattice_name = bpy.context.object.modifiers[len(bpy.context.object.modifiers)-1].name bpy.context.object.modifiers[lattice_name].object = lattice_obj bpy.context.object.modifiers[lattice_name].vertex_group = v_group - + if move_first == True: for x in bpy.context.object.modifiers: bpy.ops.object.modifier_move_up(modifier=lattice_name) bpy.ops.object.select_all(action='DESELECT') - + bpy.data.objects[lattice_obj.name].select = True bpy.context.scene.objects.active = bpy.data.objects[lattice_obj.name] bpy.context.object.data.interpolation_type_u = interpolation bpy.context.object.data.interpolation_type_v = interpolation bpy.context.object.data.interpolation_type_w = interpolation - + bpy.context.object.data.points_u = self.seg_u bpy.context.object.data.points_v = self.seg_v bpy.context.object.data.points_w = self.seg_w - + checkScale() - - - - return {'FINISHED'} + + + + return {'FINISHED'} def invoke( self, context, event ): wm = context.window_manager @@ -291,17 +291,17 @@ class lattice_to_selection(bpy.types.Operator): -#Adds Calculate Normals and Smooth to the Addon +#Adds Calculate Normals and Smooth to the Addon class calc_normals(bpy.types.Operator): - """Calculates and smooths normals.""" - bl_idname = "mesh.calc_normals" - bl_label = "Calculate Normals" - bl_options = {'REGISTER', 'UNDO'} - + """Calculates and smooths normals.""" + bl_idname = "mesh.calc_normals" + bl_label = "Calculate Normals" + bl_options = {'REGISTER', 'UNDO'} + invert = BoolProperty(name = "Invert Normals", description = "Inverts the normals.", default = False) def execute(self, context): - + invert = self.invert mode = bpy.context.active_object.mode @@ -315,52 +315,52 @@ class calc_normals(bpy.types.Operator): for ob in sel: ob = ob.name - bpy.context.scene.objects.active = bpy.data.objects[ob] + bpy.context.scene.objects.active = bpy.data.objects[ob] bpy.ops.object.editmode_toggle() bpy.ops.mesh.select_all(action='SELECT') bpy.ops.mesh.normals_make_consistent(inside=invert) bpy.ops.object.editmode_toggle() - bpy.context.scene.objects.active = bpy.data.objects[active] - + bpy.context.scene.objects.active = bpy.data.objects[active] + elif mode == 'EDIT': bpy.ops.mesh.normals_make_consistent(inside=invert) - - - return {'FINISHED'} + return {'FINISHED'} -#Adds SnapToAxis to the Addon + + +#Adds SnapToAxis to the Addon class snaptoaxis(bpy.types.Operator): - """Snaps selected vertices to zero on the selected axis.""" - bl_idname = "mesh.snaptoaxis" - bl_label = "Snap to Axis" - bl_options = {'REGISTER', 'UNDO'} - - #worldspace = bpy.props.EnumProperty(items= (('OBJECT', 'Object Space', 'Snap to the object axis'), + """Snaps selected vertices to zero on the selected axis.""" + bl_idname = "mesh.snaptoaxis" + bl_label = "Snap to Axis" + bl_options = {'REGISTER', 'UNDO'} + + #worldspace = bpy.props.EnumProperty(items= (('OBJECT', 'Object Space', 'Snap to the object axis'), # ('WORLD', 'World Space', 'Snap to the global axis')), # name = "Object/World", default = 'OBJECT') - + snap_x = BoolProperty(name = "Snap to X", description = "Snaps to zero in X. Also sets the axis for the mirror modifier if that button is turned on", default = True) snap_y = BoolProperty(name = "Snap to Y", description = "Snaps to zero in Y. Also sets the axis for the mirror modifier if that button is turned on", default = False) snap_z = BoolProperty(name = "Snap to Z", description = "Snaps to zero in Z. Also sets the axis for the mirror modifier if that button is turned on", default = False) - + mirror_add = BoolProperty(name = "Add Mirror Modifier", description = "Adds a mirror modifer", default = False) - + mirror_x = BoolProperty(name = "Mirror on X", description = "Sets the modifier to mirror on X", default = True) mirror_y = BoolProperty(name = "Mirror on Y", description = "Sets the modifier to mirror on Y", default = False) mirror_z = BoolProperty(name = "Mirror on Z", description = "Sets the modifier to mirror on Z", default = False) clipping = BoolProperty(name = "Enable Clipping", description = "Prevents vertices from going through the mirror during transform", default = True) - + def draw(self, context): layout = self.layout col = layout.column() - + col_move = col.column(align=True) row = col_move.row(align=True) if self.snap_x: @@ -375,13 +375,13 @@ class snaptoaxis(bpy.types.Operator): row.prop(self, "snap_z", text = "Z", icon='CHECKBOX_HLT') else: row.prop(self, "snap_z", text = "Z", icon='CHECKBOX_DEHLT') - + col.separator() - + col_move = col.column(align=True) - col_move.prop(self, "mirror_add", icon = 'MODIFIER') + col_move.prop(self, "mirror_add", icon = 'MODIFIER') row = col_move.row(align=True) - + row = col_move.row(align=True) row.active = self.mirror_add if self.mirror_x: @@ -396,10 +396,10 @@ class snaptoaxis(bpy.types.Operator): row.prop(self, "mirror_z", text = "Z", icon='CHECKBOX_HLT') else: row.prop(self, "mirror_z", text = "Z", icon='CHECKBOX_DEHLT') - + col = col.column() col.active = self.mirror_add - col.prop(self, "clipping") + col.prop(self, "clipping") def execute(self, context): @@ -407,12 +407,12 @@ class snaptoaxis(bpy.types.Operator): mode = bpy.context.active_object.mode mirror_find = bpy.context.object.modifiers.find('Mirror') run = True - + if mode == 'EDIT': loc = bpy.context.object.location - - + + me = bpy.context.object.data bm = bmesh.from_edit_mesh(me) @@ -424,66 +424,66 @@ class snaptoaxis(bpy.types.Operator): v.co.y = 0 if self.snap_z == True: v.co.z = 0 - + bmesh.update_edit_mesh(me, True, False) - + if self.mirror_add == True: - + if mirror_find <= -1: bpy.ops.object.modifier_add(type='MIRROR') - + bpy.context.object.modifiers['Mirror'].show_viewport = True - + run = False - + bpy.context.object.modifiers["Mirror"].use_clip = self.clipping bpy.context.object.modifiers["Mirror"].use_x = self.mirror_x bpy.context.object.modifiers["Mirror"].use_y = self.mirror_y bpy.context.object.modifiers["Mirror"].use_z = self.mirror_z - - - - - return {'FINISHED'} -#Adds QuickBool to the Addon + + return {'FINISHED'} + + + +#Adds QuickBool to the Addon class quickbool(bpy.types.Operator): - """Quickly carves out the selected polygons. Works best with manifold meshes.""" - bl_idname = "mesh.quickbool" - bl_label = "Quick Bool" - bl_options = {'REGISTER', 'UNDO'} - + """Quickly carves out the selected polygons. Works best with manifold meshes.""" + bl_idname = "mesh.quickbool" + bl_label = "Quick Bool" + bl_options = {'REGISTER', 'UNDO'} + del_bool = BoolProperty(name="Delete BoolMesh", description="Deletes the objects used for the boolean operation.", default= True) move_to = BoolProperty(name="Move to layer 10", description="Moves the objects used for the boolean operation to layer 10", default= False) operation = EnumProperty(items= (('UNION', 'Union', 'Combines'), - ('INTERSECT', 'Intersect', 'Keep the part that overlaps'), + ('INTERSECT', 'Intersect', 'Keep the part that overlaps'), ('DIFFERENCE', 'Difference', 'Cuts out')), - name = "Operation", default = 'DIFFERENCE') - + name = "Operation", default = 'DIFFERENCE') + def draw(self, context): layout = self.layout col = layout.column() col.prop(self, "del_bool") - + col = col.column() col.active = self.del_bool == False - col.prop(self, "move_to") - + col.prop(self, "move_to") + col = layout.column() col.prop(self, "operation") - - - + + + def execute(self, context): - + del_bool = self.del_bool move_to = self.move_to mode = bpy.context.active_object.mode - - + + if mode == 'EDIT': @@ -520,7 +520,7 @@ class quickbool(bpy.types.Operator): bpy.context.scene.objects.active = bpy.data.objects[original] bpy.ops.object.select_pattern(pattern=original) bpy.ops.object.editmode_toggle() - + else: @@ -528,10 +528,10 @@ class quickbool(bpy.types.Operator): original = bpy.context.active_object.name bool = bpy.context.selected_objects - - + + list = [] - + for x in bool: x = x.name if x != original: @@ -543,10 +543,10 @@ class quickbool(bpy.types.Operator): bpy.context.object.modifiers["Boolean"].object = bpy.data.objects[name] bpy.context.object.modifiers["Boolean"].operation = self.operation bpy.ops.object.modifier_apply(apply_as='DATA', modifier="Boolean") - - + + if del_bool == True: - + bpy.ops.object.select_all(action='DESELECT') bpy.ops.object.select_pattern(pattern=name) bpy.context.scene.objects.active = bpy.data.objects[name] @@ -556,57 +556,57 @@ class quickbool(bpy.types.Operator): bpy.ops.mesh.select_all(action='SELECT') bpy.ops.mesh.delete(type='VERT') bpy.ops.object.mode_set(mode = 'OBJECT', toggle = False) - + bpy.ops.object.delete(use_global=False) - bpy.context.scene.objects.active = bpy.data.objects[original] - else: + bpy.context.scene.objects.active = bpy.data.objects[original] + else: bpy.ops.object.select_all(action='DESELECT') bpy.ops.object.select_pattern(pattern=name) - bpy.context.scene.objects.active = bpy.data.objects[name] + bpy.context.scene.objects.active = bpy.data.objects[name] bpy.context.object.draw_type = 'WIRE' - + # Move to garbage layer if move_to == True: bpy.ops.object.move_to_layer(layers=(False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False)) - - bpy.context.scene.objects.active = bpy.data.objects[original] - + + bpy.context.scene.objects.active = bpy.data.objects[original] + bpy.ops.object.mode_set(mode=mode, toggle=False) - return {'FINISHED'} + return {'FINISHED'} -#Adds Autotubes to the Addon +#Adds Autotubes to the Addon class autotubes(bpy.types.Operator): - """Creates a spline tube based on selected edges""" - bl_idname = "mesh.autotubes" - bl_label = "Auto Tubes" - bl_options = {'REGISTER', 'UNDO'} + """Creates a spline tube based on selected edges""" + bl_idname = "mesh.autotubes" + bl_label = "Auto Tubes" + bl_options = {'REGISTER', 'UNDO'} bevel = FloatProperty(name="Tube Width", description="Change width of the tube.", default=0.1, min = 0) res = IntProperty(name="Tube Resolution", description="Change resolution of the tube.", default=2, min = 0, max = 20) - + def execute(self, context): - + mode = bpy.context.active_object.mode type = bpy.context.active_object.type - bevel = self.bevel + bevel = self.bevel res = self.res - + if mode == 'EDIT' and type == 'MESH': bpy.ops.object.mode_set(mode='OBJECT', toggle=False) bpy.ops.object.duplicate() - + bpy.ops.object.mode_set(mode='EDIT', toggle=False) bpy.ops.mesh.select_all(action='INVERT') bpy.ops.mesh.delete(type='EDGE') - + bpy.ops.object.mode_set(mode='OBJECT', toggle=False) bpy.ops.object.subdivision_set(level=0) bpy.ops.object.convert(target='CURVE') @@ -615,49 +615,49 @@ class autotubes(bpy.types.Operator): bpy.context.object.data.splines[0].use_smooth = True bpy.context.object.data.bevel_resolution = 2 bpy.ops.object.shade_smooth() - + bpy.ops.object.mode_set(mode='EDIT', toggle=False) bpy.ops.curve.spline_type_set(type='BEZIER') - + bpy.context.object.data.bevel_depth = bevel bpy.context.object.data.bevel_resolution = res - + #bpy.ops.transform.transform(('INVOKE_DEFAULT'), mode='CURVE_SHRINKFATTEN') - - - + + + elif type == 'CURVE': - + bpy.context.object.data.bevel_depth = bevel bpy.context.object.data.bevel_resolution = res - + elif mode != 'EDIT' and type == 'MESH': self.report({'ERROR'}, "This one only works in Edit mode") return {'CANCELLED'} - return {'FINISHED'} + return {'FINISHED'} -#Adds basicRename to the Addon +#Adds basicRename to the Addon class basicRename(bpy.types.Operator): - """Renames everything to Banana""" - bl_idname = "object.basic_rename" - bl_label = "Basic Renamer" - bl_options = {'REGISTER', 'UNDO'} + """Renames everything to Banana""" + bl_idname = "object.basic_rename" + bl_label = "Basic Renamer" + bl_options = {'REGISTER', 'UNDO'} name = StringProperty(name="Rename", description="Rename selected objects", default="banana") padding = IntProperty(name = "Number Padding", description = "Adds how many padded numbers", default = 3, min = 1, max = 8) prefix = StringProperty(name="Pre Fix", description="Adds a Prefix to the name", default="") post_ob = StringProperty(name="Post Fix Object", description="Adds ending to object name", default="_MDL") post_data = StringProperty(name="Post Fix Data", description="Adds ending to data name", default="_DATA") - - def execute(self, context): - + def execute(self, context): + + # The original script obj = bpy.context.selected_objects name = self.name @@ -669,30 +669,30 @@ class basicRename(bpy.types.Operator): for item in obj: number += 1 item.name = "%s%s_%s%s" %(str(prefix), str(name), str(number).zfill(padding), str(post_ob)) - item.data.name = "%s%s_%s%s" %(str(prefix), str(name), str(number).zfill(padding), str(post_data)) - + item.data.name = "%s%s_%s%s" %(str(prefix), str(name), str(number).zfill(padding), str(post_data)) + return {'FINISHED'} class cut_tool(bpy.types.Operator): - """Context sensitive cut tool""" - bl_idname = "mesh.cut_tool" - bl_label = "Cut Tool" - bl_options = {'REGISTER', 'UNDO'} + """Context sensitive cut tool""" + bl_idname = "mesh.cut_tool" + bl_label = "Cut Tool" + bl_options = {'REGISTER', 'UNDO'} cuts = IntProperty(name="Number of Cuts", description="Change the number of cuts.", default=1, min = 1, soft_max = 10) loopcut = BoolProperty(name="Insert LoopCut", description="Makes a loop cut based on the selected edges", default= False) smoothness = FloatProperty(name="Smoothness", description="Change the smoothness.", default=0, min = 0, soft_max = 1) - quad_corners = bpy.props.EnumProperty(items= (('INNERVERT', 'Inner Vert', 'How to subdivide quad corners'), + quad_corners = bpy.props.EnumProperty(items= (('INNERVERT', 'Inner Vert', 'How to subdivide quad corners'), ('PATH', 'Path', 'How to subdivide quad corners'), - ('STRAIGHT_CUT', 'Straight Cut', 'How to subdivide quad corners'), + ('STRAIGHT_CUT', 'Straight Cut', 'How to subdivide quad corners'), ('FAN', 'Fan', 'How to subdivide quad corners')), - name = "Quad Corner Type", default = 'STRAIGHT_CUT') + name = "Quad Corner Type", default = 'STRAIGHT_CUT') def execute(self, context): - + quad_corners = self.quad_corners cuts = self.cuts loopcut = self.loopcut @@ -700,9 +700,9 @@ class cut_tool(bpy.types.Operator): mode = bpy.context.active_object.mode if mode == 'EDIT': - + sel_mode = bpy.context.tool_settings.mesh_select_mode[:] - + #Checks and stores if any Vert, Edge or Face is selected. bpy.ops.object.mode_set(mode='OBJECT', toggle=False) @@ -722,29 +722,29 @@ class cut_tool(bpy.types.Operator): for v in bm.verts: if v.select: vert_sel.append(v.index) - - + + bm.to_mesh(me) bpy.ops.object.mode_set(mode='EDIT', toggle=False) - - - """ + + + """ if len(sel) == 0 and len(edge_sel) == 0 and len(vert_sel) == 0 : bpy.ops.mesh.knife_tool("INVOKE_DEFAULT") - """ - - + """ + + if sel_mode[2] == True and len(sel) > 1: vgrp = bpy.context.object.vertex_groups.active_index - + #Store the Hidden Polygons bpy.ops.mesh.select_all(action='SELECT') bpy.ops.object.vertex_group_assign_new() tmp_hidden = bpy.context.object.vertex_groups.active_index bpy.ops.mesh.select_all(action='DESELECT') - + #Select faces to be cut bpy.ops.object.mode_set(mode='OBJECT', toggle=False) mesh = bpy.context.active_object.data.polygons @@ -761,8 +761,8 @@ class cut_tool(bpy.types.Operator): bpy.ops.object.mode_set(mode='OBJECT', toggle=False) me = bpy.context.object.data - bm = bmesh.new() - bm.from_mesh(me) + bm = bmesh.new() + bm.from_mesh(me) boundry_edge = [] for v in bm.edges: @@ -780,8 +780,8 @@ class cut_tool(bpy.types.Operator): bpy.ops.object.mode_set(mode='OBJECT', toggle=False) me = bpy.context.object.data - bm = bmesh.new() - bm.from_mesh(me) + bm = bmesh.new() + bm.from_mesh(me) cut_edges = [] for v in bm.edges: @@ -799,8 +799,8 @@ class cut_tool(bpy.types.Operator): bpy.ops.object.mode_set(mode='OBJECT', toggle=False) me = bpy.context.object.data - bm = bmesh.new() - bm.from_mesh(me) + bm = bmesh.new() + bm.from_mesh(me) int_edges = [] for v in bm.edges: @@ -815,7 +815,7 @@ class cut_tool(bpy.types.Operator): for x in int_edges: if x in boundry_edge: cut_edges.remove(x) - + bpy.ops.mesh.select_all(action='DESELECT') #Select the new edges to cut @@ -824,7 +824,7 @@ class cut_tool(bpy.types.Operator): for f in cut_edges: mesh[f].select = True - + #Perform cut and select the cut line. bpy.ops.object.mode_set(mode='EDIT', toggle=False) bpy.ops.mesh.subdivide(number_cuts = cuts, smoothness = smoothness, quadcorner = quad_corners) @@ -839,8 +839,8 @@ class cut_tool(bpy.types.Operator): bpy.ops.object.mode_set(mode='OBJECT', toggle=False) me = bpy.context.object.data - bm = bmesh.new() - bm.from_mesh(me) + bm = bmesh.new() + bm.from_mesh(me) cut_line = [] for v in bm.edges: @@ -848,7 +848,7 @@ class cut_tool(bpy.types.Operator): cut_line.append(v.index) bm.to_mesh(me) - + bpy.ops.object.mode_set(mode='EDIT', toggle=False) bpy.ops.mesh.reveal() @@ -869,79 +869,79 @@ class cut_tool(bpy.types.Operator): for f in cut_line: mesh[f].select = True - + bpy.ops.object.mode_set(mode='EDIT', toggle=False) - + bpy.ops.object.vertex_group_remove(all=False) bpy.ops.mesh.select_mode(use_extend=True, use_expand=False, type='FACE') elif sel_mode[0] == True and len(vert_sel) >= 2: bpy.ops.mesh.vert_connect_path() - + elif sel_mode[1] == True and loopcut == False and len(edge_sel) != 0: bpy.ops.mesh.subdivide(number_cuts = cuts, smoothness = smoothness, quadcorner = quad_corners) - + elif sel_mode[1] == True and loopcut == True and len(edge_sel) != 0: bpy.ops.mesh.loop_multi_select(ring=True) bpy.ops.mesh.subdivide(number_cuts = cuts, smoothness = smoothness, quadcorner = quad_corners) else: bpy.ops.mesh.select_all(action='DESELECT') bpy.ops.mesh.knife_tool("INVOKE_DEFAULT") - + else: self.report({'ERROR'}, "This one only works in Edit mode") - return {'FINISHED'} + return {'FINISHED'} -#Adds customAutoSmooth to the Addon +#Adds customAutoSmooth to the Addon class customAutoSmooth(bpy.types.Operator): - """Set AutoSmooth angle""" - bl_idname = "object.custom_autosmooth" - bl_label = "Autosmooth" - bl_options = {'REGISTER', 'UNDO'} + """Set AutoSmooth angle""" + bl_idname = "object.custom_autosmooth" + bl_label = "Autosmooth" + bl_options = {'REGISTER', 'UNDO'} angle = FloatProperty(name="AutoSmooth Angle", description="Set AutoSmooth angle", default= 30.0, min = 0.0, max = 180.0) - - def execute(self, context): + + def execute(self, context): mode = bpy.context.active_object.mode - + if mode != 'OBJECT': bpy.ops.object.mode_set(mode='OBJECT', toggle=False) - + ob = bpy.context.selected_objects angle = self.angle angle = angle * (3.14159265359/180) - + bpy.ops.object.shade_smooth() for x in ob: x = x.name bpy.data.objects[x].data.use_auto_smooth = True bpy.data.objects[x].data.auto_smooth_angle = angle - - bpy.ops.object.mode_set(mode=mode, toggle=False) + + bpy.ops.object.mode_set(mode=mode, toggle=False) return {'FINISHED'} -#Adds shrinkwrapSmooth to the Addon +#Adds shrinkwrapSmooth to the Addon class shrinkwrapSmooth(bpy.types.Operator): - """Smooths the selected vertices while trying to keep the original shape with a shrinkwrap modifier. """ - bl_idname = "mesh.shrinkwrap_smooth" - bl_label = "Shrinkwrap Smooth" - bl_options = {'REGISTER', 'UNDO'} + """Smooths the selected vertices while trying to keep the original shape with a shrinkwrap modifier. """ + bl_idname = "mesh.shrinkwrap_smooth" + bl_label = "Shrinkwrap Smooth" + bl_options = {'REGISTER', 'UNDO'} - pin = BoolProperty(name="Pin Selection Border", description="Pins the outer edge of the selection.", default = True) - subsurf = IntProperty(name="Subsurf Levels", description="More reliable, but slower results", default = 0, min = 0, soft_max = 4) + pin = BoolProperty(name="Pin Selection Border", description="Pins the outer edge of the selection.", default = True) + subsurf = IntProperty(name="Subsurf Levels", description="More reliable, but slower results", default = 0, min = 0, soft_max = 4) def execute(self, context): - + iterate = 6 pin = self.pin data = bpy.context.object.data.name @@ -949,7 +949,7 @@ class shrinkwrapSmooth(bpy.types.Operator): # Set up for vertex weight bpy.context.scene.tool_settings.vertex_group_weight = 1 v_grps = len(bpy.context.object.vertex_groups.items()) - + bpy.ops.object.mode_set(mode = 'OBJECT', toggle = False) org_ob = bpy.context.object.name @@ -965,38 +965,38 @@ class shrinkwrapSmooth(bpy.types.Operator): bpy.ops.object.select_all(action='DESELECT') bpy.ops.object.select_pattern(pattern=tmp_ob) - bpy.context.scene.objects.active = bpy.data.objects[tmp_ob] + bpy.context.scene.objects.active = bpy.data.objects[tmp_ob] bpy.ops.object.mode_set(mode = 'EDIT', toggle = False) bpy.ops.mesh.select_mode(use_extend=False, use_expand=False, type='VERT') - + if v_grps >= 1: for x in range(v_grps): bpy.ops.object.vertex_group_add() - + if pin == True: bpy.ops.object.vertex_group_assign_new() org_id = bpy.context.object.vertex_groups.active_index - + bpy.ops.object.vertex_group_assign_new() sel = bpy.context.object.vertex_groups.active.name sel_id = bpy.context.object.vertex_groups.active_index - + bpy.ops.mesh.region_to_loop() bpy.ops.object.vertex_group_remove_from(use_all_groups=False, use_all_verts=False) - + bpy.ops.mesh.select_all(action='SELECT') bpy.ops.mesh.region_to_loop() bpy.ops.object.vertex_group_remove_from(use_all_groups=False, use_all_verts=False) - + bpy.ops.mesh.select_all(action='DESELECT') bpy.ops.object.vertex_group_select(sel_id) - - + + else: bpy.ops.object.vertex_group_assign_new() - sel = bpy.context.object.vertex_groups.active.name + sel = bpy.context.object.vertex_groups.active.name for x in range(iterate): @@ -1006,11 +1006,11 @@ class shrinkwrapSmooth(bpy.types.Operator): bpy.context.object.modifiers[shrink_name].target = bpy.data.objects[shrink_ob] bpy.context.object.modifiers[shrink_name].vertex_group = sel - + bpy.context.object.modifiers[shrink_name].wrap_method = 'PROJECT' bpy.context.object.modifiers[shrink_name].use_negative_direction = True bpy.context.object.modifiers[shrink_name].subsurf_levels = self.subsurf - + bpy.ops.mesh.vertices_smooth(factor=1, repeat=1) @@ -1018,18 +1018,18 @@ class shrinkwrapSmooth(bpy.types.Operator): bpy.ops.object.mode_set(mode = 'OBJECT', toggle = False) bpy.ops.object.convert(target='MESH') bpy.ops.object.mode_set(mode = 'EDIT', toggle = False) - + bpy.ops.object.mode_set(mode = 'OBJECT', toggle = False) - - - + + + bpy.ops.object.vertex_group_remove(all = False) bpy.ops.object.modifier_remove(modifier=shrink_name) bpy.ops.object.select_all(action='DESELECT') bpy.ops.object.select_pattern(pattern=shrink_ob) - bpy.context.scene.objects.active = bpy.data.objects[shrink_ob] + bpy.context.scene.objects.active = bpy.data.objects[shrink_ob] #Delete all geo inside Shrink_Object bpy.ops.object.mode_set(mode = 'EDIT', toggle = False) @@ -1040,7 +1040,7 @@ class shrinkwrapSmooth(bpy.types.Operator): bpy.ops.object.delete(use_global=True) bpy.ops.object.select_pattern(pattern=tmp_ob) - bpy.context.scene.objects.active = bpy.data.objects[tmp_ob] + bpy.context.scene.objects.active = bpy.data.objects[tmp_ob] bpy.ops.object.mode_set(mode = 'EDIT', toggle = False) @@ -1055,40 +1055,40 @@ class shrinkwrapSmooth(bpy.types.Operator): bpy.ops.object.select_pattern(pattern=org_ob) - bpy.context.scene.objects.active = bpy.data.objects[org_ob] + bpy.context.scene.objects.active = bpy.data.objects[org_ob] bpy.ops.object.mode_set(mode = 'EDIT', toggle = False) - + # Fix for Blender remembering the previous selection bpy.ops.object.vertex_group_assign_new() bpy.ops.object.vertex_group_remove(all = False) - + return {'FINISHED'} -#Adds buildCorner to the Addon +#Adds buildCorner to the Addon class buildCorner(bpy.types.Operator): """Builds corner topology. Good for converting ngons""" bl_idname = "mesh.build_corner" bl_label = "Build Corner" - bl_options = {'REGISTER', 'UNDO'} + bl_options = {'REGISTER', 'UNDO'} offset = IntProperty() - + def modal(self, context, event): - + if event.type == 'MOUSEMOVE': - + delta = self.offset - event.mouse_x - + if delta >= 0: offset = 1 else: offset = 0 - + bpy.ops.mesh.edge_face_add() - + bpy.ops.mesh.poke() bpy.ops.mesh.select_mode(use_extend=False, use_expand=False, type='VERT') bpy.ops.object.vertex_group_assign_new() @@ -1111,7 +1111,7 @@ class buildCorner(bpy.types.Operator): bpy.ops.object.vertex_group_remove(all = False) bpy.ops.mesh.select_mode(use_extend=False, use_expand=False, type='FACE') - + elif event.type == 'LEFTMOUSE': return {'FINISHED'} @@ -1124,12 +1124,12 @@ class buildCorner(bpy.types.Operator): def invoke(self, context, event): if context.object: - + # Check selection - + bpy.ops.mesh.edge_face_add() bpy.ops.mesh.region_to_loop() - + bpy.ops.object.mode_set(mode='OBJECT', toggle=False) me = bpy.context.object.data @@ -1138,7 +1138,7 @@ class buildCorner(bpy.types.Operator): face_sel = [] edge_sel = [] - + for v in bm.faces: if v.select: @@ -1147,30 +1147,30 @@ class buildCorner(bpy.types.Operator): if v.select: edge_sel.append(v.index) - - + + bm.to_mesh(me) bpy.ops.object.mode_set(mode='EDIT', toggle=False) bpy.ops.mesh.loop_to_region() - + ################################### - + edge_sel = len(edge_sel) - + if edge_sel == 4: return {'FINISHED'} - + elif edge_sel%2 == 0: self.offset = event.mouse_x context.window_manager.modal_handler_add(self) return {'RUNNING_MODAL'} - + #elif edge_sel == 5: # bpy.ops.mesh.quads_convert_to_tris(quad_method='BEAUTY', ngon_method='BEAUTY') # bpy.ops.mesh.tris_convert_to_quads(face_threshold=3.14159, shape_threshold=3.14159) # return {'FINISHED'} - + else: bpy.ops.mesh.poke() bpy.ops.mesh.quads_convert_to_tris(quad_method='BEAUTY', ngon_method='BEAUTY') @@ -1186,7 +1186,7 @@ class drawPoly(bpy.types.Operator): """Draw a polygon""" bl_idname = "mesh.draw_poly" bl_label = "Draw Poly" - + cursor_co = FloatVectorProperty() vert_count = 0 manip = BoolProperty() @@ -1194,63 +1194,63 @@ class drawPoly(bpy.types.Operator): sel_mode = BoolVectorProperty() cursor_depth = BoolProperty() snap = BoolProperty() - - + + def modal(self, context, event): - + # set header gui context.area.tag_redraw() context.area.header_text_set("LMB = Create New Point, SHIFT = Flip Normals, RMB / ENTER = Accept NGon, MMB = Accept QuadFill") - + mesh = bpy.context.active_object.data - + if event.type == 'LEFTMOUSE': if event.value == 'PRESS': - - + + bpy.ops.view3d.cursor3d('INVOKE_DEFAULT') - + obj = bpy.context.active_object vert_co = bpy.context.scene.cursor_location world = obj.matrix_world.inverted_safe() - + bpy.ops.mesh.select_all(action='DESELECT') bpy.ops.object.mode_set(mode='OBJECT', toggle=False) - + me = bpy.context.object.data bm = bmesh.new() bm.from_mesh(me) - + # Add new vert new_vert = bm.verts.new(vert_co) new_vert.co = world*new_vert.co new_vert_id = new_vert.index self.vert_count += 1 - + if self.vert_count >= 2: bm.verts.ensure_lookup_table() set_of_verts = set(bm.verts[i] for i in range(-2,0)) bm.edges.new(set_of_verts) - + # Get index of first and last vertex first_index = len(bm.verts)-self.vert_count second_index = first_index+1 third_index = first_index+2 second_to_last_index = len(bm.verts)-2 - - + + bm.to_mesh(me) bm.free() - + mesh.vertices[new_vert_id].select = True bpy.ops.object.mode_set(mode='EDIT', toggle=False) bpy.context.scene.cursor_location = self.cursor_co - - + + if self.vert_count >= 4: bpy.ops.object.vertex_group_assign() - + if self.vert_count == 3: # remove second vertex from group bpy.ops.mesh.select_all(action='DESELECT') @@ -1260,10 +1260,10 @@ class drawPoly(bpy.types.Operator): bpy.ops.object.mode_set(mode='EDIT', toggle=False) bpy.ops.object.vertex_group_assign() bpy.ops.mesh.select_more() - + if self.vert_count == 2: bpy.ops.mesh.select_more() - + if self.vert_count >= 4: # make core poly bpy.ops.mesh.select_all(action='DESELECT') @@ -1273,63 +1273,63 @@ class drawPoly(bpy.types.Operator): mesh.vertices[third_index].select = True bpy.ops.object.mode_set(mode='EDIT', toggle=False) bpy.ops.mesh.edge_face_add() - + if self.vert_count == 4: bpy.ops.mesh.select_all(action='DESELECT') bpy.ops.object.vertex_group_select(self.vgrp) bpy.ops.mesh.edge_face_add() - + # Remove remaining core edge bpy.ops.object.mode_set(mode='OBJECT', toggle=False) mesh.vertices[second_index].select = True bpy.ops.object.mode_set(mode='EDIT', toggle=False) bpy.ops.mesh.edge_face_add() - - + + if self.vert_count >= 5: #bpy.ops.object.vertex_group_assign() bpy.ops.mesh.select_all(action='DESELECT') - + # Remove Last Edge bpy.ops.object.mode_set(mode='OBJECT', toggle=False) mesh.vertices[first_index].select = True mesh.vertices[second_to_last_index].select = True bpy.ops.object.mode_set(mode='EDIT', toggle=False) bpy.ops.mesh.delete(type='EDGE') - + # Fill in rest of face bpy.ops.object.vertex_group_select(self.vgrp) bpy.ops.mesh.edge_face_add() - - + + # Remove remaining core edge bpy.ops.object.mode_set(mode='OBJECT', toggle=False) mesh.vertices[second_index].select = True bpy.ops.object.mode_set(mode='EDIT', toggle=False) bpy.ops.mesh.edge_face_add() bpy.ops.mesh.flip_normals() - - + + #return {'FINISHED'} elif event.type == 'MIDDLEMOUSE': - + # reset header gui context.area.tag_redraw() context.area.header_text_set() - + # Convert to Quads bpy.ops.mesh.quads_convert_to_tris(quad_method='BEAUTY', ngon_method='BEAUTY') bpy.ops.mesh.tris_convert_to_quads() bpy.ops.mesh.tris_convert_to_quads(face_threshold=3.14159, shape_threshold=3.14159) - + # restore selection mode and manipulator bpy.context.tool_settings.mesh_select_mode = self.sel_mode bpy.context.space_data.show_manipulator = self.manip bpy.context.user_preferences.view.use_mouse_depth_cursor = self.cursor_depth bpy.context.scene.tool_settings.use_snap = self.snap - - + + # Remove and make sure vertex group data is gone bpy.ops.object.vertex_group_remove_from(use_all_verts=True) bpy.ops.object.vertex_group_remove() @@ -1337,23 +1337,23 @@ class drawPoly(bpy.types.Operator): bpy.context.object.vertex_groups.active.name = "drawPoly_temp" bpy.ops.object.vertex_group_remove() - + return {'CANCELLED'} - + elif event.type in {'RIGHTMOUSE', 'ESC', 'SPACE'}: - + # reset header gui context.area.tag_redraw() context.area.header_text_set() - + # restore selection mode and manipulator bpy.context.tool_settings.mesh_select_mode = self.sel_mode bpy.context.space_data.show_manipulator = self.manip bpy.context.user_preferences.view.use_mouse_depth_cursor = self.cursor_depth bpy.context.scene.tool_settings.use_snap = self.snap - - + + # Remove and make sure vertex group data is gone bpy.ops.object.vertex_group_remove_from(use_all_verts=True) bpy.ops.object.vertex_group_remove() @@ -1361,14 +1361,14 @@ class drawPoly(bpy.types.Operator): bpy.context.object.vertex_groups.active.name = "drawPoly_temp" bpy.ops.object.vertex_group_remove() - + return {'CANCELLED'} - + elif event.type == 'LEFT_SHIFT' or event.type == 'RIGHT_SHIFT': bpy.ops.mesh.flip_normals() - + return {'PASS_THROUGH'} - + elif event.type == 'LEFT_CTRL' or event.type == 'RIGHT_CTRL' : if bpy.context.user_preferences.view.use_mouse_depth_cursor == True: bpy.context.user_preferences.view.use_mouse_depth_cursor = False @@ -1381,22 +1381,22 @@ class drawPoly(bpy.types.Operator): return {'RUNNING_MODAL'} def invoke(self, context, event): - - + + sel_ob = len(bpy.context.selected_objects) - - + + if sel_ob >= 1: sel_type = bpy.context.object.type - + if sel_type == 'MESH': bpy.ops.object.mode_set(mode='EDIT', toggle=False) - + else: self.report({'WARNING'}, "Active object is not a mesh.") return {'CANCELLED'} - - + + elif sel_ob == 0: bpy.ops.mesh.primitive_plane_add() bpy.context.selected_objects[0].name = "polyDraw" @@ -1404,29 +1404,29 @@ class drawPoly(bpy.types.Operator): bpy.ops.object.mode_set(mode='EDIT', toggle=False) bpy.ops.mesh.select_all(action='SELECT') bpy.ops.mesh.delete(type='VERT') - - - - + + + + # Store selection mode, snap and manipulator settings self.sel_mode = bpy.context.tool_settings.mesh_select_mode[:] bpy.context.tool_settings.mesh_select_mode = True, False, False self.manip = bpy.context.space_data.show_manipulator bpy.context.space_data.show_manipulator = False - self.cursor_depth = bpy.context.user_preferences.view.use_mouse_depth_cursor + self.cursor_depth = bpy.context.user_preferences.view.use_mouse_depth_cursor bpy.context.user_preferences.view.use_mouse_depth_cursor = False self.snap = bpy.context.scene.tool_settings.use_snap bpy.context.scene.tool_settings.use_snap = False - + bpy.ops.object.mode_set(mode='EDIT', toggle=False) - + bpy.ops.mesh.select_all(action='DESELECT') bpy.ops.object.vertex_group_assign_new() self.vgrp = bpy.context.object.vertex_groups.active_index bpy.context.object.vertex_groups.active.name = "drawPoly_temp" - + self.cursor_co = bpy.context.scene.cursor_location - + context.window_manager.modal_handler_add(self) return {'RUNNING_MODAL'} @@ -1436,33 +1436,33 @@ class toggleSilhouette(bpy.types.Operator): bl_idname = "object.toggle_silhouette" bl_label = "Toggle Silhouette" - + diff_col = FloatVectorProperty(default = (0.226, 0.179, 0.141)) disp_mode = StringProperty(default = 'SOLID') matcap = BoolProperty(default = False) only_render = BoolProperty(default = False) - + def execute(self, context): - - + + light_check = bpy.context.user_preferences.system.solid_lights[0].use if light_check == True: # Set Lights to Off bpy.context.user_preferences.system.solid_lights[0].use = False bpy.context.user_preferences.system.solid_lights[1].use = False - + # Store variables self.diff_col = bpy.context.user_preferences.system.solid_lights[2].diffuse_color self.disp_mode = bpy.context.space_data.viewport_shade self.matcap = bpy.context.space_data.use_matcap self.only_render = bpy.context.space_data.show_only_render - + bpy.context.user_preferences.system.solid_lights[2].diffuse_color = 0,0,0 bpy.context.space_data.viewport_shade = 'SOLID' bpy.context.space_data.use_matcap = False bpy.context.space_data.show_only_render = True - + else: bpy.context.user_preferences.system.solid_lights[0].use = True bpy.context.user_preferences.system.solid_lights[1].use = True @@ -1470,29 +1470,29 @@ class toggleSilhouette(bpy.types.Operator): bpy.context.space_data.viewport_shade = self.disp_mode bpy.context.space_data.use_matcap = self.matcap bpy.context.space_data.show_only_render = self.only_render - + return {'FINISHED'} - -#Adds growLoop to the Addon + +#Adds growLoop to the Addon class growLoop(bpy.types.Operator): - """Grows the selected edges in both directions """ - bl_idname = "mesh.grow_loop" - bl_label = "Grow Loop" - bl_options = {'REGISTER', 'UNDO'} + """Grows the selected edges in both directions """ + bl_idname = "mesh.grow_loop" + bl_label = "Grow Loop" + bl_options = {'REGISTER', 'UNDO'} grow = IntProperty(name="Grow Selection", description="How much to grow selection", default= 1, min=1, soft_max=10) - + def execute(self, context): - + grow = self.grow sel_mode = bpy.context.tool_settings.mesh_select_mode[:] - + for x in range(grow): if sel_mode[2] == True: - + edge_sel = [] border = [] interior = [] @@ -1503,7 +1503,7 @@ class growLoop(bpy.types.Operator): mesh_edges = bpy.context.active_object.data.edges mesh_faces = bpy.context.active_object.data.polygons - bpy.ops.mesh.select_mode(use_extend=False, use_expand=False, type='FACE') + bpy.ops.mesh.select_mode(use_extend=False, use_expand=False, type='FACE') me = bpy.context.object.data bm = bmesh.from_edit_mesh(me) @@ -1521,7 +1521,7 @@ class growLoop(bpy.types.Operator): for e in bm.edges: if e.select: border.append(e.index) - + for e in edge_sel: @@ -1575,10 +1575,10 @@ class growLoop(bpy.types.Operator): for f in face_grow: if f in face_loop: face_sel.append(f) - + for f in face_org: face_sel.append(f) - + bmesh.update_edit_mesh(me, True, False) bpy.ops.mesh.select_all(action='DESELECT') @@ -1589,7 +1589,7 @@ class growLoop(bpy.types.Operator): mesh_faces[f].select = True bpy.ops.object.mode_set(mode='EDIT', toggle=False) - + else: mesh = bpy.context.active_object.data.edges @@ -1605,7 +1605,7 @@ class growLoop(bpy.types.Operator): for e in bm.edges: if e.select: org_sel.append(e.index) - + bpy.ops.mesh.select_more(use_face_step=False) for e in bm.edges: @@ -1615,14 +1615,14 @@ class growLoop(bpy.types.Operator): bpy.ops.mesh.select_all(action='DESELECT') bmesh.update_edit_mesh(me, True, False) - + # Select the original edges bpy.ops.object.mode_set(mode='OBJECT', toggle=False) for e in org_sel: - mesh[e].select = True + mesh[e].select = True bpy.ops.object.mode_set(mode='EDIT', toggle=False) - + me = bpy.context.object.data bm = bmesh.from_edit_mesh(me) bpy.ops.mesh.loop_multi_select(ring=False) @@ -1638,34 +1638,34 @@ class growLoop(bpy.types.Operator): for x in loop_sel: if x in grow_sel: sel.append(x) - + bpy.ops.object.mode_set(mode='OBJECT', toggle=False) for e in sel: - mesh[e].select = True - bpy.ops.object.mode_set(mode='EDIT', toggle=False) - + mesh[e].select = True + bpy.ops.object.mode_set(mode='EDIT', toggle=False) + bpy.context.tool_settings.mesh_select_mode = sel_mode - + return {'FINISHED'} -#Adds extendLoop to the Addon +#Adds extendLoop to the Addon class extendLoop(bpy.types.Operator): - """Uses the active face or edge to extends the selection in one direction""" - bl_idname = "mesh.extend_loop" - bl_label = "Extend Loop" - bl_options = {'REGISTER', 'UNDO'} + """Uses the active face or edge to extends the selection in one direction""" + bl_idname = "mesh.extend_loop" + bl_label = "Extend Loop" + bl_options = {'REGISTER', 'UNDO'} extend = IntProperty(name="Extend Selection", description="How much to extend selection", default= 1, min=1, soft_max=10) - + def execute(self, context): - + sel_mode = bpy.context.tool_settings.mesh_select_mode[:] extend = self.extend - + for x in range(extend): if sel_mode[2] == True: - + bpy.ops.object.mode_set(mode='OBJECT', toggle=False) active_face = bpy.context.object.data.polygons.active # find active face bpy.ops.object.mode_set(mode='EDIT', toggle=False) @@ -1685,7 +1685,7 @@ class extendLoop(bpy.types.Operator): for f in bm.faces: if f.select: face_org.append(f.index) - + face_org.remove(active_face) @@ -1731,7 +1731,7 @@ class extendLoop(bpy.types.Operator): for e in bm.edges: if e.select: active_edges.append(e.index) - + for e in active_edges: if e in edge_sel: @@ -1764,7 +1764,7 @@ class extendLoop(bpy.types.Operator): if f.select: face_loop.append(f.index) - + bmesh.update_edit_mesh(me, True, False) bpy.ops.mesh.select_all(action='DESELECT') @@ -1790,14 +1790,14 @@ class extendLoop(bpy.types.Operator): for f in face_grow: if f in face_loop: face_sel.append(f) - + for f in face_sel: if f not in face_org: active_face = f - + for f in face_org: face_sel.append(f) - + bmesh.update_edit_mesh(me, True, False) bpy.ops.mesh.select_all(action='DESELECT') @@ -1809,7 +1809,7 @@ class extendLoop(bpy.types.Operator): bpy.context.object.data.polygons.active = active_face bpy.ops.object.mode_set(mode='EDIT', toggle=False) - + elif sel_mode[1] == True: mesh = bpy.context.active_object.data @@ -1819,7 +1819,7 @@ class extendLoop(bpy.types.Operator): sel = [] org_verts = [] active_verts = [] - + # Get active edge me = bpy.context.object.data bm = bmesh.from_edit_mesh(me) @@ -1833,10 +1833,10 @@ class extendLoop(bpy.types.Operator): for e in bm.edges: if e.select: org_sel.append(e.index) - + bmesh.update_edit_mesh(me, True, False) - + # Select active edge bpy.ops.mesh.select_all(action='DESELECT') bpy.ops.object.mode_set(mode='OBJECT', toggle=False) @@ -1845,13 +1845,13 @@ class extendLoop(bpy.types.Operator): # Get verts of active edge bm = bmesh.from_edit_mesh(me) - + for v in bm.verts: if v.select: active_verts.append(v.index) - + bmesh.update_edit_mesh(me, True, False) - + # Select original selection minus active edge bpy.ops.mesh.select_all(action='DESELECT') bpy.ops.object.mode_set(mode='OBJECT', toggle=False) @@ -1859,35 +1859,35 @@ class extendLoop(bpy.types.Operator): mesh.edges[x].select = True mesh.edges[active_edge].select = False bpy.ops.object.mode_set(mode='EDIT', toggle=False) - + bm = bmesh.from_edit_mesh(me) - + # Store the original vertices minus active edge for v in bm.verts: if v.select: org_verts.append(v.index) - - + + # Compare verts for x in active_verts: if x in org_verts: active_verts.remove(x) - + bmesh.update_edit_mesh(me, True, False) - + # Select end vertex bpy.ops.mesh.select_all(action='DESELECT') bpy.ops.mesh.select_mode(use_extend=False, use_expand=False, type='VERT') bpy.ops.object.mode_set(mode='OBJECT', toggle=False) mesh.vertices[active_verts[0]].select = True bpy.ops.object.mode_set(mode='EDIT', toggle=False) - - + + # Grow the end vertex and store the edges bpy.ops.mesh.select_more(use_face_step=False) bpy.ops.mesh.select_mode(use_extend=False, use_expand=False, type='EDGE') bm = bmesh.from_edit_mesh(me) - + for e in bm.edges: if e.select: grow_sel.append(e.index) @@ -1897,7 +1897,7 @@ class extendLoop(bpy.types.Operator): # Run loop of the active edges and store it bpy.ops.object.mode_set(mode='OBJECT', toggle=False) - mesh.edges[active_edge].select = True + mesh.edges[active_edge].select = True bpy.ops.object.mode_set(mode='EDIT', toggle=False) bpy.ops.mesh.loop_multi_select(ring=False) @@ -1922,17 +1922,17 @@ class extendLoop(bpy.types.Operator): for x in org_sel: if x not in sel: sel.append(x) - + # Compare org_sel with sel to get the active edge for x in sel: if x not in org_sel: active_edge = x - + # Select the resulting edges bpy.ops.object.mode_set(mode='OBJECT', toggle=False) for e in sel: - mesh.edges[e].select = True + mesh.edges[e].select = True bpy.ops.object.mode_set(mode='EDIT', toggle=False) # Set the new active edge @@ -1941,26 +1941,26 @@ class extendLoop(bpy.types.Operator): bm.edges.ensure_lookup_table() bm.select_history.add(bm.edges[active_edge]) bmesh.update_edit_mesh(me, True, False) - - + + return {'FINISHED'} -#Adds extendLoop to the Addon +#Adds extendLoop to the Addon class shrinkLoop(bpy.types.Operator): - """Shrink the selected loop""" - bl_idname = "mesh.shrink_loop" - bl_label = "Shrink Loop" - bl_options = {'REGISTER', 'UNDO'} + """Shrink the selected loop""" + bl_idname = "mesh.shrink_loop" + bl_label = "Shrink Loop" + bl_options = {'REGISTER', 'UNDO'} shrink = IntProperty(name="Shrink Selection", description="How much to shrink selection", default= 1, min=1, soft_max=15) - + def execute(self, context): - + sel_mode = bpy.context.tool_settings.mesh_select_mode[:] shrink = self.shrink - + for x in range(shrink): if sel_mode[2] == True: me = bpy.context.object.data @@ -1979,11 +1979,11 @@ class shrinkLoop(bpy.types.Operator): for e in bm.edges: if e.select: sel.append(e.index) - + # Populate vert_list vert_list.append(e.verts[0].index) vert_list.append(e.verts[1].index) - + # Store dictionary edge_dic[e.index] = [e.verts[0].index, e.verts[1].index] @@ -1996,7 +1996,7 @@ class shrinkLoop(bpy.types.Operator): for v in vert_list: if vert_list.count(v) == 2: end_verts.append(v) - + # Check verts in dictionary for key, value in edge_dic.items(): if value[0] in end_verts: @@ -2040,7 +2040,7 @@ class shrinkLoop(bpy.types.Operator): for e in new_faces: mesh.polygons[e].select = True bpy.ops.object.mode_set(mode='EDIT', toggle=False) - + else: me = bpy.context.object.data bm = bmesh.from_edit_mesh(me) @@ -2054,11 +2054,11 @@ class shrinkLoop(bpy.types.Operator): for e in bm.edges: if e.select: sel.append(e.index) - + # Populate vert_list vert_list.append(e.verts[0].index) vert_list.append(e.verts[1].index) - + # Store dictionary edge_dic[e.index] = [e.verts[0].index, e.verts[1].index] @@ -2066,7 +2066,7 @@ class shrinkLoop(bpy.types.Operator): for v in vert_list: if vert_list.count(v) == 1: end_verts.append(v) - + # Check verts in dictionary for key, value in edge_dic.items(): if value[0] in end_verts: @@ -2086,15 +2086,15 @@ class shrinkLoop(bpy.types.Operator): for e in sel: mesh[e].select = True bpy.ops.object.mode_set(mode='EDIT', toggle=False) - - + + return {'FINISHED'} class paintSelect(bpy.types.Operator): """Click and drag to select""" bl_idname = "view3d.select_paint" bl_label = "Paint Select" - bl_options = {'REGISTER', 'UNDO'} + bl_options = {'REGISTER', 'UNDO'} deselect = BoolProperty(default = False, description = 'Deselect objects, polys, edges or verts') toggle = BoolProperty(default = False, description = 'Toggles the selection. NOTE: this option can be slow on heavy meshes') @@ -2102,34 +2102,34 @@ class paintSelect(bpy.types.Operator): sel_after = IntProperty(description = 'Do Not Touch', options = {'HIDDEN'}) def modal(self, context, event): - + #if event.type == 'MOUSEMOVE': refresh = event.mouse_x - - + + if self.deselect == False: bpy.ops.view3d.select('INVOKE_DEFAULT', extend = True, deselect = False) else: bpy.ops.view3d.select('INVOKE_DEFAULT', extend = False, deselect = True, toggle = True) - - - if event.value == 'RELEASE': + + + if event.value == 'RELEASE': return {'FINISHED'} return {'RUNNING_MODAL'} def invoke(self, context, event): - + if self.toggle: sel_ob = len(bpy.context.selected_objects) - + if sel_ob >= 1: mode = bpy.context.object.mode - + if mode == 'EDIT': sel_mode = bpy.context.tool_settings.mesh_select_mode[:] - + # Get Selection before bpy.ops.object.mode_set(mode='OBJECT', toggle=False) ob = bpy.context.object.data @@ -2148,11 +2148,11 @@ class paintSelect(bpy.types.Operator): for p in ob.polygons: if p.select: self.sel_before += 1 - + # Toggle Selection bpy.ops.object.mode_set(mode='EDIT', toggle=False) bpy.ops.view3d.select('INVOKE_DEFAULT', extend = False, toggle = True) - + bpy.ops.object.mode_set(mode='OBJECT', toggle=False) ob = bpy.context.object.data # check verts after @@ -2160,7 +2160,7 @@ class paintSelect(bpy.types.Operator): for v in ob.vertices: if v.select: self.sel_after += 1 - + # check edges after elif sel_mode[1]: for e in ob.edges: @@ -2171,8 +2171,8 @@ class paintSelect(bpy.types.Operator): for p in ob.polygons: if p.select: self.sel_after += 1 - - + + if self.sel_after > self.sel_before: self.deselect = False elif self.sel_after == self.sel_before: @@ -2183,16 +2183,16 @@ class paintSelect(bpy.types.Operator): self.deselect = True bpy.ops.object.mode_set(mode='EDIT', toggle=False) - + elif mode == 'OBJECT': bpy.ops.view3d.select('INVOKE_DEFAULT', extend = False, toggle = True) - + sel_ob_after = len(bpy.context.selected_objects) - + if sel_ob_after < sel_ob: - self.deselect = True - - + self.deselect = True + + context.window_manager.modal_handler_add(self) return {'RUNNING_MODAL'} @@ -2201,58 +2201,58 @@ class pathSelectRing(bpy.types.Operator): """Selects the shortest edge ring path""" bl_idname = "mesh.path_select_ring" bl_label = "Path Select Ring" - bl_options = {'REGISTER', 'UNDO'} - + bl_options = {'REGISTER', 'UNDO'} + pick = BoolProperty(name = "Pick Mode", description = "Pick Mode", default = False) collapse = BoolProperty(name = "Collapse", description = "Collapses everything between your two selected edges", default = False) def draw(self, context): layout = self.layout - + def execute(self, context): - + me = bpy.context.object.data bm = bmesh.from_edit_mesh(me) mesh = bpy.context.active_object.data sel_mode = bpy.context.tool_settings.mesh_select_mode[:] - + org_sel = [] start_end = [] active_edge = [] border_sel = [] vert_sel = [] face_sel = [] - + if sel_mode[1]: - + bpy.context.tool_settings.mesh_select_mode = [False, True, False] - + if self.pick: bpy.ops.view3d.select('INVOKE_DEFAULT', extend=True, deselect=False, toggle=False) - - # Store the Start and End edges + + # Store the Start and End edges iterate = 0 for e in reversed(bm.select_history): if isinstance(e, bmesh.types.BMEdge): iterate += 1 start_end.append(e) if iterate >= 2: - break - + break + if len(start_end) <= 1: if self.collapse: bpy.ops.mesh.merge(type='COLLAPSE', uvs=True) return{'FINISHED'} return{'CANCELLED'} - + # Store active edge for e in reversed(bm.select_history): if isinstance(e, bmesh.types.BMEdge): active_edge = e.index - break - + break + # Store original edges for e in bm.edges: if e.select: @@ -2263,8 +2263,8 @@ class pathSelectRing(bpy.types.Operator): for f in bm.faces: if f.select: face_sel.append(f) - - + + # Store boundry edges bpy.ops.mesh.region_to_loop() @@ -2273,17 +2273,17 @@ class pathSelectRing(bpy.types.Operator): border_sel.append(e) bpy.ops.mesh.select_all(action='DESELECT') - + # Select Start and End edges for e in start_end: e.select = True - + # Hide trick bpy.ops.mesh.loop_multi_select(ring=True) - + bpy.ops.mesh.select_mode(use_extend=False, use_expand=True, type='FACE') bpy.ops.mesh.hide(unselected=True) - + bpy.ops.mesh.select_mode(use_extend=False, use_expand=False, type='EDGE') bpy.ops.mesh.select_all(action='DESELECT') for e in start_end: @@ -2291,7 +2291,7 @@ class pathSelectRing(bpy.types.Operator): bpy.ops.mesh.shortest_path_select() bpy.ops.mesh.select_more() bpy.ops.mesh.select_mode(use_extend=False, use_expand=False, type='FACE') - + bpy.ops.mesh.select_all(action='INVERT') bpy.ops.mesh.reveal() bpy.ops.mesh.select_all(action='INVERT') @@ -2300,36 +2300,36 @@ class pathSelectRing(bpy.types.Operator): # Deselect border edges for e in border_sel: e.select = False - + # Add to original selection for e in bm.edges: if e.select: org_sel.append(e) - + # Restore hidden polygons bpy.ops.mesh.select_mode(use_extend=False, use_expand=False, type='FACE') for f in face_sel: f.select = True bpy.ops.mesh.hide(unselected=True) - - + + # Reselect original selection bpy.ops.mesh.select_mode(use_extend=False, use_expand=False, type='EDGE') bpy.ops.mesh.select_all(action='DESELECT') for e in org_sel: e.select = True - + # Set active edge bm.select_history.add(bm.edges[active_edge]) - - + + if self.collapse: bpy.ops.mesh.merge(type='COLLAPSE', uvs=True) - + bmesh.update_edit_mesh(me, True, False) - + return {'FINISHED'} - + else: self.report({'WARNING'}, "This tool only workins in edge mode.") return {'CANCELLED'} @@ -2347,22 +2347,22 @@ class ktools_menu(bpy.types.Menu): layout = self.layout layout.operator_context = 'INVOKE_DEFAULT' layout.operator("mesh.draw_poly") - layout.operator("object.toggle_silhouette") + layout.operator("object.toggle_silhouette") layout.operator("mesh.quickbool") layout.operator("mesh.calc_normals") layout.operator("object.custom_autosmooth") layout.operator("object.basic_rename") layout.operator("object.lattice_to_selection") - + #Draws the Custom Menu in Edit Mode class VIEW3D_MT_edit_mesh_ktools_menuEdit(bpy.types.Menu): bl_label = "KTools - Edit Mode" bl_idname = "VIEW3D_MT_edit_mesh_ktools_menuEdit" def draw(self, context): - - + + layout = self.layout @@ -2370,23 +2370,23 @@ class VIEW3D_MT_edit_mesh_ktools_menuEdit(bpy.types.Menu): layout.operator("mesh.snaptoaxis") layout.operator("mesh.autotubes") layout.operator("mesh.shrinkwrap_smooth") - + layout.operator_context = 'INVOKE_DEFAULT' layout.operator("mesh.build_corner") layout.operator("object.lattice_to_selection") - + layout.separator() - + layout.operator("mesh.path_select_ring") layout.operator("mesh.grow_loop") layout.operator("mesh.shrink_loop") layout.operator("mesh.extend_loop") - + layout.separator() - + layout.operator("mesh.draw_poly") - layout.operator("object.toggle_silhouette") - layout.operator("mesh.quickbool") + layout.operator("object.toggle_silhouette") + layout.operator("mesh.quickbool") layout.operator("object.custom_autosmooth") layout.operator("mesh.calc_normals") layout.operator("object.basic_rename") @@ -2395,52 +2395,52 @@ class VIEW3D_MT_edit_mesh_ktools_menuEdit(bpy.types.Menu): #Calls the KTools Object Menu class ktools(bpy.types.Operator): #Namesuggestion: K-Tools or K-Mac - """Calls the KTools Menu""" - bl_idname = "object.ktools" - bl_label = "KTools Object Menu" - #bl_options = {'REGISTER', 'UNDO'} + """Calls the KTools Menu""" + bl_idname = "object.ktools" + bl_label = "KTools Object Menu" + #bl_options = {'REGISTER', 'UNDO'} def execute(self, context): - - - bpy.ops.wm.call_menu(name=ktools_menu.bl_idname) - return {'FINISHED'} - + + + bpy.ops.wm.call_menu(name=ktools_menu.bl_idname) + return {'FINISHED'} + """ sel_ob = bpy.context.object - - + + if sel_ob: - + mode = bpy.context.active_object.mode - + if mode == 'EDIT': bpy.ops.wm.call_menu(name=VIEW3D_MT_edit_mesh_ktools_menuEdit.bl_idname) - + else: bpy.ops.wm.call_menu(name=ktools_menu.bl_idname) - return {'FINISHED'} - + return {'FINISHED'} + else: bpy.ops.wm.call_menu(name=ktools_menu.bl_idname) return {'FINISHED'} #self.report({'WARNING'}, "Active object is not a mesh.") #return {'CANCELLED'} """ - + #Calls the KTools Edit Menu class ktools_mesh(bpy.types.Operator): #Namesuggestion: K-Tools or K-Mac - """Calls the KTools Edit Menu""" - bl_idname = "mesh.ktools_mesh" - bl_label = "KTools Mesh Menu" - #bl_options = {'REGISTER', 'UNDO'} + """Calls the KTools Edit Menu""" + bl_idname = "mesh.ktools_mesh" + bl_label = "KTools Mesh Menu" + #bl_options = {'REGISTER', 'UNDO'} def execute(self, context): - - + + bpy.ops.wm.call_menu(name=VIEW3D_MT_edit_mesh_ktools_menuEdit.bl_idname) - return {'FINISHED'} + return {'FINISHED'} # draw function for integration in menus @@ -2449,7 +2449,7 @@ def menu_func(self, context): self.layout.menu("VIEW3D_MT_edit_mesh_ktools_menuEdit", text = "KTools") def menu_func_ob(self, context): self.layout.separator() - self.layout.menu("OBJECT_MT_ktools_menu", text = "KTools") + self.layout.menu("OBJECT_MT_ktools_menu", text = "KTools") #Register and Unregister all the operators def register(): @@ -2477,13 +2477,13 @@ def register(): bpy.types.VIEW3D_MT_edit_mesh_specials.prepend(menu_func) bpy.types.VIEW3D_MT_object_specials.prepend(menu_func_ob) - + kc = bpy.context.window_manager.keyconfigs.addon if kc: # Add paint select to CTRL+SHIFT+ALT+LeftMouse km = kc.keymaps.new(name="3D View", space_type="VIEW_3D") kmi = km.keymap_items.new('view3d.select_paint', 'ACTIONMOUSE', 'PRESS', shift=True, ctrl=True, alt=True) - + def unregister(): @@ -2526,5 +2526,3 @@ def unregister(): # to test the addon without having to install it. if __name__ == "__main__": register() - - diff --git a/mesh_xoffsets.py b/mesh_xoffsets.py index 4da6cf19c01f2a3a1ed315ce93256e7fa35622cc..b688dd5524638d921a4918bb00d8040ec4e380c3 100644 --- a/mesh_xoffsets.py +++ b/mesh_xoffsets.py @@ -29,14 +29,14 @@ todo: [X] fix: when btn clicked, dialog will not appear until after mouse moved [X] fix: when new meas input, transform not applied until after mouse moved [ ] prevent selection of non-visible vertices - [ ] fix bug: obj is not subscriptable error if perspective is changed after + [ ] fix bug: obj is not subscriptable error if perspective is changed after launching addon, disabling perspective change for now [ ] better measurement input panel [ ] add hotkey reference info into 3D View ? [?] snap_point not deleted after exit [X] only free move during translate when in selected objects [X] snap toggle button still drawn when dialog opened (jumps to dialog box) - [ ] + [ ] #============================================================================ """ @@ -71,11 +71,11 @@ from bpy_extras.view3d_utils import location_3d_to_region_2d CHECK_POPUP_INFO, GET_0_OR_180, DO_TRANSFORM, - + MOVE, SCALE, ROTATE, - + SLOW3DTO2D, GRABONLY ) = range(9) @@ -900,7 +900,7 @@ def do_rotate(ref_pts, r_dat): curs_back = bpy.context.scene.cursor_location.copy() bpy.context.space_data.pivot_point = 'CURSOR' bpy.context.scene.cursor_location = ref_pts.rp_ls[1].co3d.copy() - + axis_lock = ref_pts.ax_lock op_ax_lock = () if axis_lock == 'X': op_ax_lock = 1, 0, 0 @@ -1012,7 +1012,7 @@ def reset_settings(self): if flts_alm_eq(pt1[2], pt2[2]): self.report({'ERROR'}, 'Free and Anchor share same location.') self.ref_pts = ReferencePoints() # reset ref pt data - + if self.pt_find_md == GRABONLY: create_snap_pt(self.left_click_co, self.sel_backup) @@ -1202,7 +1202,7 @@ def prepare_selected(sel_backup, ref_pts, transf_type): # runs transformation functions depending on which options are set. # transform functions cannot be called directly due to use of pop-up for -# getting user input +# getting user input def do_transform(self): global curr_meas_stor, new_meas_stor rp_ls, ax_lock = self.ref_pts.rp_ls, self.ref_pts.ax_lock diff --git a/np_station/__init__.py b/np_station/__init__.py index 73193b31f46cc8e43e3f5069ef84883c1f40867f..74748440ba9501b3334833bc080c7ac1064ea96b 100644 --- a/np_station/__init__.py +++ b/np_station/__init__.py @@ -964,4 +964,3 @@ def unregister(): if __name__ == '__main__': register() - diff --git a/np_station/np_float_box.py b/np_station/np_float_box.py index b6d73fb5e8e8b925041957a59408e8098865272c..baa7bfc8e7c229c601b2684c16fd58ceaaed59c7 100644 --- a/np_station/np_float_box.py +++ b/np_station/np_float_box.py @@ -773,4 +773,4 @@ def register(): def unregister(): #bpy.app.handlers.scene_update_post.remove(NPFB_scene_update) - pass \ No newline at end of file + pass diff --git a/np_station/np_float_poly.py b/np_station/np_float_poly.py index 061049d8ae64f602a3814e3baa3345258595ae35..81c0190961b50c20b664fc62b0adfcb5d1d3fec2 100644 --- a/np_station/np_float_poly.py +++ b/np_station/np_float_poly.py @@ -2416,4 +2416,3 @@ def unregister(): # bpy.app.handlers.scene_update_post.remove(scene_update) pass - diff --git a/np_station/np_float_rectangle.py b/np_station/np_float_rectangle.py index 4f260175a95e935694f245ab0038bdb17993975e..509650c01c78c8dd635fb8e10c325ab7b480ef4c 100644 --- a/np_station/np_float_rectangle.py +++ b/np_station/np_float_rectangle.py @@ -725,4 +725,4 @@ def register(): def unregister(): #bpy.app.handlers.scene_update_post.remove(NPFR_scene_update) - pass \ No newline at end of file + pass diff --git a/np_station/np_point_align.py b/np_station/np_point_align.py index 44a7f14316e1d29c85addb23739f78845a2f529a..4290b049c2ad11d47b00dd43e052dee1a1c982d5 100644 --- a/np_station/np_point_align.py +++ b/np_station/np_point_align.py @@ -660,4 +660,4 @@ def register(): def unregister(): #bpy.app.handlers.scene_update_post.remove(NPPL_scene_update) - pass \ No newline at end of file + pass diff --git a/np_station/np_point_array.py b/np_station/np_point_array.py index 379be6081fe62901ce6f083a786f6d566755559f..da150fcd3b15cf01a86086de39b9d4ebfadf590f 100644 --- a/np_station/np_point_array.py +++ b/np_station/np_point_array.py @@ -1211,4 +1211,3 @@ def unregister(): #bpy.utils.unregister_class(NPPAPreferences) #bpy.utils.unregister_module(__name__) bpy.app.handlers.scene_update_post.remove(NPPA_scene_update) - diff --git a/np_station/np_point_copy.py b/np_station/np_point_copy.py index 9bb0d4db756d7563e19e1d57d019b94b4a01ab6e..741dcb95d06d613463ea5bd08ff3c26436f694ee 100644 --- a/np_station/np_point_copy.py +++ b/np_station/np_point_copy.py @@ -1295,4 +1295,3 @@ def unregister(): #bpy.utils.unregister_class(NPPCPreferences) #bpy.utils.unregister_module(__name__) bpy.app.handlers.scene_update_post.remove(NPPC_scene_update) - diff --git a/np_station/np_point_instance.py b/np_station/np_point_instance.py index 2a320393bd7af7c3d41df463a68732fc678fc39e..710a04984ffc97db8c6adfa62343ce9dead52619 100644 --- a/np_station/np_point_instance.py +++ b/np_station/np_point_instance.py @@ -1305,4 +1305,3 @@ def unregister(): #bpy.utils.unregister_class(NPPIPreferences) #bpy.utils.unregister_module(__name__) bpy.app.handlers.scene_update_post.remove(NPPI_scene_update) - diff --git a/np_station/utils_function.py b/np_station/utils_function.py index f8469c2b8e7669bf20a6e7002d8f63653b71d568..5e64c0d88b771e049d35d1c961c2f0f01945727c 100644 --- a/np_station/utils_function.py +++ b/np_station/utils_function.py @@ -26,4 +26,3 @@ __npdebug__ = False def np_print(*args): if __npdebug__: print(*args) - diff --git a/np_station/utils_geometry.py b/np_station/utils_geometry.py index 33c0b99cde846f5c86c86b084e82d5447794516c..897191011a721bcc79b452a4cb7f021945cf90c9 100644 --- a/np_station/utils_geometry.py +++ b/np_station/utils_geometry.py @@ -627,4 +627,4 @@ def get_eul_z_angle_diffffff_in_rotated_system(eul_0, eul_1, n): # v6? if n[2] < 0: alpha_real = - alpha_real np_print('alpha_real', alpha_real) - return alpha_real \ No newline at end of file + return alpha_real diff --git a/np_station/utils_graphics.py b/np_station/utils_graphics.py index e71160a495f77f388a2ce8a4331b3852033bc980..b1624aff93c958afbee35ee11e719e15f11f4268 100644 --- a/np_station/utils_graphics.py +++ b/np_station/utils_graphics.py @@ -710,4 +710,3 @@ def display_cursor_badge(co2d, symbol, badge_mode, message_main, message_aux, au bgl.glEnd() ''' bgl.glDisable(bgl.GL_BLEND) - diff --git a/object_particle_hair_lab.py b/object_particle_hair_lab.py index e628e862b1fb30b5a2d8798c083b49a185c1139f..f19e7d58b85f200af90e023768cbe12fff8412db 100644 --- a/object_particle_hair_lab.py +++ b/object_particle_hair_lab.py @@ -1500,6 +1500,3 @@ def unregister(): if __name__ == "__main__": register() - - - diff --git a/object_particle_hair_net.py b/object_particle_hair_net.py index f0d4f85235cdbee8f0a0153419f5bb531abde172..f2a34e67496ec4f7d7543edee34c0e773574a88d 100644 --- a/object_particle_hair_net.py +++ b/object_particle_hair_net.py @@ -969,4 +969,3 @@ def unregister(): if __name__ == '__main__': register() - diff --git a/oscurart_mesh_thread.py b/oscurart_mesh_thread.py index 079080b4fbacaa43a5b50079a9455cd6d62245d7..b93ced68c9a17e00d33acb2f12434fdb8ce07368 100644 --- a/oscurart_mesh_thread.py +++ b/oscurart_mesh_thread.py @@ -98,4 +98,3 @@ def unregister(): if __name__ == '__main__': register() - diff --git a/render_auto_save.py b/render_auto_save.py index fe2c176cb35ae1b36738be25f98a2ea3fa38fb81..f44bae1cc12459851398a7a03ec10021ad0331e6 100644 --- a/render_auto_save.py +++ b/render_auto_save.py @@ -5,13 +5,13 @@ #All rights reserved. # #Redistribution and use in source and binary forms, with or without -#modification, are permitted provided that the following conditions are met: +#modification, are permitted provided that the following conditions are met: # #1. Redistributions of source code must retain the above copyright notice, this -# list of conditions and the following disclaimer. +# list of conditions and the following disclaimer. #2. Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. +# and/or other materials provided with the distribution. # #THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND #ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED @@ -56,13 +56,13 @@ def auto_save_render(scene): if format == 'OPEN_EXR_MULTILAYER': extension = '.exr' if format == 'JPEG': extension = '.jpg' if format == 'PNG': extension = '.png' - + blendname = basename(bpy.data.filepath).rpartition('.')[0] filepath = dirname(bpy.data.filepath) + '/auto_saves' - + if not exists(filepath): mkdir(filepath) - + if scene.auto_save_subfolders: filepath = join(filepath, blendname) if not exists(filepath): @@ -72,7 +72,7 @@ def auto_save_render(scene): files = [f for f in listdir(filepath) \ if f.startswith(blendname) \ and f.lower().endswith(('.png', '.jpg', '.jpeg', '.exr'))] - + highest = 0 if files: for f in files: @@ -81,37 +81,37 @@ def auto_save_render(scene): if suffix: if int(suffix[-1]) > highest: highest = int(suffix[-1]) - + save_name = join(filepath, blendname) + '_' + str(highest+1).zfill(3) + extension image = bpy.data.images['Render Result'] if not image: print('Auto Save: Render Result not found. Image not saved') return - + print('Auto_Save:', save_name) image.save_render(save_name, scene=None) if scene.save_blend: save_name_blend = join(filepath, blendname) + '_' + str(highest+1).zfill(3) + '.blend' print('Blend_Save:',save_name_blend) - bpy.ops.wm.save_as_mainfile(filepath=save_name_blend, copy=True) - + bpy.ops.wm.save_as_mainfile(filepath=save_name_blend, copy=True) + rndr.image_settings.file_format = original_format ########################################################################### def auto_save_UI(self, context): layout = self.layout - + split=layout.split() col = split.column() col.prop(context.scene, 'save_after_render', text='Auto Save Image', toggle=False) - col.prop(context.scene, 'save_blend', text='with .blend', toggle=False) + col.prop(context.scene, 'save_blend', text='with .blend', toggle=False) - col = split.column() + col = split.column() col.prop(context.scene, 'auto_save_subfolders', toggle=False) col.prop(context.scene, 'auto_save_format', text='as', expand=False) - + def register(): bpy.types.Scene.save_after_render = BoolProperty( name='Save after render', @@ -120,7 +120,7 @@ def register(): bpy.types.Scene.save_blend = BoolProperty( name = 'with .blend', default=True, - description='Also save .blend file into: //auto_save/') + description='Also save .blend file into: //auto_save/') bpy.types.Scene.auto_save_format = EnumProperty( name='Auto Save File Format', description='File Format for the auto saves.', @@ -135,7 +135,7 @@ def register(): description='Save into individual subfolders per blend name') bpy.app.handlers.render_post.append(auto_save_render) bpy.types.RENDER_PT_render.append(auto_save_UI) - + def unregister(): del(bpy.types.Scene.save_after_render) del(bpy.types.Scene.auto_save_format) diff --git a/render_shots.py b/render_shots.py index 22203ca06d3f9d8ebe35804ef7f7ec65427ba4a0..5aa011bf97f354850c780b6c7ce30cb682362f68 100644 --- a/render_shots.py +++ b/render_shots.py @@ -42,15 +42,15 @@ import os, shutil ##################################### def shape_nav(self, context): nav = self.rs_shotshape_nav - + if self.rs_shotshape_shape != "": shapeVerts = bpy.data.objects[self.rs_shotshape_shape].data.vertices max = len(shapeVerts)-1 min = max - (max+max) - + if nav > max or nav < min: nav = 0 - + v = shapeVerts[nav].co self.location = (v[0], v[1], v[2]) return None @@ -61,7 +61,7 @@ def is_new_object(ob): isNew = ob["rs_shotshape_use_frames"] except: isNew = None - + return True if isNew is None else False @@ -69,7 +69,7 @@ def update_shot_list(scn): scn.rs_is_updating = True if hasattr(scn, 'rs_create_folders'): scn.rs_create_folders = False - + for ob in bpy.data.objects: if ob.type == 'CAMERA': if is_new_object(ob): @@ -104,7 +104,7 @@ def update_shot_list(scn): ob["rs_shotshape_nav_start"] ob["rs_shotshape_offset"] ob["rs_shotshape_use_frames"] - + scn.rs_is_updating = False @@ -114,60 +114,60 @@ def update_shot_list(scn): def init_props(): object = bpy.types.Object scene = bpy.types.Scene - + # Camera properties - object.rs_shot_include = BoolProperty(name="", + object.rs_shot_include = BoolProperty(name="", description="Include this shot during render", default=True) - + object.rs_shot_start = IntProperty(name="Start", description="First frame in this shot", default=0, min=0, max=300000) - + object.rs_shot_end = IntProperty(name="End", - description="Last frame in this shot", + description="Last frame in this shot", default=0, min=0, max=300000) object.rs_shot_output = StringProperty(name="", description="Directory/name to save to", subtype='DIR_PATH') - + object.rs_toggle_panel = BoolProperty(name="", description="Show/hide options for this shot", default=True) - + # Render settings - object.rs_settings_use = BoolProperty(name = "", default=False, + object.rs_settings_use = BoolProperty(name = "", default=False, description = "Use specific render settings for this shot") - + object.rs_resolution_x = IntProperty(name="X", description="Number of horizontal pixels in the rendered image", default=2000, min=4, max=10000) - + object.rs_resolution_y = IntProperty(name="Y", description = "Number of vertical pixels in the rendered image", default=2000, min=4, max=10000) - + object.rs_cycles_samples = IntProperty(name="Samples", description = "Number of samples to render for each pixel", default=10, min=1, max=2147483647) - + # Shot shapes object.rs_shotshape_use = BoolProperty(name="", default=False, description="Use a shape to set a series of shots for this camera") - - object.rs_shotshape_shape = StringProperty(name="Shape:", + + object.rs_shotshape_shape = StringProperty(name="Shape:", description="Select an object") - - object.rs_shotshape_nav = IntProperty(name="Navigate", - description="Navigate through this shape's vertices (0 = first vertex)", + + object.rs_shotshape_nav = IntProperty(name="Navigate", + description="Navigate through this shape's vertices (0 = first vertex)", default=0, update=shape_nav) - - object.rs_shotshape_nav_start = BoolProperty(name="Start from here", + + object.rs_shotshape_nav_start = BoolProperty(name="Start from here", default=False, description="Start from this vertex (skips previous vertices)") - - object.rs_shotshape_offset = IntProperty(name="Offset", - description="Offset between frames (defines animation length)", + + object.rs_shotshape_offset = IntProperty(name="Offset", + description="Offset between frames (defines animation length)", default=1, min=1, max=200) - + object.rs_shotshape_use_frames = BoolProperty(name="Use frame range", description="Use the shot's frame range instead of the object's vertex"\ " count", default=False) @@ -180,7 +180,7 @@ def init_props(): scene.rs_main_folder = StringProperty(name="Main Folder", subtype='DIR_PATH', default="", description="Main folder in which to create the sub folders") - + scene.rs_overwrite_folders = BoolProperty(name="Overwrite", default=False, description="Overwrite existing folders (this will delete all"\ " files inside any existing folders)") @@ -208,12 +208,12 @@ def using_cycles(scn): def timeline_handler(scn, mode): global TIMELINE - + if mode == 'GET': TIMELINE["start"] = scn.frame_start TIMELINE["end"] = scn.frame_end TIMELINE["current"] = scn.frame_current - + elif mode == 'SET': scn.frame_start = TIMELINE["start"] scn.frame_end = TIMELINE["end"] @@ -222,18 +222,18 @@ def timeline_handler(scn, mode): def render_settings_handler(scn, mode, cycles_on, ob): global RENDER_SETTINGS - + if mode == 'GET': RENDER_SETTINGS["cycles_samples"] = scn.cycles.samples RENDER_SETTINGS["res_x"] = scn.render.resolution_x RENDER_SETTINGS["res_y"] = scn.render.resolution_y - + elif mode == 'SET': if cycles_on: scn.cycles.samples = ob["rs_cycles_samples"] scn.render.resolution_x = ob["rs_resolution_x"] scn.render.resolution_y = ob["rs_resolution_y"] - + elif mode == 'REVERT': if cycles_on: scn.cycles.samples = RENDER_SETTINGS["cycles_samples"] @@ -245,7 +245,7 @@ def frames_from_verts(ob, end, shape, mode): start = ob.rs_shot_start frame_range = (end - start)+1 verts = len(shape.data.vertices) - + if frame_range % verts != 0: end += 1 return create_frames_from_verts(ob, end, shape, mode) @@ -259,16 +259,16 @@ def frames_from_verts(ob, end, shape, mode): def keyframes_handler(scn, ob, shape, mode): bpy.ops.object.select_all(action='DESELECT') ob.select = True - + start = ob.rs_shotshape_nav if ob.rs_shotshape_nav_start else 0 - + if ob.rs_shotshape_use_frames and shape is not None: firstframe = ob.rs_shot_start offset = frames_from_verts(ob, ob.rs_shot_end, shape, 'OFFSET') else: firstframe = 1 offset = ob.rs_shotshape_offset - + if mode == 'SET': scn.frame_current = firstframe for vert in shape.data.vertices: @@ -277,7 +277,7 @@ def keyframes_handler(scn, ob, shape, mode): bpy.ops.anim.keyframe_insert_menu(type='Location') scn.frame_current += offset return (len(shape.data.vertices) - start) * offset - + elif mode == 'WIPE': ob.animation_data_clear() @@ -286,15 +286,15 @@ class RENDER_OT_RenderShots_create_folders(bpy.types.Operator): ''' Create the output folders for all cameras ''' bl_idname = "render.rendershots_create_folders" bl_label = "Create Folders" - + mode = IntProperty() - + def execute(self, context): scn = context.scene - + if self.mode == 1: # Display options scn.rs_create_folders = True - + elif self.mode == 2: # Create folders if scn.rs_main_folder != "" and not scn.rs_main_folder.isspace(): for ob in bpy.data.objects: @@ -305,32 +305,32 @@ class RENDER_OT_RenderShots_create_folders(bpy.types.Operator): camName = name[0]+name[1] else: camName = ob.name - + mainFolder = scn.rs_main_folder destination = os.path.join(mainFolder, camName) - + # Folder creation if scn.rs_overwrite_folders: if os.path.isdir(destination): shutil.rmtree(destination) - + os.mkdir(destination) ob.rs_shot_output = destination+"\\" else: if not os.path.isdir(destination): ob.rs_shot_output = destination+"\\" - + os.makedirs(destination_path) self.report({'INFO'}, "Output folders created") scn.rs_overwrite_folders = False scn.rs_create_folders = False else: self.report({'ERROR'}, "No main folder selected") - + elif self.mode == 3: # Cancelled scn.rs_overwrite_folders = False scn.rs_create_folders = False - + return {'FINISHED'} @@ -340,7 +340,7 @@ class RENDER_OT_RenderShots_settingshelp(bpy.types.Operator): ''' bl_idname = "render.rendershots_settingshelp" bl_label = "Render Settings Help" - + cam = StringProperty() def execute(self, context): @@ -352,7 +352,7 @@ class RENDER_OT_RenderShots_settingshelp(bpy.types.Operator): render_settings_handler(scn, 'GET', using_cycles(scn), None) context.window_manager.modal_handler_add(self) return {'RUNNING_MODAL'} - + def modal(self, context, event): scn = context.scene ob = bpy.data.objects[self.cam] @@ -362,10 +362,10 @@ class RENDER_OT_RenderShots_settingshelp(bpy.types.Operator): RENDER_SETTINGS_HELP = False render_settings_handler(scn, 'REVERT', using_cycles(scn), None) return {'FINISHED'} - + scn.render.resolution_x = ob["rs_resolution_x"] scn.render.resolution_y = ob["rs_resolution_y"] - + return {'PASS_THROUGH'} @@ -373,39 +373,39 @@ class RENDER_OT_RenderShots_constraints_add(bpy.types.Operator): ''' Add the tracking constraints and Empty for this camera ''' bl_idname = "render.rendershots_constraints_add" bl_label = "Create Constraints" - + cam = StringProperty() - + def execute(self, context): ob = bpy.data.objects[self.cam] ssName = "LookAt_for_"+ob.name - + bpy.ops.object.add(type="EMPTY") context.active_object.name = ssName - + target = bpy.data.objects[ssName] - + ob.constraints.new(type="DAMPED_TRACK").name="SS_Damped" damped_track = ob.constraints["SS_Damped"] damped_track.target = target damped_track.track_axis = 'TRACK_NEGATIVE_Z' damped_track.influence = 0.994 - + ob.constraints.new(type="LOCKED_TRACK").name="SS_Locked" locked_track = ob.constraints["SS_Locked"] locked_track.target = target locked_track.track_axis = 'TRACK_Y' locked_track.lock_axis = 'LOCK_Z' locked_track.influence = 1.0 - + return {'FINISHED'} class RENTER_OT_rendershots_refresh(bpy.types.Operator): ''' Adds newly created cameras to the list ''' bl_idname = "render.rendershots_refresh" - bl_label = "Refresh" - + bl_label = "Refresh" + def execute(self, context): update_shot_list(context.scene) return {'FINISHED'} @@ -414,16 +414,16 @@ class RENTER_OT_rendershots_refresh(bpy.types.Operator): class RENDER_OT_RenderShots_render(bpy.types.Operator): ''' Render shots ''' bl_idname = "render.rendershots_render" - bl_label = "Render" - + bl_label = "Render" + animation = BoolProperty(default=False) _timer = None _usingShape = False - + def execute(self, context): global RENDER_DONE RENDER_DONE = True - + scn = context.scene self.camList = [] self.vertTrack = -1 @@ -433,20 +433,20 @@ class RENDER_OT_RenderShots_render(bpy.types.Operator): if ob.type == 'CAMERA' and not is_new_object(ob): if ob["rs_shot_include"]: output = ob["rs_shot_output"] - + addToList = False - + if output != "" and not output.isspace(): addToList = True else: message = "\"%s\" has no output destination" % ob.name self.report({'WARNING'}, message) - + if ob["rs_shotshape_use"]: shotShape = ob["rs_shotshape_shape"] if shotShape == "": addToList = False - self.report({'WARNING'}, + self.report({'WARNING'}, "\"%s\" has no shot shape" % ob.name) elif bpy.data.objects[shotShape].type != 'MESH': errObj = bpy.data.objects[shotShape].name @@ -457,94 +457,94 @@ class RENDER_OT_RenderShots_render(bpy.types.Operator): # bpy.data.objects[shotShape].hide_render = True if addToList: self.camList.append(ob.name) - + self.camList.reverse() timeline_handler(scn, 'GET') render_settings_handler(scn, 'GET', using_cycles(scn), None) context.window_manager.modal_handler_add(self) self._timer = context.window_manager.event_timer_add(3, context.window) return {'RUNNING_MODAL'} - - + + def modal(self, context, event): global RENDER_DONE - + scn = context.scene - + if event.type in {'ESC'}: context.window_manager.event_timer_remove(self._timer) keyframes_handler(scn, bpy.data.objects[self.cam], None, 'WIPE') render_settings_handler(scn, 'REVERT', using_cycles(scn), None) timeline_handler(scn, 'SET') return {'CANCELLED'} - + if RENDER_DONE and self.camList: RENDER_DONE = False objs = bpy.data.objects range = 0 - + if self._usingShape: keyframes_handler(scn, objs[self.cam], None, 'WIPE') - + self._usingShape = False - + if not self._usingShape and self.camList: self.cam = self.camList.pop() - + ob = objs[self.cam] - + # Output and name cleaning scn.camera = ob output = ob["rs_shot_output"] - + if output[-1] == "/" or output[-1] == "\\": if "." in self.cam: camName = self.cam.split(".") output += camName[0]+camName[1] else: output += self.cam - + # Shot shapes if ob["rs_shotshape_use"]: self._usingShape = True shape = ob["rs_shotshape_shape"] range = keyframes_handler(scn, ob, objs[shape], 'SET') - + # Render settings if ob["rs_settings_use"]: render_settings_handler(scn, 'SET', using_cycles(scn), ob) else: render_settings_handler(scn, 'REVERT', using_cycles(scn), None) - + context.scene.render.filepath = output - + # Render ssUsing = ob["rs_shotshape_use"] if self.animation and not ssUsing and not self._usingShape: scn.frame_start = ob["rs_shot_start"] scn.frame_end = ob["rs_shot_end"] bpy.ops.render.render('INVOKE_DEFAULT', animation=True) - + elif self.animation and ssUsing and self._usingShape: if ob["rs_shotshape_use_frames"]: scn.frame_start = ob.rs_shot_start - scn.frame_end = frames_from_verts(ob, ob.rs_shot_end, + scn.frame_end = frames_from_verts(ob, ob.rs_shot_end, objs[shape], 'END') else: scn.frame_start = 1 scn.frame_end = range bpy.ops.render.render('INVOKE_DEFAULT', animation=True) - + elif not self.animation and not ssUsing and not self._usingShape: bpy.ops.render.render('INVOKE_DEFAULT', write_still=True) - + elif RENDER_DONE and not self.camList: context.window_manager.event_timer_remove(self._timer) keyframes_handler(scn, bpy.data.objects[self.cam], None, 'WIPE') render_settings_handler(scn, 'REVERT', using_cycles(scn), None) timeline_handler(scn, 'SET') return {'FINISHED'} - + return {'PASS_THROUGH'} @@ -552,9 +552,9 @@ class RENDER_OT_RenderShots_previewcamera(bpy.types.Operator): ''' Preview this shot (makes this the active camera in 3D View) ''' bl_idname = "render.rendershots_preview_camera" bl_label = "Preview Camera" - + camera = bpy.props.StringProperty() - + def execute(self, context): scn = context.scene cam = bpy.data.objects[self.camera] @@ -571,32 +571,32 @@ class RENDER_PT_RenderShots(bpy.types.Panel): bl_space_type = "PROPERTIES" bl_region_type = "WINDOW" bl_context = "render" - + def draw(self, context): global RENDER_SETTINGS_HELP - + layout = self.layout scn = context.scene ANI_ICO, STILL_ICO = "RENDER_ANIMATION", "RENDER_STILL" INCL_ICO = "RESTRICT_RENDER_OFF" RENDER_OP = "render.rendershots_render" - + row = layout.row() row.operator(RENDER_OP, text="Image", icon=STILL_ICO) row.operator(RENDER_OP, text="Animation", icon=ANI_ICO).animation=True - + row = layout.row() if scn.rs_create_folders: - row.operator("render.rendershots_create_folders", + row.operator("render.rendershots_create_folders", icon="FILE_TICK").mode=2 else: - row.operator("render.rendershots_create_folders", + row.operator("render.rendershots_create_folders", icon="NEWFOLDER").mode=1 - + row.operator("render.rendershots_refresh", icon="FILE_REFRESH") - + if scn.rs_create_folders: row = layout.row() col = row.column(align=True) @@ -606,38 +606,38 @@ class RENDER_PT_RenderShots(bpy.types.Panel): colrow.prop(scn, "rs_main_folder", text="") colrow = col.row() colrow.prop(scn, "rs_overwrite_folders") - colrow.operator("render.rendershots_create_folders", text="Cancel", + colrow.operator("render.rendershots_create_folders", text="Cancel", icon="X").mode=3 - + if not scn.rs_is_updating: for ob in bpy.data.objects: if ob.type == 'CAMERA' and not is_new_object(ob): TOGL_ICO = "TRIA_DOWN" if ob["rs_toggle_panel"] else "TRIA_LEFT" - + box = layout.box() box.active = ob["rs_shot_include"] col = box.column() row = col.row() row.label(text="\""+ob.name+"\"") - row.operator("render.rendershots_preview_camera", text="", + row.operator("render.rendershots_preview_camera", text="", icon="OUTLINER_OB_CAMERA").camera=ob.name row.prop(ob, "rs_shotshape_use", icon="MESH_DATA") row.prop(ob, "rs_settings_use", icon="SETTINGS") row.prop(ob, "rs_shot_include", icon=INCL_ICO) row.prop(ob, "rs_toggle_panel", icon=TOGL_ICO, emboss=False) - + if ob["rs_toggle_panel"]: col.separator() row = col.row() rowbox = row.box() col = rowbox.column() - + if ob["rs_shotshape_use"]: row = col.row() row.label(text="Shot Shape:") row = col.row() - row.prop_search(ob, "rs_shotshape_shape", - scn, "objects", text="", + row.prop_search(ob, "rs_shotshape_shape", + scn, "objects", text="", icon="OBJECT_DATA") row = col.row(align=True) row.prop(ob, "rs_shotshape_nav") @@ -646,10 +646,10 @@ class RENDER_PT_RenderShots(bpy.types.Panel): row.prop(ob, "rs_shotshape_offset") row.prop(ob, "rs_shotshape_use_frames") row = col.row() - row.operator("render.rendershots_constraints_add", + row.operator("render.rendershots_constraints_add", icon="CONSTRAINT_DATA").cam=ob.name col.separator() - + if ob["rs_settings_use"]: row = col.row() row.label(text="Render Settings:") @@ -657,21 +657,21 @@ class RENDER_PT_RenderShots(bpy.types.Panel): rowcol = row.column(align=True) rowcol.prop(ob, "rs_resolution_x") rowcol.prop(ob, "rs_resolution_y") - + rowcol = row.column() if not RENDER_SETTINGS_HELP: - rowcol.operator("render.rendershots_settingshelp", + rowcol.operator("render.rendershots_settingshelp", text="", icon="HELP").cam=ob.name else: rowcol.label(icon="TIME") - + if using_cycles(scn): rowcol.prop(ob, "rs_cycles_samples") else: rowcol.label() - + col.separator() - + row = col.row() row.label(text="Shot Settings:") row = col.row(align=True) @@ -691,23 +691,23 @@ def register(): def unregister(): bpy.app.handlers.render_complete.remove(render_finished) bpy.utils.unregister_module(__name__) - + object = bpy.types.Object scene = bpy.types.Scene - + # Camera properties del object.rs_shot_include del object.rs_shot_start del object.rs_shot_end del object.rs_shot_output del object.rs_toggle_panel - + # Render settings del object.rs_settings_use del object.rs_resolution_x del object.rs_resolution_y del object.rs_cycles_samples - + # Shot shapes del object.rs_shotshape_use del object.rs_shotshape_shape diff --git a/space_view3d_enhanced_3d_cursor.py b/space_view3d_enhanced_3d_cursor.py index 4cdacdb801c7076cf67696dcf443e68ae92a0f5f..583bbd72a4aa1e0adde9697d7267e466fabe0603 100644 --- a/space_view3d_enhanced_3d_cursor.py +++ b/space_view3d_enhanced_3d_cursor.py @@ -4405,7 +4405,7 @@ class SnapCursor_Circumscribed(bpy.types.Operator): self.report({'WARNING'}, 'Not implemented \ for %s mode' % context.mode) return {'CANCELLED'} - + pos = center_of_circumscribed_circle(vecs) if pos is None: self.report({'WARNING'}, 'Select 3 objects/elements') @@ -4426,7 +4426,7 @@ class SnapCursor_Inscribed(bpy.types.Operator): self.report({'WARNING'}, 'Not implemented \ for %s mode' % context.mode) return {'CANCELLED'} - + pos = center_of_inscribed_circle(vecs) if pos is None: self.report({'WARNING'}, 'Select 3 objects/elements') @@ -4686,7 +4686,7 @@ class CursorMonitor(bpy.types.Operator): if IsKeyMapItemEvent(kmi, event): self.cancel(context) return {'CANCELLED'} - + try: return self._modal(context, event) except Exception as e: @@ -4719,7 +4719,7 @@ class CursorMonitor(bpy.types.Operator): context.area.tag_redraw() settings = find_settings() - + propagate_settings_to_all_screens(settings) # ================== # @@ -5673,7 +5673,7 @@ def register(): bpy.types.VIEW3D_MT_snap.append(extra_snap_menu_draw) bpy.app.handlers.scene_update_post.append(scene_update_post_kmreg) - + bpy.app.handlers.load_post.append(scene_load_post) @@ -5706,7 +5706,7 @@ def unregister(): #bpy.types.VIEW3D_PT_view3d_properties.remove(draw_cursor_tools) bpy.types.VIEW3D_MT_snap.remove(extra_snap_menu_draw) - + bpy.app.handlers.load_post.remove(scene_load_post) diff --git a/space_view3d_library_hide.py b/space_view3d_library_hide.py index c85028df45f34ab17d87b00f649eae0cef2e4241..e14c1169f4b944df5e666f728175aaffa3c13bab 100644 --- a/space_view3d_library_hide.py +++ b/space_view3d_library_hide.py @@ -131,7 +131,7 @@ def pick_object(context, event, pick_objects, ray_max=10000.0): pick_objects.append((best_obj, best_obj.hide, best_obj.hide_render)) best_obj.hide = True best_obj.hide_render = True - + #if best_obj_parent: # best_obj_parent.update_tag(refresh={'OBJECT'}) #scene.update() @@ -152,23 +152,23 @@ def pick_finalize(context, pick_objects): if is_new: data = [] - + data += LIB_HIDE_TEXT_HEADER.split("\n") else: data = text.as_string().split("\n") data.append("# ---") - + for pick_obj_tuple in pick_objects: - + pick_obj = pick_obj_tuple[0] - + pick_obj.hide = True pick_obj.hide_render = True line = "hide(%r, %s)" % (pick_obj.name, repr(pick_obj.library.filepath) if pick_obj.library is not None else "None") data.append(line) - + text.from_string("\n".join(data)) @@ -218,7 +218,7 @@ class ViewOperatorRayCast(bpy.types.Operator): context.area.header_text_set() self.report({'INFO'}, "Finished") return {'FINISHED'} - + elif event.type in {'RIGHTMOUSE', 'ESC'}: if event.value == 'RELEASE': for pick_obj in self.pick_objects: @@ -231,7 +231,7 @@ class ViewOperatorRayCast(bpy.types.Operator): def invoke(self, context, event): if context.space_data.type == 'VIEW_3D': - + self.pick_objects = [] self._update_header(context) diff --git a/space_view3d_quickPrefs.py b/space_view3d_quickPrefs.py index 77b0987c80923d184309ec09c6fdd1ebdd41f914..3ccf3dbc10e5004281d58c9d537fa4379cc280a2 100644 --- a/space_view3d_quickPrefs.py +++ b/space_view3d_quickPrefs.py @@ -962,8 +962,7 @@ def unregister(): bpy.utils.unregister_class(gllightpreset) bpy.utils.unregister_class(SCENE_OT_gllightpreset) bpy.utils.unregister_class(quickprefproperties) - bpy.app.handlers.scene_update_pre.remove(setup) + bpy.app.handlers.scene_update_pre.remove(setup) if __name__ == "__main__": register() - diff --git a/sun_position/map.py b/sun_position/map.py index 129b3c3c3a15632a1124714a3bb49ce0619a92ce..5669aea4d853c114dd60ee78696e1e394380f57f 100644 --- a/sun_position/map.py +++ b/sun_position/map.py @@ -249,7 +249,7 @@ class MapClass: return True else: self.textureless = False - + # S.L. fix to use any relative path dir_path = os.path.dirname(os.path.realpath(__file__)) self.image.name = dir_path + os.path.sep + file_name diff --git a/sun_position/operators.py b/sun_position/operators.py index 600c4bd16819479f3e17a2d46f79e378f2a2f7f2..ca163d275e289786bc411b0b388bb5b17229a2ee 100644 --- a/sun_position/operators.py +++ b/sun_position/operators.py @@ -162,7 +162,7 @@ class SunPos_OT_Controller(bpy.types.Operator): Sun.SP.IsActive = False except: pass - + def modal(self, context, event): if Display.PANEL: diff --git a/sun_position/properties.py b/sun_position/properties.py index 468cde11e539490803cdf0b09fbba985d56e4a06..1d140a1c06505209ba4f4a7c8d67ad1516d29ea7 100644 --- a/sun_position/properties.py +++ b/sun_position/properties.py @@ -306,7 +306,7 @@ class SunPosSettings(PropertyGroup): class SunPosPreferences(PropertyGroup): - + UsageMode = EnumProperty( name="Usage mode", description="operate in normal mode or environment texture mode", diff --git a/text_editor_hastebin.py b/text_editor_hastebin.py index 1c40d8498f142620bf4e4ba3383c78937ded2868..9c97a70d3c6ce04fbfef78ca167ba470ba3fe3b0 100644 --- a/text_editor_hastebin.py +++ b/text_editor_hastebin.py @@ -165,4 +165,3 @@ def unregister(): if __name__ == "__main__": register() -