diff options
229 files changed, 7 insertions, 94278 deletions
diff --git a/SConstruct b/SConstruct index 7e3d23970cb..5c4af916327 100644 --- a/SConstruct +++ b/SConstruct @@ -476,8 +476,8 @@ if env['OURPLATFORM']!='darwin': dotblenderinstall.append(env.Install(dir=td, source=srcfile)) if env['WITH_BF_PYTHON']: - #-- .blender/scripts, .blender/ui, .blender/io - scriptpaths=['release/scripts', 'release/ui', 'release/io'] + #-- .blender/scripts + scriptpaths=['release/scripts'] for scriptpath in scriptpaths: for dp, dn, df in os.walk(scriptpath): if '.svn' in dn: diff --git a/release/Makefile b/release/Makefile index 94bb902646d..9fe83ef3494 100644 --- a/release/Makefile +++ b/release/Makefile @@ -153,9 +153,6 @@ endif @echo "----> Copy python infrastructure" @[ ! -d scripts ] || cp -r scripts $(CONFDIR)/scripts - - @echo "----> Copy python UI files" - @[ ! -d ui ] || cp -r ui $(CONFDIR)/ui ifeq ($(OS),darwin) @echo "----> Copy python modules" diff --git a/release/scripts/3ds_export.py b/release/scripts/3ds_export.py deleted file mode 100644 index 87680bce1b0..00000000000 --- a/release/scripts/3ds_export.py +++ /dev/null @@ -1,1019 +0,0 @@ -#!BPY -# coding: utf-8 -""" -Name: '3D Studio (.3ds)...' -Blender: 243 -Group: 'Export' -Tooltip: 'Export to 3DS file format (.3ds).' -""" - -__author__ = ["Campbell Barton", "Bob Holcomb", "Richard Lärkäng", "Damien McGinnes", "Mark Stijnman"] -__url__ = ("blenderartists.org", "www.blender.org", "www.gametutorials.com", "lib3ds.sourceforge.net/") -__version__ = "0.90a" -__bpydoc__ = """\ - -3ds Exporter - -This script Exports a 3ds file. - -Exporting is based on 3ds loader from www.gametutorials.com(Thanks DigiBen) and using information -from the lib3ds project (http://lib3ds.sourceforge.net/) sourcecode. -""" - -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Script copyright (C) Bob Holcomb -# -# 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 ***** -# -------------------------------------------------------------------------- - - -###################################################### -# Importing modules -###################################################### - -import Blender -import bpy -from BPyMesh import getMeshFromObject -from BPyObject import getDerivedObjects -try: - import struct -except: - struct = None - -# So 3ds max can open files, limit names to 12 in length -# this is verry annoying for filenames! -name_unique = [] -name_mapping = {} -def sane_name(name): - name_fixed = name_mapping.get(name) - if name_fixed != None: - return name_fixed - - if len(name) > 12: - new_name = name[:12] - else: - new_name = name - - i = 0 - - while new_name in name_unique: - new_name = new_name[:-4] + '.%.3d' % i - i+=1 - - name_unique.append(new_name) - name_mapping[name] = new_name - return new_name - -###################################################### -# Data Structures -###################################################### - -#Some of the chunks that we will export -#----- Primary Chunk, at the beginning of each file -PRIMARY= long("0x4D4D",16) - -#------ Main Chunks -OBJECTINFO = long("0x3D3D",16); #This gives the version of the mesh and is found right before the material and object information -VERSION = long("0x0002",16); #This gives the version of the .3ds file -KFDATA = long("0xB000",16); #This is the header for all of the key frame info - -#------ sub defines of OBJECTINFO -MATERIAL=45055 #0xAFFF // This stored the texture info -OBJECT=16384 #0x4000 // This stores the faces, vertices, etc... - -#>------ sub defines of MATERIAL -MATNAME = long("0xA000",16); # This holds the material name -MATAMBIENT = long("0xA010",16); # Ambient color of the object/material -MATDIFFUSE = long("0xA020",16); # This holds the color of the object/material -MATSPECULAR = long("0xA030",16); # SPecular color of the object/material -MATSHINESS = long("0xA040",16); # ?? -MATMAP = long("0xA200",16); # This is a header for a new material -MATMAPFILE = long("0xA300",16); # This holds the file name of the texture - -RGB1= long("0x0011",16) -RGB2= long("0x0012",16) - -#>------ sub defines of OBJECT -OBJECT_MESH = long("0x4100",16); # This lets us know that we are reading a new object -OBJECT_LIGHT = long("0x4600",16); # This lets un know we are reading a light object -OBJECT_CAMERA= long("0x4700",16); # This lets un know we are reading a camera object - -#>------ sub defines of CAMERA -OBJECT_CAM_RANGES= long("0x4720",16); # The camera range values - -#>------ sub defines of OBJECT_MESH -OBJECT_VERTICES = long("0x4110",16); # The objects vertices -OBJECT_FACES = long("0x4120",16); # The objects faces -OBJECT_MATERIAL = long("0x4130",16); # This is found if the object has a material, either texture map or color -OBJECT_UV = long("0x4140",16); # The UV texture coordinates -OBJECT_TRANS_MATRIX = long("0x4160",16); # The Object Matrix - -#>------ sub defines of KFDATA -KFDATA_KFHDR = long("0xB00A",16); -KFDATA_KFSEG = long("0xB008",16); -KFDATA_KFCURTIME = long("0xB009",16); -KFDATA_OBJECT_NODE_TAG = long("0xB002",16); - -#>------ sub defines of OBJECT_NODE_TAG -OBJECT_NODE_ID = long("0xB030",16); -OBJECT_NODE_HDR = long("0xB010",16); -OBJECT_PIVOT = long("0xB013",16); -OBJECT_INSTANCE_NAME = long("0xB011",16); -POS_TRACK_TAG = long("0xB020",16); -ROT_TRACK_TAG = long("0xB021",16); -SCL_TRACK_TAG = long("0xB022",16); - -def uv_key(uv): - return round(uv.x, 6), round(uv.y, 6) - -# size defines: -SZ_SHORT = 2 -SZ_INT = 4 -SZ_FLOAT = 4 - -class _3ds_short(object): - '''Class representing a short (2-byte integer) for a 3ds file. - *** This looks like an unsigned short H is unsigned from the struct docs - Cam***''' - __slots__ = 'value' - def __init__(self, val=0): - self.value=val - - def get_size(self): - return SZ_SHORT - - def write(self,file): - file.write(struct.pack("<H", self.value)) - - def __str__(self): - return str(self.value) - -class _3ds_int(object): - '''Class representing an int (4-byte integer) for a 3ds file.''' - __slots__ = 'value' - def __init__(self, val=0): - self.value=val - - def get_size(self): - return SZ_INT - - def write(self,file): - file.write(struct.pack("<I", self.value)) - - def __str__(self): - return str(self.value) - -class _3ds_float(object): - '''Class representing a 4-byte IEEE floating point number for a 3ds file.''' - __slots__ = 'value' - def __init__(self, val=0.0): - self.value=val - - def get_size(self): - return SZ_FLOAT - - def write(self,file): - file.write(struct.pack("<f", self.value)) - - def __str__(self): - return str(self.value) - - -class _3ds_string(object): - '''Class representing a zero-terminated string for a 3ds file.''' - __slots__ = 'value' - def __init__(self, val=""): - self.value=val - - def get_size(self): - return (len(self.value)+1) - - def write(self,file): - binary_format = "<%ds" % (len(self.value)+1) - file.write(struct.pack(binary_format, self.value)) - - def __str__(self): - return self.value - -class _3ds_point_3d(object): - '''Class representing a three-dimensional point for a 3ds file.''' - __slots__ = 'x','y','z' - def __init__(self, point=(0.0,0.0,0.0)): - self.x, self.y, self.z = point - - def get_size(self): - return 3*SZ_FLOAT - - def write(self,file): - file.write(struct.pack('<3f', self.x, self.y, self.z)) - - def __str__(self): - return '(%f, %f, %f)' % (self.x, self.y, self.z) - -# Used for writing a track -""" -class _3ds_point_4d(object): - '''Class representing a four-dimensional point for a 3ds file, for instance a quaternion.''' - __slots__ = 'x','y','z','w' - def __init__(self, point=(0.0,0.0,0.0,0.0)): - self.x, self.y, self.z, self.w = point - - def get_size(self): - return 4*SZ_FLOAT - - def write(self,file): - data=struct.pack('<4f', self.x, self.y, self.z, self.w) - file.write(data) - - def __str__(self): - return '(%f, %f, %f, %f)' % (self.x, self.y, self.z, self.w) -""" - -class _3ds_point_uv(object): - '''Class representing a UV-coordinate for a 3ds file.''' - __slots__ = 'uv' - def __init__(self, point=(0.0,0.0)): - self.uv = point - - def __cmp__(self, other): - return cmp(self.uv,other.uv) - - def get_size(self): - return 2*SZ_FLOAT - - def write(self,file): - data=struct.pack('<2f', self.uv[0], self.uv[1]) - file.write(data) - - def __str__(self): - return '(%g, %g)' % self.uv - -class _3ds_rgb_color(object): - '''Class representing a (24-bit) rgb color for a 3ds file.''' - __slots__ = 'r','g','b' - def __init__(self, col=(0,0,0)): - self.r, self.g, self.b = col - - def get_size(self): - return 3 - - def write(self,file): - file.write( struct.pack('<3c', chr(int(255*self.r)), chr(int(255*self.g)), chr(int(255*self.b)) ) ) - - def __str__(self): - return '{%f, %f, %f}' % (self.r, self.g, self.b) - -class _3ds_face(object): - '''Class representing a face for a 3ds file.''' - __slots__ = 'vindex' - def __init__(self, vindex): - self.vindex = vindex - - def get_size(self): - return 4*SZ_SHORT - - def write(self,file): - # The last zero is only used by 3d studio - file.write(struct.pack("<4H", self.vindex[0],self.vindex[1], self.vindex[2], 0)) - - def __str__(self): - return '[%d %d %d]' % (self.vindex[0],self.vindex[1], self.vindex[2]) - -class _3ds_array(object): - '''Class representing an array of variables for a 3ds file. - - Consists of a _3ds_short to indicate the number of items, followed by the items themselves. - ''' - __slots__ = 'values', 'size' - def __init__(self): - self.values=[] - self.size=SZ_SHORT - - # add an item: - def add(self,item): - self.values.append(item) - self.size+=item.get_size() - - def get_size(self): - return self.size - - def write(self,file): - _3ds_short(len(self.values)).write(file) - #_3ds_int(len(self.values)).write(file) - for value in self.values: - value.write(file) - - # To not overwhelm the output in a dump, a _3ds_array only - # outputs the number of items, not all of the actual items. - def __str__(self): - return '(%d items)' % len(self.values) - -class _3ds_named_variable(object): - '''Convenience class for named variables.''' - - __slots__ = 'value', 'name' - def __init__(self, name, val=None): - self.name=name - self.value=val - - def get_size(self): - if (self.value==None): - return 0 - else: - return self.value.get_size() - - def write(self, file): - if (self.value!=None): - self.value.write(file) - - def dump(self,indent): - if (self.value!=None): - spaces="" - for i in xrange(indent): - spaces+=" "; - if (self.name!=""): - print spaces, self.name, " = ", self.value - else: - print spaces, "[unnamed]", " = ", self.value - - -#the chunk class -class _3ds_chunk(object): - '''Class representing a chunk in a 3ds file. - - Chunks contain zero or more variables, followed by zero or more subchunks. - ''' - __slots__ = 'ID', 'size', 'variables', 'subchunks' - def __init__(self, id=0): - self.ID=_3ds_short(id) - self.size=_3ds_int(0) - self.variables=[] - self.subchunks=[] - - def set_ID(id): - self.ID=_3ds_short(id) - - def add_variable(self, name, var): - '''Add a named variable. - - The name is mostly for debugging purposes.''' - self.variables.append(_3ds_named_variable(name,var)) - - def add_subchunk(self, chunk): - '''Add a subchunk.''' - self.subchunks.append(chunk) - - def get_size(self): - '''Calculate the size of the chunk and return it. - - The sizes of the variables and subchunks are used to determine this chunk\'s size.''' - tmpsize=self.ID.get_size()+self.size.get_size() - for variable in self.variables: - tmpsize+=variable.get_size() - for subchunk in self.subchunks: - tmpsize+=subchunk.get_size() - self.size.value=tmpsize - return self.size.value - - def write(self, file): - '''Write the chunk to a file. - - Uses the write function of the variables and the subchunks to do the actual work.''' - #write header - self.ID.write(file) - self.size.write(file) - for variable in self.variables: - variable.write(file) - for subchunk in self.subchunks: - subchunk.write(file) - - - def dump(self, indent=0): - '''Write the chunk to a file. - - Dump is used for debugging purposes, to dump the contents of a chunk to the standard output. - Uses the dump function of the named variables and the subchunks to do the actual work.''' - spaces="" - for i in xrange(indent): - spaces+=" "; - print spaces, "ID=", hex(self.ID.value), "size=", self.get_size() - for variable in self.variables: - variable.dump(indent+1) - for subchunk in self.subchunks: - subchunk.dump(indent+1) - - - -###################################################### -# EXPORT -###################################################### - -def get_material_images(material): - # blender utility func. - images = [] - if material: - for mtex in material.getTextures(): - if mtex and mtex.tex.type == Blender.Texture.Types.IMAGE: - image = mtex.tex.image - if image: - images.append(image) # maye want to include info like diffuse, spec here. - return images - -def make_material_subchunk(id, color): - '''Make a material subchunk. - - Used for color subchunks, such as diffuse color or ambient color subchunks.''' - mat_sub = _3ds_chunk(id) - col1 = _3ds_chunk(RGB1) - col1.add_variable("color1", _3ds_rgb_color(color)); - mat_sub.add_subchunk(col1) -# optional: -# col2 = _3ds_chunk(RGB1) -# col2.add_variable("color2", _3ds_rgb_color(color)); -# mat_sub.add_subchunk(col2) - return mat_sub - - -def make_material_texture_chunk(id, images): - """Make Material Map texture chunk - """ - mat_sub = _3ds_chunk(id) - - def add_image(img): - filename = image.filename.split('\\')[-1].split('/')[-1] - mat_sub_file = _3ds_chunk(MATMAPFILE) - mat_sub_file.add_variable("mapfile", _3ds_string(sane_name(filename))) - mat_sub.add_subchunk(mat_sub_file) - - for image in images: - add_image(image) - - return mat_sub - -def make_material_chunk(material, image): - '''Make a material chunk out of a blender material.''' - material_chunk = _3ds_chunk(MATERIAL) - name = _3ds_chunk(MATNAME) - - if material: name_str = material.name - else: name_str = 'None' - if image: name_str += image.name - - name.add_variable("name", _3ds_string(sane_name(name_str))) - material_chunk.add_subchunk(name) - - if not material: - material_chunk.add_subchunk(make_material_subchunk(MATAMBIENT, (0,0,0) )) - material_chunk.add_subchunk(make_material_subchunk(MATDIFFUSE, (.8, .8, .8) )) - material_chunk.add_subchunk(make_material_subchunk(MATSPECULAR, (1,1,1) )) - - else: - material_chunk.add_subchunk(make_material_subchunk(MATAMBIENT, [a*material.amb for a in material.rgbCol] )) - material_chunk.add_subchunk(make_material_subchunk(MATDIFFUSE, material.rgbCol)) - material_chunk.add_subchunk(make_material_subchunk(MATSPECULAR, material.specCol)) - - images = get_material_images(material) # can be None - if image: images.append(image) - - if images: - material_chunk.add_subchunk(make_material_texture_chunk(MATMAP, images)) - - return material_chunk - -class tri_wrapper(object): - '''Class representing a triangle. - - Used when converting faces to triangles''' - - __slots__ = 'vertex_index', 'mat', 'image', 'faceuvs', 'offset' - def __init__(self, vindex=(0,0,0), mat=None, image=None, faceuvs=None): - self.vertex_index= vindex - self.mat= mat - self.image= image - self.faceuvs= faceuvs - self.offset= [0, 0, 0] # offset indicies - - -def extract_triangles(mesh): - '''Extract triangles from a mesh. - - If the mesh contains quads, they will be split into triangles.''' - tri_list = [] - do_uv = mesh.faceUV - - if not do_uv: - face_uv = None - - img = None - for face in mesh.faces: - f_v = face.v - - if do_uv: - f_uv = face.uv - img = face.image - if img: img = img.name - - if len(f_v)==3: - new_tri = tri_wrapper((f_v[0].index, f_v[1].index, f_v[2].index), face.mat, img) - if (do_uv): new_tri.faceuvs= uv_key(f_uv[0]), uv_key(f_uv[1]), uv_key(f_uv[2]) - tri_list.append(new_tri) - - else: #it's a quad - new_tri = tri_wrapper((f_v[0].index, f_v[1].index, f_v[2].index), face.mat, img) - new_tri_2 = tri_wrapper((f_v[0].index, f_v[2].index, f_v[3].index), face.mat, img) - - if (do_uv): - new_tri.faceuvs= uv_key(f_uv[0]), uv_key(f_uv[1]), uv_key(f_uv[2]) - new_tri_2.faceuvs= uv_key(f_uv[0]), uv_key(f_uv[2]), uv_key(f_uv[3]) - - tri_list.append( new_tri ) - tri_list.append( new_tri_2 ) - - return tri_list - - -def remove_face_uv(verts, tri_list): - '''Remove face UV coordinates from a list of triangles. - - Since 3ds files only support one pair of uv coordinates for each vertex, face uv coordinates - need to be converted to vertex uv coordinates. That means that vertices need to be duplicated when - there are multiple uv coordinates per vertex.''' - - # initialize a list of UniqueLists, one per vertex: - #uv_list = [UniqueList() for i in xrange(len(verts))] - unique_uvs= [{} for i in xrange(len(verts))] - - # for each face uv coordinate, add it to the UniqueList of the vertex - for tri in tri_list: - for i in xrange(3): - # store the index into the UniqueList for future reference: - # offset.append(uv_list[tri.vertex_index[i]].add(_3ds_point_uv(tri.faceuvs[i]))) - - context_uv_vert= unique_uvs[tri.vertex_index[i]] - uvkey= tri.faceuvs[i] - - offset_index__uv_3ds = context_uv_vert.get(uvkey) - - if not offset_index__uv_3ds: - offset_index__uv_3ds = context_uv_vert[uvkey] = len(context_uv_vert), _3ds_point_uv(uvkey) - - tri.offset[i] = offset_index__uv_3ds[0] - - - - # At this point, each vertex has a UniqueList containing every uv coordinate that is associated with it - # only once. - - # Now we need to duplicate every vertex as many times as it has uv coordinates and make sure the - # faces refer to the new face indices: - vert_index = 0 - vert_array = _3ds_array() - uv_array = _3ds_array() - index_list = [] - for i,vert in enumerate(verts): - index_list.append(vert_index) - - pt = _3ds_point_3d(vert.co) # reuse, should be ok - uvmap = [None] * len(unique_uvs[i]) - for ii, uv_3ds in unique_uvs[i].itervalues(): - # add a vertex duplicate to the vertex_array for every uv associated with this vertex: - vert_array.add(pt) - # add the uv coordinate to the uv array: - # This for loop does not give uv's ordered by ii, so we create a new map - # and add the uv's later - # uv_array.add(uv_3ds) - uvmap[ii] = uv_3ds - - # Add the uv's in the correct order - for uv_3ds in uvmap: - # add the uv coordinate to the uv array: - uv_array.add(uv_3ds) - - vert_index += len(unique_uvs[i]) - - # Make sure the triangle vertex indices now refer to the new vertex list: - for tri in tri_list: - for i in xrange(3): - tri.offset[i]+=index_list[tri.vertex_index[i]] - tri.vertex_index= tri.offset - - return vert_array, uv_array, tri_list - -def make_faces_chunk(tri_list, mesh, materialDict): - '''Make a chunk for the faces. - - Also adds subchunks assigning materials to all faces.''' - - materials = mesh.materials - if not materials: - mat = None - - face_chunk = _3ds_chunk(OBJECT_FACES) - face_list = _3ds_array() - - - if mesh.faceUV: - # Gather materials used in this mesh - mat/image pairs - unique_mats = {} - for i,tri in enumerate(tri_list): - - face_list.add(_3ds_face(tri.vertex_index)) - - if materials: - mat = materials[tri.mat] - if mat: mat = mat.name - - img = tri.image - - try: - context_mat_face_array = unique_mats[mat, img][1] - except: - - if mat: name_str = mat - else: name_str = 'None' - if img: name_str += img - - context_mat_face_array = _3ds_array() - unique_mats[mat, img] = _3ds_string(sane_name(name_str)), context_mat_face_array - - - context_mat_face_array.add(_3ds_short(i)) - # obj_material_faces[tri.mat].add(_3ds_short(i)) - - face_chunk.add_variable("faces", face_list) - for mat_name, mat_faces in unique_mats.itervalues(): - obj_material_chunk=_3ds_chunk(OBJECT_MATERIAL) - obj_material_chunk.add_variable("name", mat_name) - obj_material_chunk.add_variable("face_list", mat_faces) - face_chunk.add_subchunk(obj_material_chunk) - - else: - - obj_material_faces=[] - obj_material_names=[] - for m in materials: - if m: - obj_material_names.append(_3ds_string(sane_name(m.name))) - obj_material_faces.append(_3ds_array()) - n_materials = len(obj_material_names) - - for i,tri in enumerate(tri_list): - face_list.add(_3ds_face(tri.vertex_index)) - if (tri.mat < n_materials): - obj_material_faces[tri.mat].add(_3ds_short(i)) - - face_chunk.add_variable("faces", face_list) - for i in xrange(n_materials): - obj_material_chunk=_3ds_chunk(OBJECT_MATERIAL) - obj_material_chunk.add_variable("name", obj_material_names[i]) - obj_material_chunk.add_variable("face_list", obj_material_faces[i]) - face_chunk.add_subchunk(obj_material_chunk) - - return face_chunk - -def make_vert_chunk(vert_array): - '''Make a vertex chunk out of an array of vertices.''' - vert_chunk = _3ds_chunk(OBJECT_VERTICES) - vert_chunk.add_variable("vertices",vert_array) - return vert_chunk - -def make_uv_chunk(uv_array): - '''Make a UV chunk out of an array of UVs.''' - uv_chunk = _3ds_chunk(OBJECT_UV) - uv_chunk.add_variable("uv coords", uv_array) - return uv_chunk - -def make_mesh_chunk(mesh, materialDict): - '''Make a chunk out of a Blender mesh.''' - - # Extract the triangles from the mesh: - tri_list = extract_triangles(mesh) - - if mesh.faceUV: - # Remove the face UVs and convert it to vertex UV: - vert_array, uv_array, tri_list = remove_face_uv(mesh.verts, tri_list) - else: - # Add the vertices to the vertex array: - vert_array = _3ds_array() - for vert in mesh.verts: - vert_array.add(_3ds_point_3d(vert.co)) - # If the mesh has vertex UVs, create an array of UVs: - if mesh.vertexUV: - uv_array = _3ds_array() - for vert in mesh.verts: - uv_array.add(_3ds_point_uv(vert.uvco)) - else: - # no UV at all: - uv_array = None - - # create the chunk: - mesh_chunk = _3ds_chunk(OBJECT_MESH) - - # add vertex chunk: - mesh_chunk.add_subchunk(make_vert_chunk(vert_array)) - # add faces chunk: - - mesh_chunk.add_subchunk(make_faces_chunk(tri_list, mesh, materialDict)) - - # if available, add uv chunk: - if uv_array: - mesh_chunk.add_subchunk(make_uv_chunk(uv_array)) - - return mesh_chunk - -""" # COMMENTED OUT FOR 2.42 RELEASE!! CRASHES 3DS MAX -def make_kfdata(start=0, stop=0, curtime=0): - '''Make the basic keyframe data chunk''' - kfdata = _3ds_chunk(KFDATA) - - kfhdr = _3ds_chunk(KFDATA_KFHDR) - kfhdr.add_variable("revision", _3ds_short(0)) - # Not really sure what filename is used for, but it seems it is usually used - # to identify the program that generated the .3ds: - kfhdr.add_variable("filename", _3ds_string("Blender")) - kfhdr.add_variable("animlen", _3ds_int(stop-start)) - - kfseg = _3ds_chunk(KFDATA_KFSEG) - kfseg.add_variable("start", _3ds_int(start)) - kfseg.add_variable("stop", _3ds_int(stop)) - - kfcurtime = _3ds_chunk(KFDATA_KFCURTIME) - kfcurtime.add_variable("curtime", _3ds_int(curtime)) - - kfdata.add_subchunk(kfhdr) - kfdata.add_subchunk(kfseg) - kfdata.add_subchunk(kfcurtime) - return kfdata -""" - -""" -def make_track_chunk(ID, obj): - '''Make a chunk for track data. - - Depending on the ID, this will construct a position, rotation or scale track.''' - track_chunk = _3ds_chunk(ID) - track_chunk.add_variable("track_flags", _3ds_short()) - track_chunk.add_variable("unknown", _3ds_int()) - track_chunk.add_variable("unknown", _3ds_int()) - track_chunk.add_variable("nkeys", _3ds_int(1)) - # Next section should be repeated for every keyframe, but for now, animation is not actually supported. - track_chunk.add_variable("tcb_frame", _3ds_int(0)) - track_chunk.add_variable("tcb_flags", _3ds_short()) - if obj.type=='Empty': - if ID==POS_TRACK_TAG: - # position vector: - track_chunk.add_variable("position", _3ds_point_3d(obj.getLocation())) - elif ID==ROT_TRACK_TAG: - # rotation (quaternion, angle first, followed by axis): - q = obj.getEuler().toQuat() - track_chunk.add_variable("rotation", _3ds_point_4d((q.angle, q.axis[0], q.axis[1], q.axis[2]))) - elif ID==SCL_TRACK_TAG: - # scale vector: - track_chunk.add_variable("scale", _3ds_point_3d(obj.getSize())) - else: - # meshes have their transformations applied before - # exporting, so write identity transforms here: - if ID==POS_TRACK_TAG: - # position vector: - track_chunk.add_variable("position", _3ds_point_3d((0.0,0.0,0.0))) - elif ID==ROT_TRACK_TAG: - # rotation (quaternion, angle first, followed by axis): - track_chunk.add_variable("rotation", _3ds_point_4d((0.0, 1.0, 0.0, 0.0))) - elif ID==SCL_TRACK_TAG: - # scale vector: - track_chunk.add_variable("scale", _3ds_point_3d((1.0, 1.0, 1.0))) - - return track_chunk -""" - -""" -def make_kf_obj_node(obj, name_to_id): - '''Make a node chunk for a Blender object. - - Takes the Blender object as a parameter. Object id's are taken from the dictionary name_to_id. - Blender Empty objects are converted to dummy nodes.''' - - name = obj.name - # main object node chunk: - kf_obj_node = _3ds_chunk(KFDATA_OBJECT_NODE_TAG) - # chunk for the object id: - obj_id_chunk = _3ds_chunk(OBJECT_NODE_ID) - # object id is from the name_to_id dictionary: - obj_id_chunk.add_variable("node_id", _3ds_short(name_to_id[name])) - - # object node header: - obj_node_header_chunk = _3ds_chunk(OBJECT_NODE_HDR) - # object name: - if obj.type == 'Empty': - # Empties are called "$$$DUMMY" and use the OBJECT_INSTANCE_NAME chunk - # for their name (see below): - obj_node_header_chunk.add_variable("name", _3ds_string("$$$DUMMY")) - else: - # Add the name: - obj_node_header_chunk.add_variable("name", _3ds_string(sane_name(name))) - # Add Flag variables (not sure what they do): - obj_node_header_chunk.add_variable("flags1", _3ds_short(0)) - obj_node_header_chunk.add_variable("flags2", _3ds_short(0)) - - # Check parent-child relationships: - parent = obj.parent - if (parent == None) or (parent.name not in name_to_id): - # If no parent, or the parents name is not in the name_to_id dictionary, - # parent id becomes -1: - obj_node_header_chunk.add_variable("parent", _3ds_short(-1)) - else: - # Get the parent's id from the name_to_id dictionary: - obj_node_header_chunk.add_variable("parent", _3ds_short(name_to_id[parent.name])) - - # Add pivot chunk: - obj_pivot_chunk = _3ds_chunk(OBJECT_PIVOT) - obj_pivot_chunk.add_variable("pivot", _3ds_point_3d(obj.getLocation())) - kf_obj_node.add_subchunk(obj_pivot_chunk) - - # add subchunks for object id and node header: - kf_obj_node.add_subchunk(obj_id_chunk) - kf_obj_node.add_subchunk(obj_node_header_chunk) - - # Empty objects need to have an extra chunk for the instance name: - if obj.type == 'Empty': - obj_instance_name_chunk = _3ds_chunk(OBJECT_INSTANCE_NAME) - obj_instance_name_chunk.add_variable("name", _3ds_string(sane_name(name))) - kf_obj_node.add_subchunk(obj_instance_name_chunk) - - # Add track chunks for position, rotation and scale: - kf_obj_node.add_subchunk(make_track_chunk(POS_TRACK_TAG, obj)) - kf_obj_node.add_subchunk(make_track_chunk(ROT_TRACK_TAG, obj)) - kf_obj_node.add_subchunk(make_track_chunk(SCL_TRACK_TAG, obj)) - - return kf_obj_node -""" - -import BPyMessages -def save_3ds(filename): - '''Save the Blender scene to a 3ds file.''' - # Time the export - - if not filename.lower().endswith('.3ds'): - filename += '.3ds' - - if not BPyMessages.Warning_SaveOver(filename): - return - - time1= Blender.sys.time() - Blender.Window.WaitCursor(1) - sce= bpy.data.scenes.active - - # Initialize the main chunk (primary): - primary = _3ds_chunk(PRIMARY) - # Add version chunk: - version_chunk = _3ds_chunk(VERSION) - version_chunk.add_variable("version", _3ds_int(3)) - primary.add_subchunk(version_chunk) - - # init main object info chunk: - object_info = _3ds_chunk(OBJECTINFO) - - ''' # COMMENTED OUT FOR 2.42 RELEASE!! CRASHES 3DS MAX - # init main key frame data chunk: - kfdata = make_kfdata() - ''' - - # Get all the supported objects selected in this scene: - # ob_sel= list(sce.objects.context) - # mesh_objects = [ (ob, me) for ob in ob_sel for me in (BPyMesh.getMeshFromObject(ob, None, True, False, sce),) if me ] - # empty_objects = [ ob for ob in ob_sel if ob.type == 'Empty' ] - - # Make a list of all materials used in the selected meshes (use a dictionary, - # each material is added once): - materialDict = {} - mesh_objects = [] - for ob in sce.objects.context: - for ob_derived, mat in getDerivedObjects(ob, False): - data = getMeshFromObject(ob_derived, None, True, False, sce) - if data: - data.transform(mat, recalc_normals=False) - mesh_objects.append((ob_derived, data)) - mat_ls = data.materials - mat_ls_len = len(mat_ls) - # get material/image tuples. - if data.faceUV: - if not mat_ls: - mat = mat_name = None - - for f in data.faces: - if mat_ls: - mat_index = f.mat - if mat_index >= mat_ls_len: - mat_index = f.mat = 0 - mat = mat_ls[mat_index] - if mat: mat_name = mat.name - else: mat_name = None - # else there alredy set to none - - img = f.image - if img: img_name = img.name - else: img_name = None - - materialDict.setdefault((mat_name, img_name), (mat, img) ) - - - else: - for mat in mat_ls: - if mat: # material may be None so check its not. - materialDict.setdefault((mat.name, None), (mat, None) ) - - # Why 0 Why! - for f in data.faces: - if f.mat >= mat_ls_len: - f.mat = 0 - - # Make material chunks for all materials used in the meshes: - for mat_and_image in materialDict.itervalues(): - object_info.add_subchunk(make_material_chunk(mat_and_image[0], mat_and_image[1])) - - # Give all objects a unique ID and build a dictionary from object name to object id: - """ - name_to_id = {} - for ob, data in mesh_objects: - name_to_id[ob.name]= len(name_to_id) - #for ob in empty_objects: - # name_to_id[ob.name]= len(name_to_id) - """ - - # Create object chunks for all meshes: - i = 0 - for ob, blender_mesh in mesh_objects: - # create a new object chunk - object_chunk = _3ds_chunk(OBJECT) - - # set the object name - object_chunk.add_variable("name", _3ds_string(sane_name(ob.name))) - - # make a mesh chunk out of the mesh: - object_chunk.add_subchunk(make_mesh_chunk(blender_mesh, materialDict)) - object_info.add_subchunk(object_chunk) - - ''' # COMMENTED OUT FOR 2.42 RELEASE!! CRASHES 3DS MAX - # make a kf object node for the object: - kfdata.add_subchunk(make_kf_obj_node(ob, name_to_id)) - ''' - blender_mesh.verts = None - i+=i - - # Create chunks for all empties: - ''' # COMMENTED OUT FOR 2.42 RELEASE!! CRASHES 3DS MAX - for ob in empty_objects: - # Empties only require a kf object node: - kfdata.add_subchunk(make_kf_obj_node(ob, name_to_id)) - pass - ''' - - # Add main object info chunk to primary chunk: - primary.add_subchunk(object_info) - - ''' # COMMENTED OUT FOR 2.42 RELEASE!! CRASHES 3DS MAX - # Add main keyframe data chunk to primary chunk: - primary.add_subchunk(kfdata) - ''' - - # At this point, the chunk hierarchy is completely built. - - # Check the size: - primary.get_size() - # Open the file for writing: - file = open( filename, 'wb' ) - - # Recursively write the chunks to file: - primary.write(file) - - # Close the file: - file.close() - - # Debugging only: report the exporting time: - Blender.Window.WaitCursor(0) - print "3ds export time: %.2f" % (Blender.sys.time() - time1) - - # Debugging only: dump the chunk hierarchy: - #primary.dump() - - -if __name__=='__main__': - if struct: - Blender.Window.FileSelector(save_3ds, "Export 3DS", Blender.sys.makename(ext='.3ds')) - else: - Blender.Draw.PupMenu("Error%t|This script requires a full python installation") -# save_3ds('/test_b.3ds') diff --git a/release/scripts/3ds_import.py b/release/scripts/3ds_import.py deleted file mode 100644 index bcde82c4869..00000000000 --- a/release/scripts/3ds_import.py +++ /dev/null @@ -1,1007 +0,0 @@ -#!BPY -""" -Name: '3D Studio (.3ds)...' -Blender: 244 -Group: 'Import' -Tooltip: 'Import from 3DS file format (.3ds)' -""" - -__author__= ['Bob Holcomb', 'Richard L?rk?ng', 'Damien McGinnes', 'Campbell Barton', 'Mario Lapin'] -__url__ = ("blenderartists.org", "www.blender.org", "www.gametutorials.com", "lib3ds.sourceforge.net/") -__version__= '0.996' -__bpydoc__= '''\ - -3ds Importer - -This script imports a 3ds file and the materials into Blender for editing. - -Loader is based on 3ds loader from www.gametutorials.com (Thanks DigiBen). - -0.996 by Mario Lapin (mario.lapin@gmail.com) 13/04/200 <br> - - Implemented workaround to correct association between name, geometry and materials of - imported meshes. - - Without this patch, version 0.995 of this importer would associate to each mesh object the - geometry and the materials of the previously parsed mesh object. By so, the name of the - first mesh object would be thrown away, and the name of the last mesh object would be - automatically merged with a '.001' at the end. No object would desappear, however object's - names and materials would be completely jumbled. - -0.995 by Campbell Barton<br> -- workaround for buggy mesh vert delete -- minor tweaks - -0.99 by Bob Holcomb<br> -- added support for floating point color values that previously broke on import. - -0.98 by Campbell Barton<br> -- import faces and verts to lists instead of a mesh, convert to a mesh later -- use new index mapping feature of mesh to re-map faces that were not added. - -0.97 by Campbell Barton<br> -- Strip material names of spaces -- Added import as instance to import the 3ds into its own - scene and add a group instance to the current scene -- New option to scale down imported objects so they are within a limited bounding area. - -0.96 by Campbell Barton<br> -- Added workaround for bug in setting UV's for Zero vert index UV faces. -- Removed unique name function, let blender make the names unique. - -0.95 by Campbell Barton<br> -- Removed workarounds for Blender 2.41 -- Mesh objects split by material- many 3ds objects used more then 16 per mesh. -- Removed a lot of unneeded variable creation. - -0.94 by Campbell Barton<br> -- Face import tested to be about overall 16x speedup over 0.93. -- Material importing speedup. -- Tested with more models. -- Support some corrupt models. - -0.93 by Campbell Barton<br> -- Tested with 400 3ds files from turbosquid and samples. -- Tactfully ignore faces that used the same verts twice. -- Rollback to 0.83 sloppy un-reorganized code, this broke UV coord loading. -- Converted from NMesh to Mesh. -- Faster and cleaner new names. -- Use external comprehensive image loader. -- Re intergrated 0.92 and 0.9 changes -- Fixes for 2.41 compat. -- Non textured faces do not use a texture flag. - -0.92<br> -- Added support for diffuse, alpha, spec, bump maps in a single material - -0.9<br> -- Reorganized code into object/material block functions<br> -- Use of Matrix() to copy matrix data<br> -- added support for material transparency<br> - -0.83 2005-08-07: Campell Barton -- Aggressive image finding and case insensitivy for posisx systems. - -0.82a 2005-07-22 -- image texture loading (both for face uv and renderer) - -0.82 - image texture loading (for face uv) - -0.81a (fork- not 0.9) Campbell Barton 2005-06-08 -- Simplified import code -- Never overwrite data -- Faster list handling -- Leaves import selected - -0.81 Damien McGinnes 2005-01-09 -- handle missing images better - -0.8 Damien McGinnes 2005-01-08 -- copies sticky UV coords to face ones -- handles images better -- Recommend that you run 'RemoveDoubles' on each imported mesh after using this script - -''' - -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Script copyright (C) Bob Holcomb -# -# 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 ***** -# -------------------------------------------------------------------------- - -# Importing modules - -import Blender -import bpy -from Blender import Mesh, Object, Material, Image, Texture, Lamp, Mathutils -from Blender.Mathutils import Vector -import BPyImage - -import BPyMessages - -try: - from struct import calcsize, unpack -except: - calcsize= unpack= None - - - -# If python version is less than 2.4, try to get set stuff from module -try: - set -except: - from sets import Set as set - -BOUNDS_3DS= [] - - -#this script imports uvcoords as sticky vertex coords -#this parameter enables copying these to face uv coords -#which shold be more useful. - -def createBlenderTexture(material, name, image): - texture= bpy.data.textures.new(name) - texture.setType('Image') - texture.image= image - material.setTexture(0, texture, Texture.TexCo.UV, Texture.MapTo.COL) - - - -###################################################### -# Data Structures -###################################################### - -#Some of the chunks that we will see -#----- Primary Chunk, at the beginning of each file -PRIMARY= long('0x4D4D',16) - -#------ Main Chunks -OBJECTINFO = long('0x3D3D',16); #This gives the version of the mesh and is found right before the material and object information -VERSION = long('0x0002',16); #This gives the version of the .3ds file -EDITKEYFRAME= long('0xB000',16); #This is the header for all of the key frame info - -#------ sub defines of OBJECTINFO -MATERIAL=45055 #0xAFFF // This stored the texture info -OBJECT=16384 #0x4000 // This stores the faces, vertices, etc... - -#>------ sub defines of MATERIAL -#------ sub defines of MATERIAL_BLOCK -MAT_NAME = long('0xA000',16) # This holds the material name -MAT_AMBIENT = long('0xA010',16) # Ambient color of the object/material -MAT_DIFFUSE = long('0xA020',16) # This holds the color of the object/material -MAT_SPECULAR = long('0xA030',16) # SPecular color of the object/material -MAT_SHINESS = long('0xA040',16) # ?? -MAT_TRANSPARENCY= long('0xA050',16) # Transparency value of material -MAT_SELF_ILLUM = long('0xA080',16) # Self Illumination value of material -MAT_WIRE = long('0xA085',16) # Only render's wireframe - -MAT_TEXTURE_MAP = long('0xA200',16) # This is a header for a new texture map -MAT_SPECULAR_MAP= long('0xA204',16) # This is a header for a new specular map -MAT_OPACITY_MAP = long('0xA210',16) # This is a header for a new opacity map -MAT_REFLECTION_MAP= long('0xA220',16) # This is a header for a new reflection map -MAT_BUMP_MAP = long('0xA230',16) # This is a header for a new bump map -MAT_MAP_FILENAME = long('0xA300',16) # This holds the file name of the texture - -MAT_FLOAT_COLOR = long ('0x0010', 16) #color defined as 3 floats -MAT_24BIT_COLOR = long ('0x0011', 16) #color defined as 3 bytes - -#>------ sub defines of OBJECT -OBJECT_MESH = long('0x4100',16); # This lets us know that we are reading a new object -OBJECT_LAMP = long('0x4600',16); # This lets un know we are reading a light object -OBJECT_LAMP_SPOT = long('0x4610',16); # The light is a spotloght. -OBJECT_LAMP_OFF = long('0x4620',16); # The light off. -OBJECT_LAMP_ATTENUATE = long('0x4625',16); -OBJECT_LAMP_RAYSHADE = long('0x4627',16); -OBJECT_LAMP_SHADOWED = long('0x4630',16); -OBJECT_LAMP_LOCAL_SHADOW = long('0x4640',16); -OBJECT_LAMP_LOCAL_SHADOW2 = long('0x4641',16); -OBJECT_LAMP_SEE_CONE = long('0x4650',16); -OBJECT_LAMP_SPOT_RECTANGULAR= long('0x4651',16); -OBJECT_LAMP_SPOT_OVERSHOOT= long('0x4652',16); -OBJECT_LAMP_SPOT_PROJECTOR= long('0x4653',16); -OBJECT_LAMP_EXCLUDE= long('0x4654',16); -OBJECT_LAMP_RANGE= long('0x4655',16); -OBJECT_LAMP_ROLL= long('0x4656',16); -OBJECT_LAMP_SPOT_ASPECT= long('0x4657',16); -OBJECT_LAMP_RAY_BIAS= long('0x4658',16); -OBJECT_LAMP_INNER_RANGE= long('0x4659',16); -OBJECT_LAMP_OUTER_RANGE= long('0x465A',16); -OBJECT_LAMP_MULTIPLIER = long('0x465B',16); -OBJECT_LAMP_AMBIENT_LIGHT = long('0x4680',16); - - - -OBJECT_CAMERA= long('0x4700',16); # This lets un know we are reading a camera object - -#>------ sub defines of CAMERA -OBJECT_CAM_RANGES= long('0x4720',16); # The camera range values - -#>------ sub defines of OBJECT_MESH -OBJECT_VERTICES = long('0x4110',16); # The objects vertices -OBJECT_FACES = long('0x4120',16); # The objects faces -OBJECT_MATERIAL = long('0x4130',16); # This is found if the object has a material, either texture map or color -OBJECT_UV = long('0x4140',16); # The UV texture coordinates -OBJECT_TRANS_MATRIX = long('0x4160',16); # The Object Matrix - -global scn -scn= None - -#the chunk class -class chunk: - ID=0 - length=0 - bytes_read=0 - - #we don't read in the bytes_read, we compute that - binary_format='<HI' - - def __init__(self): - self.ID=0 - self.length=0 - self.bytes_read=0 - - def dump(self): - print 'ID: ', self.ID - print 'ID in hex: ', hex(self.ID) - print 'length: ', self.length - print 'bytes_read: ', self.bytes_read - -def read_chunk(file, chunk): - temp_data=file.read(calcsize(chunk.binary_format)) - data=unpack(chunk.binary_format, temp_data) - chunk.ID=data[0] - chunk.length=data[1] - #update the bytes read function - chunk.bytes_read=6 - - #if debugging - #chunk.dump() - -def read_string(file): - #read in the characters till we get a null character - s='' - while not s.endswith('\x00'): - s+=unpack( '<c', file.read(1) )[0] - #print 'string: ',s - - #remove the null character from the string - return s[:-1] - -###################################################### -# IMPORT -###################################################### -def process_next_object_chunk(file, previous_chunk): - new_chunk=chunk() - temp_chunk=chunk() - - while (previous_chunk.bytes_read<previous_chunk.length): - #read the next chunk - read_chunk(file, new_chunk) - -def skip_to_end(file, skip_chunk): - buffer_size=skip_chunk.length-skip_chunk.bytes_read - binary_format='%ic' % buffer_size - temp_data=file.read(calcsize(binary_format)) - skip_chunk.bytes_read+=buffer_size - - -def add_texture_to_material(image, texture, material, mapto): - if mapto=='DIFFUSE': - map=Texture.MapTo.COL - elif mapto=='SPECULAR': - map=Texture.MapTo.SPEC - elif mapto=='OPACITY': - map=Texture.MapTo.ALPHA - elif mapto=='BUMP': - map=Texture.MapTo.NOR - else: - print '/tError: Cannot map to "%s"\n\tassuming diffuse color. modify material "%s" later.' % (mapto, material.name) - map=Texture.MapTo.COL - - if image: texture.setImage(image) # double check its an image. - free_tex_slots= [i for i, tex in enumerate( material.getTextures() ) if tex==None] - if not free_tex_slots: - print '/tError: Cannot add "%s" map. 10 Texture slots alredy used.' % mapto - else: - material.setTexture(free_tex_slots[0],texture,Texture.TexCo.UV,map) - - -def process_next_chunk(file, previous_chunk, importedObjects, IMAGE_SEARCH): - #print previous_chunk.bytes_read, 'BYTES READ' - contextObName= None - contextLamp= [None, None] # object, Data - contextMaterial= None - contextMatrix_rot= None # Blender.Mathutils.Matrix(); contextMatrix.identity() - #contextMatrix_tx= None # Blender.Mathutils.Matrix(); contextMatrix.identity() - contextMesh_vertls= None - contextMesh_facels= None - contextMeshMaterials= {} # matname:[face_idxs] - contextMeshUV= None - - TEXTURE_DICT={} - MATDICT={} - TEXMODE= Mesh.FaceModes['TEX'] - - # Localspace variable names, faster. - STRUCT_SIZE_1CHAR= calcsize('c') - STRUCT_SIZE_2FLOAT= calcsize('2f') - STRUCT_SIZE_3FLOAT= calcsize('3f') - STRUCT_SIZE_UNSIGNED_SHORT= calcsize('H') - STRUCT_SIZE_4UNSIGNED_SHORT= calcsize('4H') - STRUCT_SIZE_4x3MAT= calcsize('ffffffffffff') - _STRUCT_SIZE_4x3MAT= calcsize('fffffffffffff') - # STRUCT_SIZE_4x3MAT= calcsize('ffffffffffff') - # print STRUCT_SIZE_4x3MAT, ' STRUCT_SIZE_4x3MAT' - - def putContextMesh(myContextMesh_vertls, myContextMesh_facels, myContextMeshMaterials): - - materialFaces= set() # faces that have a material. Can optimize? - - # Now make copies with assigned materils. - - def makeMeshMaterialCopy(matName, faces): - ''' - Make a new mesh with only face the faces that use this material. - faces can be any iterable object - containing ints. - ''' - - faceVertUsers = [False] * len(myContextMesh_vertls) - ok=0 - for fIdx in faces: - for vindex in myContextMesh_facels[fIdx]: - faceVertUsers[vindex] = True - if matName != None: # if matName is none then this is a set(), meaning we are using the untextured faces and do not need to store textured faces. - materialFaces.add(fIdx) - ok=1 - - if not ok: - return - - myVertMapping = {} - vertMappingIndex = 0 - - vertsToUse = [i for i in xrange(len(myContextMesh_vertls)) if faceVertUsers[i]] - myVertMapping = dict( [ (ii, i) for i, ii in enumerate(vertsToUse) ] ) - - tempName= '%s_%s' % (contextObName, matName) # matName may be None. - bmesh = bpy.data.meshes.new(tempName) - - if matName == None: - img= None - else: - bmat = MATDICT[matName][1] - bmesh.materials= [bmat] - try: img= TEXTURE_DICT[bmat.name] - except: img= None - - bmesh_verts = bmesh.verts - bmesh_verts.extend( [Vector()] ) - bmesh_verts.extend( [myContextMesh_vertls[i] for i in vertsToUse] ) - # +1 because of DUMMYVERT - face_mapping= bmesh.faces.extend( [ [ bmesh_verts[ myVertMapping[vindex]+1] for vindex in myContextMesh_facels[fIdx]] for fIdx in faces ], indexList=True ) - - if bmesh.faces and (contextMeshUV or img): - bmesh.faceUV= 1 - for ii, i in enumerate(faces): - - # Mapped index- faces may have not been added- if so, then map to the correct index - # BUGGY API - face_mapping is not always the right length - map_index= face_mapping[ii] - - if map_index != None: - targetFace= bmesh.faces[map_index] - if contextMeshUV: - # v.index-1 because of the DUMMYVERT - targetFace.uv= [contextMeshUV[vindex] for vindex in myContextMesh_facels[i]] - if img: - targetFace.image= img - - # bmesh.transform(contextMatrix) - ob = SCN_OBJECTS.new(bmesh, tempName) - ''' - if contextMatrix_tx: - ob.setMatrix(contextMatrix_tx) - ''' - - if contextMatrix_rot: - ob.setMatrix(contextMatrix_rot) - - importedObjects.append(ob) - bmesh.calcNormals() - - for matName, faces in myContextMeshMaterials.iteritems(): - makeMeshMaterialCopy(matName, faces) - - if len(materialFaces)!=len(myContextMesh_facels): - # Invert material faces. - makeMeshMaterialCopy(None, set(range(len( myContextMesh_facels ))) - materialFaces) - #raise 'Some UnMaterialed faces', len(contextMesh.faces) - - #a spare chunk - new_chunk= chunk() - temp_chunk= chunk() - - CreateBlenderObject = False - - #loop through all the data for this chunk (previous chunk) and see what it is - while (previous_chunk.bytes_read<previous_chunk.length): - #print '\t', previous_chunk.bytes_read, 'keep going' - #read the next chunk - #print 'reading a chunk' - read_chunk(file, new_chunk) - - #is it a Version chunk? - if (new_chunk.ID==VERSION): - #print 'if (new_chunk.ID==VERSION):' - #print 'found a VERSION chunk' - #read in the version of the file - #it's an unsigned short (H) - temp_data= file.read(calcsize('I')) - version = unpack('<I', temp_data)[0] - new_chunk.bytes_read+= 4 #read the 4 bytes for the version number - #this loader works with version 3 and below, but may not with 4 and above - if (version>3): - print '\tNon-Fatal Error: Version greater than 3, may not load correctly: ', version - - #is it an object info chunk? - elif (new_chunk.ID==OBJECTINFO): - #print 'elif (new_chunk.ID==OBJECTINFO):' - # print 'found an OBJECTINFO chunk' - process_next_chunk(file, new_chunk, importedObjects, IMAGE_SEARCH) - - #keep track of how much we read in the main chunk - new_chunk.bytes_read+=temp_chunk.bytes_read - - #is it an object chunk? - elif (new_chunk.ID==OBJECT): - - if CreateBlenderObject: - putContextMesh(contextMesh_vertls, contextMesh_facels, contextMeshMaterials) - contextMesh_vertls= []; contextMesh_facels= [] - - ## preparando para receber o proximo objeto - contextMeshMaterials= {} # matname:[face_idxs] - contextMeshUV= None - #contextMesh.vertexUV= 1 # Make sticky coords. - # Reset matrix - contextMatrix_rot= None - #contextMatrix_tx= None - - CreateBlenderObject= True - tempName= read_string(file) - contextObName= tempName - new_chunk.bytes_read += len(tempName)+1 - - #is it a material chunk? - elif (new_chunk.ID==MATERIAL): - #print 'elif (new_chunk.ID==MATERIAL):' - contextMaterial= bpy.data.materials.new('Material') - - elif (new_chunk.ID==MAT_NAME): - #print 'elif (new_chunk.ID==MAT_NAME):' - material_name= read_string(file) - - #plus one for the null character that ended the string - new_chunk.bytes_read+= len(material_name)+1 - - contextMaterial.name= material_name.rstrip() # remove trailing whitespace - MATDICT[material_name]= (contextMaterial.name, contextMaterial) - - elif (new_chunk.ID==MAT_AMBIENT): - #print 'elif (new_chunk.ID==MAT_AMBIENT):' - read_chunk(file, temp_chunk) - if (temp_chunk.ID==MAT_FLOAT_COLOR): - temp_data=file.read(calcsize('3f')) - temp_chunk.bytes_read+=12 - contextMaterial.mirCol=[float(col) for col in unpack('<3f', temp_data)] - elif (temp_chunk.ID==MAT_24BIT_COLOR): - temp_data=file.read(calcsize('3B')) - temp_chunk.bytes_read+= 3 - contextMaterial.mirCol= [float(col)/255 for col in unpack('<3B', temp_data)] # data [0,1,2] == rgb - else: - skip_to_end(file, temp_chunk) - new_chunk.bytes_read+= temp_chunk.bytes_read - - elif (new_chunk.ID==MAT_DIFFUSE): - #print 'elif (new_chunk.ID==MAT_DIFFUSE):' - read_chunk(file, temp_chunk) - if (temp_chunk.ID==MAT_FLOAT_COLOR): - temp_data=file.read(calcsize('3f')) - temp_chunk.bytes_read+=12 - contextMaterial.rgbCol=[float(col) for col in unpack('<3f', temp_data)] - elif (temp_chunk.ID==MAT_24BIT_COLOR): - temp_data=file.read(calcsize('3B')) - temp_chunk.bytes_read+= 3 - contextMaterial.rgbCol= [float(col)/255 for col in unpack('<3B', temp_data)] # data [0,1,2] == rgb - else: - skip_to_end(file, temp_chunk) - new_chunk.bytes_read+= temp_chunk.bytes_read - - elif (new_chunk.ID==MAT_SPECULAR): - #print 'elif (new_chunk.ID==MAT_SPECULAR):' - read_chunk(file, temp_chunk) - if (temp_chunk.ID==MAT_FLOAT_COLOR): - temp_data=file.read(calcsize('3f')) - temp_chunk.bytes_read+=12 - contextMaterial.mirCol=[float(col) for col in unpack('<3f', temp_data)] - elif (temp_chunk.ID==MAT_24BIT_COLOR): - temp_data=file.read(calcsize('3B')) - temp_chunk.bytes_read+= 3 - contextMaterial.mirCol= [float(col)/255 for col in unpack('<3B', temp_data)] # data [0,1,2] == rgb - else: - skip_to_end(file, temp_chunk) - new_chunk.bytes_read+= temp_chunk.bytes_read - - elif (new_chunk.ID==MAT_TEXTURE_MAP): - #print 'elif (new_chunk.ID==MAT_TEXTURE_MAP):' - new_texture= bpy.data.textures.new('Diffuse') - new_texture.setType('Image') - img = None - while (new_chunk.bytes_read<new_chunk.length): - #print 'MAT_TEXTURE_MAP..while', new_chunk.bytes_read, new_chunk.length - read_chunk(file, temp_chunk) - - if (temp_chunk.ID==MAT_MAP_FILENAME): - texture_name=read_string(file) - #img= TEXTURE_DICT[contextMaterial.name]= BPyImage.comprehensiveImageLoad(texture_name, FILENAME) - img= TEXTURE_DICT[contextMaterial.name]= BPyImage.comprehensiveImageLoad(texture_name, FILENAME, PLACE_HOLDER= False, RECURSIVE= IMAGE_SEARCH) - new_chunk.bytes_read += (len(texture_name)+1) #plus one for the null character that gets removed - - else: - skip_to_end(file, temp_chunk) - - new_chunk.bytes_read+= temp_chunk.bytes_read - - #add the map to the material in the right channel - if img: - add_texture_to_material(img, new_texture, contextMaterial, 'DIFFUSE') - - elif (new_chunk.ID==MAT_SPECULAR_MAP): - #print 'elif (new_chunk.ID==MAT_SPECULAR_MAP):' - new_texture= bpy.data.textures.new('Specular') - new_texture.setType('Image') - img = None - while (new_chunk.bytes_read<new_chunk.length): - read_chunk(file, temp_chunk) - - if (temp_chunk.ID==MAT_MAP_FILENAME): - texture_name= read_string(file) - #img= BPyImage.comprehensiveImageLoad(texture_name, FILENAME) - img= BPyImage.comprehensiveImageLoad(texture_name, FILENAME, PLACE_HOLDER= False, RECURSIVE= IMAGE_SEARCH) - new_chunk.bytes_read+= (len(texture_name)+1) #plus one for the null character that gets removed - else: - skip_to_end(file, temp_chunk) - - new_chunk.bytes_read+= temp_chunk.bytes_read - - #add the map to the material in the right channel - if img: - add_texture_to_material(img, new_texture, contextMaterial, 'SPECULAR') - - elif (new_chunk.ID==MAT_OPACITY_MAP): - #print 'new_texture=Blender.Texture.New('Opacity')' - new_texture= bpy.data.textures.new('Opacity') - new_texture.setType('Image') - img = None - while (new_chunk.bytes_read<new_chunk.length): - read_chunk(file, temp_chunk) - - if (temp_chunk.ID==MAT_MAP_FILENAME): - texture_name= read_string(file) - #img= BPyImage.comprehensiveImageLoad(texture_name, FILENAME) - img= BPyImage.comprehensiveImageLoad(texture_name, FILENAME, PLACE_HOLDER= False, RECURSIVE= IMAGE_SEARCH) - new_chunk.bytes_read += (len(texture_name)+1) #plus one for the null character that gets removed - else: - skip_to_end(file, temp_chunk) - - new_chunk.bytes_read+= temp_chunk.bytes_read - #add the map to the material in the right channel - if img: - add_texture_to_material(img, new_texture, contextMaterial, 'OPACITY') - - elif (new_chunk.ID==MAT_BUMP_MAP): - #print 'elif (new_chunk.ID==MAT_BUMP_MAP):' - new_texture= bpy.data.textures.new('Bump') - new_texture.setType('Image') - img = None - while (new_chunk.bytes_read<new_chunk.length): - read_chunk(file, temp_chunk) - - if (temp_chunk.ID==MAT_MAP_FILENAME): - texture_name= read_string(file) - #img= BPyImage.comprehensiveImageLoad(texture_name, FILENAME) - img= BPyImage.comprehensiveImageLoad(texture_name, FILENAME, PLACE_HOLDER= False, RECURSIVE= IMAGE_SEARCH) - new_chunk.bytes_read += (len(texture_name)+1) #plus one for the null character that gets removed - else: - skip_to_end(file, temp_chunk) - - new_chunk.bytes_read+=temp_chunk.bytes_read - - #add the map to the material in the right channel - if img: - add_texture_to_material(img, new_texture, contextMaterial, 'BUMP') - - elif (new_chunk.ID==MAT_TRANSPARENCY): - #print 'elif (new_chunk.ID==MAT_TRANSPARENCY):' - read_chunk(file, temp_chunk) - temp_data=file.read(STRUCT_SIZE_UNSIGNED_SHORT) - - temp_chunk.bytes_read+=2 - contextMaterial.alpha= 1-(float(unpack('<H', temp_data)[0])/100) - new_chunk.bytes_read+=temp_chunk.bytes_read - - - elif (new_chunk.ID==OBJECT_LAMP): # Basic lamp support. - - temp_data=file.read(STRUCT_SIZE_3FLOAT) - - x,y,z=unpack('<3f', temp_data) - new_chunk.bytes_read+=STRUCT_SIZE_3FLOAT - - contextLamp[1]= bpy.data.lamps.new() - contextLamp[0]= SCN_OBJECTS.new(contextLamp[1]) - importedObjects.append(contextLamp[0]) - - #print 'number of faces: ', num_faces - #print x,y,z - contextLamp[0].setLocation(x,y,z) - - # Reset matrix - contextMatrix_rot= None - #contextMatrix_tx= None - #print contextLamp.name, - - elif (new_chunk.ID==OBJECT_MESH): - # print 'Found an OBJECT_MESH chunk' - pass - elif (new_chunk.ID==OBJECT_VERTICES): - ''' - Worldspace vertex locations - ''' - # print 'elif (new_chunk.ID==OBJECT_VERTICES):' - temp_data=file.read(STRUCT_SIZE_UNSIGNED_SHORT) - num_verts=unpack('<H', temp_data)[0] - new_chunk.bytes_read+=2 - - # print 'number of verts: ', num_verts - def getvert(): - temp_data= unpack('<3f', file.read(STRUCT_SIZE_3FLOAT)) - new_chunk.bytes_read += STRUCT_SIZE_3FLOAT #12: 3 floats x 4 bytes each - return temp_data - - #contextMesh.verts.extend( [Vector(),] ) # DUMMYVERT! - remove when blenders internals are fixed. - contextMesh_vertls= [getvert() for i in xrange(num_verts)] - - #print 'object verts: bytes read: ', new_chunk.bytes_read - - elif (new_chunk.ID==OBJECT_FACES): - # print 'elif (new_chunk.ID==OBJECT_FACES):' - temp_data= file.read(STRUCT_SIZE_UNSIGNED_SHORT) - num_faces= unpack('<H', temp_data)[0] - new_chunk.bytes_read+= 2 - #print 'number of faces: ', num_faces - - def getface(): - # print '\ngetting a face' - temp_data= file.read(STRUCT_SIZE_4UNSIGNED_SHORT) - new_chunk.bytes_read+= STRUCT_SIZE_4UNSIGNED_SHORT #4 short ints x 2 bytes each - v1,v2,v3,dummy= unpack('<4H', temp_data) - return v1, v2, v3 - - contextMesh_facels= [ getface() for i in xrange(num_faces) ] - - - elif (new_chunk.ID==OBJECT_MATERIAL): - # print 'elif (new_chunk.ID==OBJECT_MATERIAL):' - material_name= read_string(file) - new_chunk.bytes_read += len(material_name)+1 # remove 1 null character. - - temp_data=file.read(STRUCT_SIZE_UNSIGNED_SHORT) - num_faces_using_mat = unpack('<H', temp_data)[0] - new_chunk.bytes_read += STRUCT_SIZE_UNSIGNED_SHORT - - def getmat(): - temp_data= file.read(STRUCT_SIZE_UNSIGNED_SHORT) - new_chunk.bytes_read+= STRUCT_SIZE_UNSIGNED_SHORT - return unpack('<H', temp_data)[0] - - contextMeshMaterials[material_name]= [ getmat() for i in xrange(num_faces_using_mat) ] - - #look up the material in all the materials - - elif (new_chunk.ID==OBJECT_UV): - temp_data=file.read(STRUCT_SIZE_UNSIGNED_SHORT) - num_uv=unpack('<H', temp_data)[0] - new_chunk.bytes_read+= 2 - - def getuv(): - temp_data=file.read(STRUCT_SIZE_2FLOAT) - new_chunk.bytes_read += STRUCT_SIZE_2FLOAT #2 float x 4 bytes each - return Vector( unpack('<2f', temp_data) ) - - contextMeshUV= [ getuv() for i in xrange(num_uv) ] - - elif (new_chunk.ID== OBJECT_TRANS_MATRIX): - # How do we know the matrix size? 54 == 4x4 48 == 4x3 - temp_data=file.read(STRUCT_SIZE_4x3MAT) - data= list( unpack('<ffffffffffff', temp_data) ) - new_chunk.bytes_read += STRUCT_SIZE_4x3MAT - - contextMatrix_rot= Blender.Mathutils.Matrix(\ - data[:3] + [0],\ - data[3:6] + [0],\ - data[6:9] + [0],\ - data[9:] + [1]) - - - ''' - contextMatrix_rot= Blender.Mathutils.Matrix(\ - data[:3] + [0],\ - data[3:6] + [0],\ - data[6:9] + [0],\ - [0,0,0,1]) - ''' - - ''' - contextMatrix_rot= Blender.Mathutils.Matrix(\ - data[:3] ,\ - data[3:6],\ - data[6:9]) - ''' - - ''' - contextMatrix_rot = Blender.Mathutils.Matrix() - m = 0 - for j in xrange(4): - for i in xrange(3): - contextMatrix_rot[j][i] = data[m] - m+=1 - - contextMatrix_rot[0][3]=0; - contextMatrix_rot[1][3]=0; - contextMatrix_rot[2][3]=0; - contextMatrix_rot[3][3]=1; - ''' - - #contextMatrix_rot.resize4x4() - #print "MTX" - #print contextMatrix_rot - contextMatrix_rot.invert() - #print contextMatrix_rot - #contextMatrix_tx = Blender.Mathutils.TranslationMatrix(0.5 * Blender.Mathutils.Vector(data[9:])) - #contextMatrix_tx.invert() - - #tx.invert() - - #contextMatrix = contextMatrix * tx - #contextMatrix = contextMatrix *tx - - elif (new_chunk.ID==MAT_MAP_FILENAME): - texture_name=read_string(file) - try: - TEXTURE_DICT[contextMaterial.name] - except: - #img= TEXTURE_DICT[contextMaterial.name]= BPyImage.comprehensiveImageLoad(texture_name, FILENAME) - img= TEXTURE_DICT[contextMaterial.name]= BPyImage.comprehensiveImageLoad(texture_name, FILENAME, PLACE_HOLDER= False, RECURSIVE= IMAGE_SEARCH) - - new_chunk.bytes_read+= len(texture_name)+1 #plus one for the null character that gets removed - - else: #(new_chunk.ID!=VERSION or new_chunk.ID!=OBJECTINFO or new_chunk.ID!=OBJECT or new_chunk.ID!=MATERIAL): - # print 'skipping to end of this chunk' - buffer_size=new_chunk.length-new_chunk.bytes_read - binary_format='%ic' % buffer_size - temp_data=file.read(calcsize(binary_format)) - new_chunk.bytes_read+=buffer_size - - - #update the previous chunk bytes read - # print 'previous_chunk.bytes_read += new_chunk.bytes_read' - # print previous_chunk.bytes_read, new_chunk.bytes_read - previous_chunk.bytes_read += new_chunk.bytes_read - ## print 'Bytes left in this chunk: ', previous_chunk.length-previous_chunk.bytes_read - - # FINISHED LOOP - # There will be a number of objects still not added - if contextMesh_facels != None: - putContextMesh(contextMesh_vertls, contextMesh_facels, contextMeshMaterials) - -def load_3ds(filename, PREF_UI= True): - global FILENAME, SCN_OBJECTS - - if BPyMessages.Error_NoFile(filename): - return - - print '\n\nImporting 3DS: "%s"' % (Blender.sys.expandpath(filename)) - - time1= Blender.sys.time() - - FILENAME=filename - current_chunk=chunk() - - file=open(filename,'rb') - - #here we go! - # print 'reading the first chunk' - read_chunk(file, current_chunk) - if (current_chunk.ID!=PRIMARY): - print '\tFatal Error: Not a valid 3ds file: ', filename - file.close() - return - - - # IMPORT_AS_INSTANCE= Blender.Draw.Create(0) - IMPORT_CONSTRAIN_BOUNDS= Blender.Draw.Create(10.0) - IMAGE_SEARCH= Blender.Draw.Create(1) - APPLY_MATRIX= Blender.Draw.Create(0) - - # Get USER Options - pup_block= [\ - ('Size Constraint:', IMPORT_CONSTRAIN_BOUNDS, 0.0, 1000.0, 'Scale the model by 10 until it reacehs the size constraint. Zero Disables.'),\ - ('Image Search', IMAGE_SEARCH, 'Search subdirs for any assosiated images (Warning, may be slow)'),\ - ('Transform Fix', APPLY_MATRIX, 'Workaround for object transformations importing incorrectly'),\ - #('Group Instance', IMPORT_AS_INSTANCE, 'Import objects into a new scene and group, creating an instance in the current scene.'),\ - ] - - if PREF_UI: - if not Blender.Draw.PupBlock('Import 3DS...', pup_block): - return - - Blender.Window.WaitCursor(1) - - IMPORT_CONSTRAIN_BOUNDS= IMPORT_CONSTRAIN_BOUNDS.val - # IMPORT_AS_INSTANCE= IMPORT_AS_INSTANCE.val - IMAGE_SEARCH = IMAGE_SEARCH.val - APPLY_MATRIX = APPLY_MATRIX.val - - if IMPORT_CONSTRAIN_BOUNDS: - BOUNDS_3DS[:]= [1<<30, 1<<30, 1<<30, -1<<30, -1<<30, -1<<30] - else: - BOUNDS_3DS[:]= [] - - ##IMAGE_SEARCH - - scn= bpy.data.scenes.active - SCN_OBJECTS = scn.objects - SCN_OBJECTS.selected = [] # de select all - - importedObjects= [] # Fill this list with objects - process_next_chunk(file, current_chunk, importedObjects, IMAGE_SEARCH) - - - # Link the objects into this scene. - # Layers= scn.Layers - - # REMOVE DUMMYVERT, - remove this in the next release when blenders internal are fixed. - - - for ob in importedObjects: - if ob.type=='Mesh': - me= ob.getData(mesh=1) - me.verts.delete([me.verts[0],]) - if not APPLY_MATRIX: - me.transform(ob.matrixWorld.copy().invert()) - - # Done DUMMYVERT - """ - if IMPORT_AS_INSTANCE: - name= filename.split('\\')[-1].split('/')[-1] - # Create a group for this import. - group_scn= Scene.New(name) - for ob in importedObjects: - group_scn.link(ob) # dont worry about the layers - - grp= Blender.Group.New(name) - grp.objects= importedObjects - - grp_ob= Object.New('Empty', name) - grp_ob.enableDupGroup= True - grp_ob.DupGroup= grp - scn.link(grp_ob) - grp_ob.Layers= Layers - grp_ob.sel= 1 - else: - # Select all imported objects. - for ob in importedObjects: - scn.link(ob) - ob.Layers= Layers - ob.sel= 1 - """ - - if IMPORT_CONSTRAIN_BOUNDS!=0.0: - # Set bounds from objecyt bounding box - for ob in importedObjects: - if ob.type=='Mesh': - ob.makeDisplayList() # Why dosnt this update the bounds? - for v in ob.getBoundBox(): - for i in (0,1,2): - if v[i] < BOUNDS_3DS[i]: - BOUNDS_3DS[i]= v[i] # min - - if v[i] > BOUNDS_3DS[i+3]: - BOUNDS_3DS[i+3]= v[i] # min - - # Get the max axis x/y/z - max_axis= max(BOUNDS_3DS[3]-BOUNDS_3DS[0], BOUNDS_3DS[4]-BOUNDS_3DS[1], BOUNDS_3DS[5]-BOUNDS_3DS[2]) - # print max_axis - if max_axis < 1<<30: # Should never be false but just make sure. - - # Get a new scale factor if set as an option - SCALE=1.0 - while (max_axis*SCALE) > IMPORT_CONSTRAIN_BOUNDS: - SCALE/=10 - - # SCALE Matrix - SCALE_MAT= Blender.Mathutils.Matrix([SCALE,0,0,0],[0,SCALE,0,0],[0,0,SCALE,0],[0,0,0,1]) - - for ob in importedObjects: - ob.setMatrix(ob.matrixWorld*SCALE_MAT) - - # Done constraining to bounds. - - # Select all new objects. - print 'finished importing: "%s" in %.4f sec.' % (filename, (Blender.sys.time()-time1)) - file.close() - Blender.Window.WaitCursor(0) - - -DEBUG= False -if __name__=='__main__' and not DEBUG: - if calcsize==None: - Blender.Draw.PupMenu('Error%t|a full python installation not found') - else: - Blender.Window.FileSelector(load_3ds, 'Import 3DS', '*.3ds') - -# For testing compatibility -#load_3ds('/metavr/convert/vehicle/truck_002/TruckTanker1.3DS', False) -#load_3ds('/metavr/archive/convert/old/arranged_3ds_to_hpx-2/only-need-engine-trains/Engine2.3DS', False) -''' - -else: - import os - # DEBUG ONLY - TIME= Blender.sys.time() - import os - print 'Searching for files' - os.system('find /metavr/ -iname "*.3ds" > /tmp/temp3ds_list') - # os.system('find /storage/ -iname "*.3ds" > /tmp/temp3ds_list') - print '...Done' - file= open('/tmp/temp3ds_list', 'r') - lines= file.readlines() - file.close() - # sort by filesize for faster testing - lines_size = [(os.path.getsize(f[:-1]), f[:-1]) for f in lines] - lines_size.sort() - lines = [f[1] for f in lines_size] - - - def between(v,a,b): - if v <= max(a,b) and v >= min(a,b): - return True - return False - - for i, _3ds in enumerate(lines): - if between(i, 650,800): - #_3ds= _3ds[:-1] - print 'Importing', _3ds, '\nNUMBER', i, 'of', len(lines) - _3ds_file= _3ds.split('/')[-1].split('\\')[-1] - newScn= Blender.Scene.New(_3ds_file) - newScn.makeCurrent() - load_3ds(_3ds, False) - - print 'TOTAL TIME: %.6f' % (Blender.sys.time() - TIME) - -''' diff --git a/release/scripts/Axiscopy.py b/release/scripts/Axiscopy.py deleted file mode 100644 index 6a31432edb6..00000000000 --- a/release/scripts/Axiscopy.py +++ /dev/null @@ -1,125 +0,0 @@ -#!BPY - -""" Registration info for Blender menus: <- these words are ignored -Name: 'Axis Orientation Copy' -Blender: 242 -Group: 'Object' -Tip: 'Copy local axis orientation of active object to all selected meshes (changes mesh data)' -""" - -__author__ = "A Vanpoucke (xand)" -__url__ = ("blenderartists.org", "www.blender.org", -"French Blender support forum, http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender") -__version__ = "2 17/12/05" - -__bpydoc__ = """\ -This script copies the axis orientation -- X, Y and Z rotations -- of the -active object to all selected meshes. - -It's useful to align the orientations of all meshes of a structure, a human -skeleton, for example. - -Usage: - -Select all mesh objects that need to have their orientations changed -(reminder: keep SHIFT pressed after the first, to add each new one to the -selection), then select the object whose orientation will be copied from and -finally run this script to update the angles. - -Notes:<br> - This script changes mesh data: the vertices are transformed.<br> - Before copying the orientation to each object, the script stores its -transformation matrix. Then the angles are copied and after that the object's -vertices are transformed "back" so that they still have the same positions as -before. In other words, the rotations are updated, but you won't notice that -just from looking at the objects.<br> - Checking their X, Y and Z rotation values with "Transform Properties" in -the 3D View's Object menu shows the angles are now the same of the active -object. Or simply look at the transform manipulator handles in local transform -orientation. -""" - - -# $Id$ -# -#---------------------------------------------- -# A Vanpoucke (xand) -#from the previous script realignaxis -#---------------------------------------------- -# Communiquer les problemes et erreurs sur: -# http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender -# -------------------------------------------------------------------------- -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Copyright (C) 2003, 2004: A Vanpoucke -# -# 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 ***** -# -------------------------------------------------------------------------- - -from Blender import * -from Blender import Mathutils -from Blender.Mathutils import * -import BPyMessages - -def realusers(data): - users = data.users - if data.fakeUser: users -= 1 - return users - - - -def main(): - - scn_obs= Scene.GetCurrent().objects - ob_act = scn_obs.active - scn_obs = scn_obs.context - - if not ob_act: - BPyMessages.Error_NoActive() - - obs = [(ob, ob.getData(mesh=1)) for ob in scn_obs if ob != ob_act] - - for ob, me in obs: - - if ob.type != 'Mesh': - Draw.PupMenu("Error%t|Selection must be made up of mesh objects only") - return - - if realusers(me) != 1: - Draw.PupMenu("Error%t|Meshes must be single user") - return - - if len(obs) < 1: - Draw.PupMenu("Error: you must select at least 2 objects") - return - - result = Draw.PupMenu("Copy axis orientation from: " + ob_act.name + " ?%t|OK") - if result == -1: - return - - for ob_target, me_target in obs: - if ob_act.rot != ob_target.rot: - rot_target = ob_target.matrixWorld.rotationPart().toEuler().toMatrix() - rot_source = ob_act.matrixWorld.rotationPart().toEuler().toMatrix() - rot_source_inv = rot_source.copy().invert() - tx_mat = rot_target * rot_source_inv - tx_mat.resize4x4() - me_target.transform(tx_mat) - ob_target.rot=ob_act.rot - -if __name__ == '__main__': - main()
\ No newline at end of file diff --git a/release/scripts/DirectX8Exporter.py b/release/scripts/DirectX8Exporter.py deleted file mode 100644 index 8a0ecaf0eb7..00000000000 --- a/release/scripts/DirectX8Exporter.py +++ /dev/null @@ -1,1196 +0,0 @@ -#!BPY - -""" -# Name: 'DirectX (.x)...' -# Blender: 242 -# Group: 'Export' -# Tooltip: 'Export to DirectX text file format format for XNA Animation Component Library.' -""" -__author__ = "vertex color exporting feature is added by mnemoto (original:minahito (original:Arben (Ben) Omari))" -__url__ = ("blender.org", "blenderartists.org", "Adjuster's site http://sunday-lab.blogspot.com/, Author's site http://www.omariben.too.it","Adjuster's site http://ex.homeunix.net/") -__version__ = "3.1" - -__bpydoc__ = """\ -This script exports a Blender mesh with armature to DirectX 8's text file -format. - -Notes:<br> - Check author's site or the elYsiun forum for a new beta version of the -DX exporter. -""" -# DirectXExporter.py version 3.0 -# Copyright (C) 2006 Arben OMARI -- omariarben@everyday.com -# -# 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. - -# This script export meshes created with Blender in DirectX8 file format -# it exports meshes,armatures,materials,normals,texturecoords and animations - -# Grab the latest version here :www.omariben.too.it - -# [Notice] -# This script is the custom version of Mr.Arben Omari's great work. -# If you have a question about the adjusted part, visit http://sunday-lab.blogspot.com/. - -import Blender -from Blender import Types, Object, NMesh, Material,Armature,Mesh -from Blender.Mathutils import * -from Blender import Draw, BGL -from Blender.BGL import * -try: import math -except: math = None - -global mat_flip,index_list,space,bone_list,mat_dict -global anim,flip_norm,swap_zy,flip_z,speed,ticks,no_light,recalc_norm,Bl_norm -bone_list =[] -index_list = [] -mat_dict = {} -space = 0;flip_z = 1;anim=0;swap_yz=0;flip_norm=0;speed=0;ticks= 25 -Bl_norm = 1;recalc_norm = 0;no_light = 0 - -toggle_val = 0 -toggle1_val = 0 -toggle2_val = 0 -toggle3_val = 1 -toggle4_val = 0 -toggle5_val = 1 -toggle6_val = 0 -toggle7_val = 0 -anim_tick = Draw.Create(25) - -#*********************************************** -# DirectX file spec only allows letters, digits, and -# underscore in Names. -#*********************************************** -def make_legal_name(starting_name): - new_name = starting_name.replace('.','_') - new_name = new_name.replace(' ','_') - if new_name[0].isdigit(): - new_name = '_' + new_name - return new_name - -#*********************************************** -# MAIN -#*********************************************** - -def my_callback(filename): - if filename.find('.x', -2) <= 0: filename += '.x' - xexport = xExport(filename) - xexport.SelectObjs() - -def my_callback_sel(filename): - if filename.find('.x', -2) <= 0: filename += '.x' - xexport = xExport(filename) - xexport.exportSelMesh() -def event(evt, val): - if evt == Draw.ESCKEY: - Draw.Exit() - return - -def button_event(evt): - global toggle_val,toggle1_val,toggle2_val,toggle3_val,toggle4_val,toggle5_val,toggle6_val,toggle7_val - global flip_z,swap_yz,flip_norm,anim,ticks,speed,no_light,Bl_norm,recalc_norm - arg = __script__['arg'] - if evt == 1: - toggle_val = 1 - toggle_val - anim = toggle_val - Draw.Redraw(1) - if evt == 2: - toggle1_val = 1 - toggle1_val - flip_norm = toggle1_val - Draw.Redraw(1) - if evt == 3: - toggle2_val = 1 - toggle2_val - swap_yz = toggle2_val - Draw.Redraw(1) - if evt == 4: - toggle3_val = 1 - toggle3_val - flip_z = toggle3_val - Draw.Redraw(1) - if evt == 5: - toggle4_val = 1 - toggle4_val - speed = toggle4_val - Draw.Redraw(1) - if evt == 10: - toggle5_val = 1 - toggle5_val - if toggle5_val==1: - toggle6_val = 0 - toggle7_val = 0 - else : - toggle6_val = 1 - toggle7_val = 1 - no_light = toggle7_val - recalc_norm = toggle6_val - Bl_norm = toggle5_val - Draw.Redraw(1) - if evt == 11: - toggle6_val = 1 - toggle6_val - if toggle6_val==1: - toggle5_val = 0 - toggle7_val = 0 - else : - toggle5_val = 1 - toggle7_val = 1 - no_light = toggle7_val - recalc_norm = toggle6_val - Bl_norm = toggle5_val - Draw.Redraw(1) - if evt == 12: - toggle7_val = 1 - toggle7_val - if toggle7_val==1: - toggle6_val = 0 - toggle5_val = 0 - else : - toggle6_val = 1 - toggle5_val = 1 - no_light = toggle7_val - recalc_norm = toggle6_val - Bl_norm = toggle5_val - Draw.Redraw(1) - if evt == 6: - ticks = anim_tick.val - if evt == 7: - fname = Blender.sys.makename(ext = ".x") - Blender.Window.FileSelector(my_callback, "Export DirectX", fname) - if evt == 8: - fname = Blender.sys.makename(ext = ".x") - Blender.Window.FileSelector(my_callback_sel, "Export DirectX", fname) - if evt == 9: - Draw.Exit() - - -def draw(): - global animsg,flipmsg,swapmsg,anim_tick - global flip_z,swap_yz,flip_norm,anim,ticks,speed,recalc_norm,Bl_norm,no_light - glClearColor(0.55,0.6,0.6,1) - glClear(BGL.GL_COLOR_BUFFER_BIT) - #external box - glColor3f(0.2,0.3,0.3) - rect(10,402,300,382) - #-- - #glColor3f(0.3,0.4,0.4) - #rect(11,399,298,398) - #-- - glColor3f(0.5,0.75,0.65) - rect(14,398,292,30) - #-- - glColor3f(0.5,0.75,0.65) - rect(14,366,292,160) - #-- - glColor3f(0.5,0.75,0.65) - rect(14,202,292,60) - #-- - glColor3f(0.5,0.75,0.65) - rect(14,138,292,40) - #-- - glColor3f(0.5,0.75,0.65) - rect(14,94,292,70) - - glColor3f(0.8,.8,0.6) - glRasterPos2i(20, 380) - Draw.Text("DirectX Exporter ",'large') - Draw.Text("(for Blender 2.41)", 'small') - #-------Aniamtion toggle--------------------------------------------- - Draw.Toggle("Anim", 1, 20, 330, 55, 20, toggle_val,"export animations") - if toggle_val : - anim = 1 - animsg = "animation will be exported" - else: - anim = 0 - animsg = "animation will be not exported" - glRasterPos2i(100,335) - Draw.Text(animsg) - #---Flip normals toggle----------------------------------------------- - Draw.Toggle("Flip norm", 2, 20, 300, 55, 20, toggle1_val,"invert normals") - if toggle1_val : - flip_norm = 1 - flipmsg = "flipped normals" - else: - flip_norm = 0 - flipmsg = "not flipped normals" - glRasterPos2i(100,305) - Draw.Text(flipmsg) - #------Swap yz toggle---------------------------------------------------------------- - Draw.Toggle("Swap zy", 3, 20, 270, 55, 20, toggle2_val,"swap z,y axis(y up)") - if toggle2_val : - swap_yz = 1 - swapmsg = "Y-axis up" - else: - swap_yz = 0 - swapmsg = "Z-axis up" - glRasterPos2i(100,275) - Draw.Text(swapmsg) - #------Flip z toggle---------------------------------------------------------------- - Draw.Toggle("Flip z", 4, 20, 240, 55, 20, toggle3_val,"flip z axis") - if toggle3_val : - flip_z = 1 - zmsg = "left handed system" - else: - flip_z = 0 - zmsg = "right handed system" - glRasterPos2i(100,245) - Draw.Text(zmsg) - #------Speed toggle---------------------------------------------------------------- - Draw.Toggle("Speed", 5, 20, 210, 55, 20, toggle4_val,"Animation speed") - if toggle4_val : - speed = 1 - spedmsg = "set speed" - anim_tick = Draw.Number("", 6,200, 210, 85, 20, anim_tick.val,1,100000,"ticks per second") - else: - speed = 0 - spedmsg = "" - glRasterPos2i(100,215) - Draw.Text(spedmsg) - #------Blender Normals toggle---------------------------------------------------------------- - Draw.Toggle("Bl.normals", 10, 20, 105, 75, 25, toggle5_val,"export normals as in Blender") - if toggle5_val : - Bl_norm = 1 - #------Recalculute Normals toggle---------------------------------------------------------------- - Draw.Toggle("recalc.no", 11, 120, 105, 75, 25, toggle6_val,"export recalculated normals") - if toggle6_val : - recalc_norm = 1 - #------Recalculute Normals toggle---------------------------------------------------------------- - Draw.Toggle("no smooth", 12, 220, 105, 75, 25, toggle7_val,"every vertex has the face normal,no smoothing") - if toggle7_val : - no_light = 1 - #------Draw Button export---------------------------------------------------------------- - exp_butt = Draw.Button("Export All",7,20, 155, 75, 30, "export all the scene objects") - sel_butt = Draw.Button("Export Sel",8,120, 155, 75, 30, "export the selected object") - exit_butt = Draw.Button("Exit",9,220, 155, 75, 30, "exit") - glRasterPos2i(20,75) - Draw.Text("(C) 2006 Arben OMARI ") - glRasterPos2i(20,55) - Draw.Text("http://www.omariben.too.it") - glRasterPos2i(20,35) - Draw.Text("aromar@tin.it") - -def rect(x,y,width,height): - glBegin(GL_LINE_LOOP) - glVertex2i(x,y) - glVertex2i(x+width,y) - glVertex2i(x+width,y-height) - glVertex2i(x,y-height) - glEnd() - -def rectFill(x,y,width,height): - glBegin(GL_POLYGON) - glVertex2i(x,y) - glVertex2i(x+width,y) - glVertex2i(x+width,y-height) - glVertex2i(x,y-height) - glEnd() - - - -Draw.Register(draw, event, button_event) - - -#*********************************************** -#*********************************************** -# EXPORTER -#*********************************************** -#*********************************************** - -class xExport: - def __init__(self, filename): - self.file = open(filename, "w") - -#********************************************************************************************************************************************* - #*********************************************** - #Select Scene objects - #*********************************************** - def analyzeScene(self): - parent_list = [] - for obj in Blender.Scene.GetCurrent().objects: - if obj.type in ('Mesh', 'Armature', 'Empty'): - if obj.parent == None : - parent_list.append(obj) - - return parent_list - - def getChildren(self,obj): - obs = Blender.Scene.GetCurrent().objects - return [ ob for ob in obs if ob.parent == obj ] - - def getArmChildren(self,obj): - for ob in Blender.Scene.GetCurrent().objects: #Object.Get(): - if ob.parent == obj : - return ob - - def getLocMat(self, obj): - pare = obj.parent - mat = obj.matrixWorld - mat_id = Matrix([1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]) - if pare: - mat_p = pare.matrixWorld - mat_c = Matrix(mat_p) - mat_c.invert() - mat_f = mat * mat_c - else : - mat_id.invert() - mat_f = mat * mat_id - return mat_f - - def writeObjFrames(self,obj): - global space,chld_obj,ch_list - mesh = obj.getData() - if obj.type == "Empty" : - mat = self.getLocMat(obj) - mat_c = Matrix(mat) - self.writeArmFrames(mat_c, make_legal_name(obj.name)) - if type(mesh) == Types.ArmatureType : - Child_obj = self.getArmChildren(obj) - chld_obj = obj - ch_list.append(Child_obj) - self.writeRootBone(obj, Child_obj) - if obj.type == 'Mesh' and obj not in ch_list: - self.exportMesh(obj) - - - def writeChildObj(self,obj): - global space,ch_list - space += 1 - if obj : - for ob in obj: - if ob not in ch_list: - self.writeObjFrames(ob) - ch_list.append(ob) - ch_ob = self.getChildren(ob) - self.writeChildObj(ch_ob) - self.closeBrackets() - self.file.write(" // End of the Object %s \n" % (ob.name)) - - - def writeRootFrame(self): - global flip_z,swap_yz,speed - if speed: - self.writeAnimTicks() - if flip_z: - mat_flip = Matrix([1, 0, 0, 0], [0, 1, 0, 0], [0, 0, -1, 0], [0, 0, 0, 1]) - else : - mat_flip = Matrix([1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]) - if swap_yz : - mat_rot = RotationMatrix(-90, 4, 'x') - mat_flip = mat_rot * mat_flip - self.writeArmFrames(mat_flip, "RootFrame") - - ################################################################## - def SelectObjs(self): - global space,chld_obj,ch_list,flip_z,swap_yz,speed - print "exporting..." - self.writeHeader() - self.writeRootFrame() - obj_list = self.analyzeScene() - space += 1 - ch_list = [] - for obj in obj_list: - self.writeObjFrames(obj) - ch_l = self.getChildren(obj) - for ch in ch_l: - - - if ch and ch.type == "Armature": - ch_list.append(ch) - self.writeObjFrames(ch) - else : - self.writeChildObj(ch_l) - if obj.type != "Armature": - self.file.write(" } // SI End of the Object %s \n" % (obj.name)) - - - - self.file.write("} // End of the Root Frame\n") - if anim : - self.file.write("AnimationSet AnimationSet0 {\n") - for obj in Blender.Scene.GetCurrent().objects: - if obj.type in ('Mesh', 'Empty'): - ip_list = obj.ipo - if ip_list != None : - self.writeAnimationObj(obj) - elif obj.type == 'Armature': - act_list = obj.getAction() - if act_list != None : - self.writeAnimation(obj) - #ip_list = obj.ipo - #if ip_list != None : - # self.writeAnimationObj(obj) - - self.file.write("} // End of Animation Set\n") - self.writeEnd() - ####################################################### - - - def writeAnimTicks(self): - global ticks - self.file.write("AnimTicksPerSecond {\n") - self.file.write("%d; \n" % (ticks)) - self.file.write("}\n") - - #*********************************************** - #Export Mesh without Armature - #*********************************************** - def exportMesh(self, obj): - tex = [] - mesh = obj.getData() - self.writeTextures(obj, tex) - self.writeMeshcoordArm(obj, arm_ob = None) - self.writeMeshMaterialList(obj, mesh, tex) - self.writeMeshNormals(obj, mesh) - self.writeMeshTextureCoords(obj, mesh) - self.writeMeshVertexColors(obj, mesh) - self.file.write(" } // End of the Mesh %s \n" % (obj.name)) - - - #*********************************************** - #Export the Selected Mesh - #*********************************************** - def exportSelMesh(self): - print "exporting ..." - self.writeHeader() - self.writeRootFrame() - tex = [] - objs = Object.GetSelected() - for obj in objs: - if obj.type == 'Mesh': - mesh = obj.data - self.writeTextures(obj, tex) - self.writeMeshcoordArm(obj, arm_ob = None) - self.writeMeshMaterialList(obj, mesh, tex) - self.writeMeshNormals(obj, mesh) - self.writeMeshTextureCoords(obj, mesh) - self.writeMeshVertexColors(obj, mesh) - self.file.write(" }\n") - self.file.write("}\n") - ind = objs.index(obj) - if ind == len(objs)-1: - self.file.write("}\n") - ip_list = obj.ipo - if ip_list != None : - self.file.write("AnimationSet AnimationSet0 {\n") - self.writeAnimationObj(obj) - self.file.write("}\n") - else : - print "The selected object is not a mesh" - print "...finished" - #*********************************************** - #Export Mesh with Armature - #*********************************************** - def exportMeshArm(self,arm,arm_ob,ch_obj): - tex = [] - mesh = ch_obj.getData() - self.writeTextures(ch_obj, tex) - self.writeMeshcoordArm(ch_obj ,arm_ob) - self.writeMeshMaterialList(ch_obj, mesh, tex) - self.writeMeshNormals(ch_obj, mesh) - self.writeMeshTextureCoords(ch_obj, mesh) - self.writeSkinWeights(arm,mesh) - #self.file.write(" } // End of the Frame %s \n" % (ch_obj.name)) - self.file.write(" } // End of the Object %s \n" % (ch_obj.name)) - - #*********************************************** - #Export Root Bone - #*********************************************** - def writeRootBone(self, chld_obj, child_obj): - global space,root_bon - arms = chld_obj.getData() - mat_arm = self.getLocMat(chld_obj) - for bon in arms.bones.values(): - if bon.hasParent(): - pass - else: - root_bon = bon - space += 1 - mat_r = self.writeAnimCombineMatrix(root_bon,1) - self.writeArmFrames(mat_r, make_legal_name(root_bon.name)) - - bon_c = root_bon.children - self.writeChildren(bon_c) - self.file.write(" } // End of the Bone %s \n" % (root_bon.name)) - self.exportMeshArm(arms, chld_obj ,child_obj) - - #*********************************************** - #Create Children structure - #*********************************************** - def writeBon(self,bon): - global space - mat_r = self.writeAnimCombineMatrix(bon,1) - self.writeArmFrames(mat_r, make_legal_name(bon.name)) - - - def writeChildren(self,bon_c): - global space,bone_list - space += 1 - if bon_c: - for bo in bon_c: - if bo.name not in bone_list: - self.writeBon(bo) - bone_list.append(bo.name) - bo_c = bo.children - self.writeChildren(bo_c) - self.closeBrackets() - - - - def closeBrackets(self): - global space - space = space-1 - tab = " " - self.file.write("%s" % (tab * space)) - self.file.write("}\n") - - - - #*********************************************** - #Offset Matrix - #*********************************************** - def writeMatrixOffset(self,bon): - global chld_obj - Blender.Set('curframe', 1) - pose = chld_obj.getPose() - pos_b = pose.bones[bon.name] - mat_b = pos_b.poseMatrix - mat_c = Matrix(mat_b) - mat_c.invert() - return mat_c - - - #*********************************************** - #Combine Matrix - #*********************************************** - def writeCombineMatrix(self,bon): - global chld_obj - - Blender.Set('curframe', 1) - pose = chld_obj.getPose() - pos_b = pose.bones[bon.name] - mat_b = pos_b.poseMatrix - if bon.hasParent(): - pare = bon.parent - pos_p = pose.bones[pare.name] - mat_p = pos_p.poseMatrix - - else: - mat_p = Matrix([1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]) - mat_c = Matrix(mat_p) - mat_c.invert() - mat_f = mat_b * mat_c - - return mat_f - #*********************************************** - #Combine Matrix - #*********************************************** - def writeAnimCombineMatrix(self,bon,fre): - global chld_obj - Blender.Set('curframe', fre) - pose = chld_obj.getPose() - pos_b = pose.bones[bon.name] - mat_b = pos_b.poseMatrix - if bon.hasParent(): - pare = bon.parent - pos_p = pose.bones[pare.name] - mat_p = pos_p.poseMatrix - - else: - mat_p = Matrix([1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]) - mat_c = Matrix(mat_p) - mat_c.invert() - mat_f = mat_b * mat_c - - return mat_f - - -#********************************************************************************************************************************************* - #*********************************************** - #Write SkinWeights - #*********************************************** - def writeSkinWeights(self, arm, mesh): - global index_list - v_dict = {} - Blender.Set('curframe',1) - self.file.write(" XSkinMeshHeader {\n") - max_infl = 0 - for bo in arm.bones.values() : - name = bo.name - try : - vertx_list = mesh.getVertsFromGroup(name,1) - for inde in vertx_list : - vert_infl = mesh.getVertexInfluences(inde[0]) - ln_infl = len(vert_infl) - if ln_infl > max_infl : - max_infl = ln_infl - - except: - pass - - self.file.write(" %d; \n" % (max_infl)) - self.file.write(" %d; \n" % (max_infl * 3)) - self.file.write(" %d; \n" % (len(arm.bones.values()))) - self.file.write(" }\n") - - for bo in arm.bones.values() : - bo_list = [] - weight_list = [] - name = bo.name - f_name = make_legal_name(name) - try : - vert_list = mesh.getVertsFromGroup(name,1) - le = 0 - for indx in vert_list: - ver_infl = mesh.getVertexInfluences(indx[0]) - infl = 0.0 - if len(ver_infl) != 0: - sum = 0.0 - for bone_n, weight in ver_infl: - if bone_n == name: - infl = weight - sum += weight - infl /= sum - - i = -1 - for el in index_list : - i += 1 - if el == indx[0] : - le +=1 - bo_list.append(i) - weight_list.append(infl) - - - self.file.write(" SkinWeights {\n") - self.file.write(' "%s"; \n' % (f_name)) - self.file.write(' %d; \n' % (le)) - count = 0 - for ind in bo_list : - count += 1 - if count == len(bo_list): - self.file.write(" %d; \n" % (ind)) - else : - self.file.write(" %d, \n" % (ind)) - cou = 0 - for wegh in weight_list : - cou += 1 - - if cou == len(weight_list): - self.file.write(" %f; \n" % (round(wegh,6))) - else : - self.file.write(" %f, \n" % (round(wegh,6))) - - - matx = self.writeMatrixOffset(bo) - self.writeOffsFrames(matx, name) - except : - pass - self.file.write(" } // End of XSkinMeshHeader\n") - - - #*********************************************** - # Write Matrices - #*********************************************** - def writeArmFrames(self, matx, name): - global space - tab = " " - self.file.write("%s" % (tab * space)) - self.file.write("Frame ") - self.file.write("%s {\n\n" % (name)) - self.file.write("%s" % (tab * space)) - self.file.write(" FrameTransformMatrix {\n") - self.writeFrame(matx) - - #*********************************************** - # Write Frames - #*********************************************** - def writeOffsFrames(self, matx, name): - space = 1 - self.writeFrame(matx) - - #*********************************************** - # Write Frames - #*********************************************** - def writeFrame(self, matx): - tab = " " - self.file.write("%s" % (tab * space)) - self.file.write(" %f,%f,%f,%f,\n" % - (round(matx[0][0],4),round(matx[0][1],4),round(matx[0][2],4),round(matx[0][3],4))) - self.file.write("%s" % (tab * space)) - self.file.write(" %f,%f,%f,%f,\n" % - (round(matx[1][0],4),round(matx[1][1],4),round(matx[1][2],4),round(matx[1][3],4))) - self.file.write("%s" % (tab * space)) - self.file.write(" %f,%f,%f,%f,\n" % - (round(matx[2][0],4),round(matx[2][1],4),round(matx[2][2],4),round(matx[2][3],4))) - self.file.write("%s" % (tab * space)) - self.file.write(" %f,%f,%f,%f;;\n" % - (round(matx[3][0],4),round(matx[3][1],4),round(matx[3][2],4),round(matx[3][3],4))) - self.file.write("%s" % (tab * space)) - self.file.write(" }\n") -#********************************************************************************************************************************************* - - #*********************************************** - #HEADER - #*********************************************** - def writeHeader(self): - self.file.write("xof 0303txt 0032\n\n\n") - self.file.write("template VertexDuplicationIndices { \n\ - <b8d65549-d7c9-4995-89cf-53a9a8b031e3>\n\ - DWORD nIndices;\n\ - DWORD nOriginalVertices;\n\ - array DWORD indices[nIndices];\n\ -}\n\ -template XSkinMeshHeader {\n\ - <3cf169ce-ff7c-44ab-93c0-f78f62d172e2>\n\ - WORD nMaxSkinWeightsPerVertex;\n\ - WORD nMaxSkinWeightsPerFace;\n\ - WORD nBones;\n\ -}\n\ -template SkinWeights {\n\ - <6f0d123b-bad2-4167-a0d0-80224f25fabb>\n\ - STRING transformNodeName;\n\ - DWORD nWeights;\n\ - array DWORD vertexIndices[nWeights];\n\ - array float weights[nWeights];\n\ - Matrix4x4 matrixOffset;\n\ -}\n\n") - - #*********************************************** - #CLOSE FILE - #*********************************************** - def writeEnd(self): - self.file.close() - print "... finished" - - - #*********************************************** - #EXPORT TEXTURES - #*********************************************** - def writeTextures(self,name, tex): - mesh = name.data - for face in mesh.faces: - if face.image and face.image.name not in tex: - tex.append(face.image.name) - - - - #*********************************************** - #EXPORT MESH DATA with Armature - #*********************************************** - def writeMeshcoordArm(self, obj ,arm_ob): - global index_list,flip_z - #TransformMatrix - mat = self.getLocMat(obj) - self.writeArmFrames(mat, make_legal_name(obj.name)) - mesh = NMesh.GetRawFromObject(obj.name) - self.file.write("Mesh {\n") - numface=len(mesh.faces) - #VERTICES NUMBER - numvert = 0 - for face in mesh.faces: - numvert = numvert + len(face.v) - self.file.write("%d;\n" % (numvert)) - if numvert == 0: - print "Mesh named",mesh.name,"has no vertices.Problems may occur using the .x file" - #VERTICES COORDINATES - counter = 0 - for face in mesh.faces: - counter += 1 - for n in range(len(face.v)): - index_list.append(face.v[n].index) - vec_vert = Vector([(face.v[n].co[0]), face.v[n].co[1], face.v[n].co[2], 1]) - if arm_ob : - f_vec_vert = vec_vert * mat - else : - f_vec_vert = vec_vert - self.file.write("%f; %f; %f;" % (round(f_vec_vert[0],4), round(f_vec_vert[1],4), round(f_vec_vert[2],4))) - if counter == numface : - if n == len(face.v)-1 : - self.file.write(";\n") - else : - self.file.write(",\n") - else : - self.file.write(",\n") - if flip_z: - a3 = 0;b3 = 2;c3 = 1 - a4 = 0;b4 = 3;c4 = 2;d4 = 1 - else: - a3 = 0;b3 = 1;c3 = 2 - a4 = 0;b4 = 1;c4 = 2;d4 = 3 - - #FACES NUMBER - self.file.write("%s;\n" % (numface)) - coun,counter = 0, 0 - for face in mesh.faces : - coun += 1 - separator = ',' - if coun == numface: - separator = ';' - if len(face.v) == 3: - self.file.write("3; %d, %d, %d;%c\n" % (counter + a3, counter + b3, counter + c3, separator)) - counter += 3 - elif len(face.v) == 4: - self.file.write("4; %d, %d, %d, %d;%c\n" % (counter + a4, counter + b4, counter + c4, counter + d4, separator)) - counter += 4 - elif len(face.v) < 3: - print "WARNING:the mesh has faces with less then 3 vertices" - print " It my be not exported correctly." - - - #*********************************************** - #MESH MATERIAL LIST - #*********************************************** - def writeMeshMaterialList(self, obj, mesh, tex): - self.file.write(" MeshMaterialList {\n") - #HOW MANY MATERIALS ARE USED - count = 0 - for mat in mesh.getMaterials(): - count+=1 - self.file.write(" %d;\n" % (len(tex) + count)) - #HOW MANY FACES IT HAS - numfaces=len(mesh.faces) - self.file.write(" %d;\n" % (numfaces)) - ##MATERIALS INDEX FOR EVERY FACE - counter = 0 - for face in mesh.faces : - counter += 1 - mater = face.materialIndex - if counter == numfaces: - if face.image and face.image.name in tex : - self.file.write(" %d;;\n" % (tex.index(face.image.name) + count)) - else : - self.file.write(" %d;;\n" % (mater)) - else : - if face.image and face.image.name in tex : - self.file.write(" %d,\n" % (tex.index(face.image.name) + count)) - else : - self.file.write(" %d,\n" % (mater)) - - ##MATERIAL NAME - for mat in mesh.getMaterials(): - self.file.write(" Material") - self.file.write(" %s "% (make_legal_name(mat.name))) - self.file.write("{\n") - self.file.write(" %f; %f; %f;" % (mat.R, mat.G, mat.B)) - self.file.write("%s;;\n" % (mat.alpha)) - self.file.write(" %f;\n" % (mat.spec)) - self.file.write(" %f; %f; %f;;\n" % (mat.specR, mat.specG, mat.specB)) - self.file.write(" 0.0; 0.0; 0.0;;\n") - self.file.write(" } //End of Material\n") - - for mat in tex: - self.file.write(" Material Mat") - self.file.write("%s "% (len(tex))) - self.file.write("{\n") - self.file.write(" 1.0; 1.0; 1.0; 1.0;;\n") - self.file.write(" 1.0;\n") - self.file.write(" 1.0; 1.0; 1.0;;\n") - self.file.write(" 0.0; 0.0; 0.0;;\n") - self.file.write(" TextureFilename {") - self.file.write(' "%s";'% (mat)) - self.file.write(" }\n") - self.file.write(" } // End of Material\n") - self.file.write(" } //End of MeshMaterialList\n") - - #*********************************************** - #MESH NORMALS - #*********************************************** - def writeMeshNormals(self,name,mesh): - global flip_norm,flip_z,no_light,recalc_norm,Bl_norm - - self.file.write(" MeshNormals {\n") - #VERTICES NUMBER - numvert = 0 - for face in mesh.faces: - numvert = numvert + len(face.v) - self.file.write("%d;\n" % (numvert)) - numfaces=len(mesh.faces) - if flip_norm : - fl = -1 - else : - fl = 1 - #VERTICES NORMAL - if Bl_norm: - self.writeBlenderNormals(mesh,fl) - if recalc_norm: - self.writeRecalcNormals(mesh,fl) - if no_light: - self.writeNoSmothing(mesh,fl) - - - - if flip_z: - a3 = 0;b3 = 2;c3 = 1 - a4 = 0;b4 = 3;c4 = 2;d4 = 1 - else: - a3 = 0;b3 = 1;c3 = 2 - a4 = 0;b4 = 1;c4 = 2;d4 = 3 - - #FACES NUMBER - self.file.write("%s;\n" % (numfaces)) - coun,counter = 0, 0 - for face in mesh.faces : - coun += 1 - if coun == numfaces: - if len(face.v) == 3: - self.file.write("3; %d, %d, %d;;\n" % (counter + a3, counter + b3, counter + c3)) - counter += 3 - else : - self.file.write("4; %d, %d, %d, %d;;\n" % (counter + a4, counter + b4, counter + c4, counter + d4)) - counter += 4 - else: - - if len(face.v) == 3: - self.file.write("3; %d, %d, %d;,\n" % (counter + a3, counter + b3, counter + c3)) - counter += 3 - else : - self.file.write("4; %d, %d, %d, %d;,\n" % (counter + a4, counter + b4, counter + c4, counter + d4)) - counter += 4 - self.file.write("} //End of MeshNormals\n") - - def writeBlenderNormals(self,mesh,fl): - numfaces=len(mesh.faces) - #VERTICES NORMAL - counter = 0 - for face in mesh.faces: - counter += 1 - for n in range(len(face.v)): - self.file.write(" %f; %f; %f;" % ( - (round(face.v[n].no[0],6)*fl),(round(face.v[n].no[1],6)*fl),(round(face.v[n].no[2],6)*fl))) - if counter == numfaces : - if n == len(face.v)-1 : - self.file.write(";\n") - else : - self.file.write(",\n") - else : - self.file.write(",\n") - - def writeRecalcNormals(self,mesh,fl): - numfaces=len(mesh.faces) - normal_list = {} - idx = 0 - for vertex in mesh.verts: - v_norm = Vector([0, 0, 0]) - normal_list[idx] = v_norm - idx += 1 - for face in mesh.faces: - for verts in face.v: - if verts.index == vertex.index : - v_norm[0] += face.no[0] - v_norm[1] += face.no[1] - v_norm[2] += face.no[2] - - v_norm.normalize() - - counter = 0 - for face in mesh.faces: - counter += 1 - n = 0 - for vert in face.v: - n += 1 - norm = normal_list[vert.index] - - self.file.write(" %f; %f; %f;" % ( - (round(norm[0],6)*fl),(round(norm[1],6)*fl),(round(norm[2],6)*fl))) - if counter == numfaces : - if n == len(face.v) : - self.file.write(";\n") - else : - self.file.write(",\n") - else : - self.file.write(",\n") - - def writeNoSmothing(self,mesh,fl): - numfaces=len(mesh.faces) - counter = 0 - for face in mesh.faces: - counter += 1 - n = 0 - for n in range(len(face.v)): - n += 1 - self.file.write(" %f; %f; %f;" % ( - (round(face.no[0],6)*fl),(round(face.no[1],6)*fl),(round(face.no[2],6)*fl))) - - - if counter == numfaces : - if n == len(face.v) : - self.file.write(";\n") - else : - self.file.write(",\n") - else : - self.file.write(",\n") - #*********************************************** - #MESH TEXTURE COORDS - #*********************************************** - def writeMeshTextureCoords(self, name, mesh): - if mesh.hasFaceUV(): - self.file.write("MeshTextureCoords {\n") - #VERTICES NUMBER - numvert = 0 - for face in mesh.faces: - numvert += len(face.v) - self.file.write("%d;\n" % (numvert)) - #UV COORDS - numfaces = len(mesh.faces) - counter = -1 - co = 0 - for face in mesh.faces: - counter += 1 - co += 1 - for n in range(len(face.v)): - self.file.write("%f;%f;" % (mesh.faces[counter].uv[n][0], -mesh.faces[counter].uv[n][1])) - if co == numfaces : - if n == len(face.v) - 1 : - self.file.write(";\n") - else : - self.file.write(",\n") - else : - self.file.write(",\n") - - self.file.write("} //End of MeshTextureCoords\n") - - #*********************************************** - #MESH VORTEX COLORS - #*********************************************** - def writeMeshVertexColors(self, name, mesh): - if mesh.hasVertexColours(): - self.file.write("MeshVertexColors {\n") - #VERTICES NUMBER - numvert = reduce( lambda i,f: len(f)+i, mesh.faces, 0) - self.file.write("%d;\n" % (numvert)) - #VERTEX COLORS - - vcounter =0 - for f in mesh.faces: - col = f.col - for i,c in enumerate(col): - # Note vcol alpha has no meaning - self.file.write("%d;%f;%f;%f;%f;" % (vcounter,c.r/255.0, c.g/255.0, c.b/255.0, 1.0)) # c.a/255.0)) - vcounter+=1 - if vcounter == numvert : - self.file.write(";\n") - else : - self.file.write(",\n") - - self.file.write("} //End of MeshVertexColors\n") - -#***********************************************#***********************************************#*********************************************** - #*********************************************** - #FRAMES - #*********************************************** - def writeFrames(self, matx): - - self.file.write("%f,%f,%f,%f," % - (round(matx[0][0],4),round(matx[0][1],4),round(matx[0][2],4),round(matx[0][3],4))) - self.file.write("%f,%f,%f,%f," % - (round(matx[1][0],4),round(matx[1][1],4),round(matx[1][2],4),round(matx[1][3],4))) - self.file.write("%f,%f,%f,%f," % - (round(matx[2][0],4),round(matx[2][1],4),round(matx[2][2],4),round(matx[2][3],4))) - self.file.write("%f,%f,%f,%f;;" % - (round(matx[3][0],4),round(matx[3][1],4),round(matx[3][2],4),round(matx[3][3],4))) - - - - - - #*********************************************** - #WRITE ANIMATION KEYS - #*********************************************** - def writeAnimation(self,arm_ob): - global mat_dict, root_bon - arm = arm_ob.getData() - act_list = arm_ob.getAction() - ip = act_list.getAllChannelIpos() - for bon in arm.bones.values() : - point_list = [] - name = bon.name - name_f = make_legal_name(name) - try : - ip_bon_channel = ip[bon.name] - ip_bon_name = ip_bon_channel.getName() - - ip_bon = Blender.Ipo.Get(ip_bon_name) - poi = ip_bon.getCurves() - - for po in poi[3].getPoints(): - a = po.getPoints() - point_list.append(int(a[0])) - #point_list.pop(0) - - self.file.write(" Animation { \n") - self.file.write(" { %s }\n" %(name_f)) - self.file.write(" AnimationKey { \n") - self.file.write(" 4;\n") - self.file.write(" %d; \n" % (len(point_list))) - - for fr in point_list: - - if name == root_bon.name : - - - mat_b = self.writeAnimCombineMatrix(bon,fr) - mat_arm = self.getLocMat(arm_ob) - mat = mat_b * mat_arm - else: - mat = self.writeAnimCombineMatrix(bon,fr) - - self.file.write(" %d;" % (fr)) - self.file.write("16;") - - self.writeFrames(mat) - - if fr == point_list[len(point_list)-1]: - self.file.write(";\n") - else: - self.file.write(",\n") - self.file.write(" }\n") - self.file.write(" }\n") - self.file.write("\n") - except: - pass - - - - #*********************************************** - #WRITE ANIMATION KEYS - #*********************************************** - def writeAnimationObj(self, obj): - point_list = [] - ip = obj.ipo - poi = ip.getCurves() - for po in poi[0].getPoints(): - a = po.getPoints() - point_list.append(int(a[0])) - - self.file.write(" Animation {\n") - self.file.write(" { ") - self.file.write("%s }\n" % (make_legal_name(obj.name))) - self.file.write(" AnimationKey { \n") - self.file.write(" 4;\n") - self.file.write(" %d; \n" % (len(point_list))) - for fr in point_list: - self.file.write(" %d;" % (fr)) - self.file.write("16;") - Blender.Set('curframe',fr) - - #mat_new = self.getLocMat(obj) - mat_new = obj.matrixLocal - self.writeFrames(mat_new) - - if fr == point_list[len(point_list)-1]: - self.file.write(";\n") - else: - self.file.write(",\n") - self.file.write(" }\n") - self.file.write(" }\n") - - - -#***********************************************#***********************************************#*********************************************** - - - - - diff --git a/release/scripts/DirectX8Importer.py b/release/scripts/DirectX8Importer.py deleted file mode 100644 index 0dda654944d..00000000000 --- a/release/scripts/DirectX8Importer.py +++ /dev/null @@ -1,238 +0,0 @@ -#!BPY - -""" Registration info for Blender menus: -Name: 'DirectX(.x)...' -Blender: 244 -Group: 'Import' - -Tip: 'Import from DirectX text file format format.' -""" -# DirectXImporter.py version 1.2 -# Copyright (C) 2005 Arben OMARI -- omariarben@everyday.com -# -# 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. - -# This script import meshes from DirectX text file format - -# Grab the latest version here :www.omariben.too.it -import bpy -import Blender -from Blender import Mesh,Object,Material,Texture,Image,Draw - - -class xImport: - def __init__(self, filename): - global my_path - self.file = open(filename, "r") - my_path = Blender.sys.dirname(filename) - - # - self.lines = [l_split for l in self.file.readlines() for l_split in (' '.join(l.split()),) if l_split] - - def Import(self): - lines = self.lines - print "importing into Blender ..." - scene = bpy.data.scenes.active - - mesh_indicies = {} # the index of each 'Mesh' is used as the key for those meshes indicies - context_indicies = None # will raise an error if used! - - - #Get the line of Texture Coords - nr_uv_ind = 0 - - #Get Materials - nr_fac_mat = 0 - i = -1 - mat_list = [] - tex_list = [] - mesh_line_indicies = [] - for j, line in enumerate(lines): - l = line.strip() - words = line.split() - if words[0] == "Material" : - #context_indicies["Material"] = j - self.loadMaterials(j, mat_list, tex_list) - elif words[0] == "MeshTextureCoords" : - context_indicies["MeshTextureCoords"] = j - #nr_uv_ind = j - elif words[0] == "MeshMaterialList" : - context_indicies["MeshMaterialList"] = j+2 - #nr_fac_mat = j + 2 - elif words[0] == "Mesh": # Avoid a second loop - context_indicies = mesh_indicies[j] = {'MeshTextureCoords':0, 'MeshMaterialList':0} - - for mesh_index, value in mesh_indicies.iteritems(): - mesh = Mesh.New() - self.loadVertices(mesh_index, mesh, value['MeshTextureCoords'], value['MeshMaterialList'], tex_list) - - mesh.materials = mat_list[:16] - if value['MeshMaterialList']: - self.loadMeshMaterials(value['MeshMaterialList'], mesh) - scene.objects.new(mesh) - - self.file.close() - print "... finished" - - #------------------------------------------------------------------------------ - # CREATE THE MESH - #------------------------------------------------------------------------------ - def loadVertices(self, nr_vr_ind, mesh, nr_uv, nr_fac_mat, tex_list): - v_ind = nr_vr_ind + 1 - lin = self.lines[v_ind] - if lin : - lin_c = self.CleanLine(lin) - nr_vert = int((lin_c.split()[0])) - else : - v_ind = nr_vr_ind + 2 - lin = self.lines[v_ind] - lin_c = self.CleanLine(lin) - nr_vert = int((lin_c.split()[0])) - - #-------------------------------------------------- - nr_fac_li = v_ind + nr_vert +1 - lin_f = self.lines[nr_fac_li] - if lin_f : - lin_fc = self.CleanLine(lin_f) - nr_face = int((lin_fc.split()[0])) - else : - nr_fac_li = v_ind + nr_vert +1 - lin_f = self.lines[nr_fac_li] - lin_fc = self.CleanLine(lin_f) - nr_face = int((lin_fc.split()[0])) - - #Get Coordinates - verts_list = [(0,0,0)] # WARNING - DUMMY VERT - solves EEKADOODLE ERROR - for l in xrange(v_ind + 1, (v_ind + nr_vert +1)): - line_v = self.lines[l] - lin_v = self.CleanLine(line_v) - words = lin_v.split() - if len(words)==3: - verts_list.append((float(words[0]),float(words[1]),float(words[2]))) - - mesh.verts.extend(verts_list) - del verts_list - - face_list = [] - #Make Faces - i = 0 - mesh_verts = mesh.verts - for f in xrange(nr_fac_li + 1, (nr_fac_li + nr_face + 1)): - i += 1 - line_f = self.lines[f] - lin_f = self.CleanLine(line_f) - - # +1 for dummy vert only! - words = lin_f.split() - if len(words) == 5: - face_list.append((1+int(words[1]), 1+int(words[2]), 1+int(words[3]), 1+int(words[4]))) - elif len(words) == 4: - face_list.append((1+int(words[1]), 1+int(words[2]), 1+int(words[3]))) - - mesh.faces.extend(face_list) - del face_list - - if nr_uv : - mesh.faceUV = True - for f in mesh.faces: - fuv = f.uv - for ii, v in enumerate(f): - # _u, _v = self.CleanLine(self.lines[nr_uv + 2 + v.index]).split() - - # Use a dummy vert - _u, _v = self.CleanLine(self.lines[nr_uv + 1 + v.index]).split() - - fuv[ii].x = float(_u) - fuv[ii].y = float(_v) - - if nr_fac_mat : - fac_line = self.lines[nr_fac_mat + i] - fixed_fac = self.CleanLine(fac_line) - w_tex = int(fixed_fac.split()[0]) - f.image = tex_list[w_tex] - - # remove dummy vert - mesh.verts.delete([0,]) - - def CleanLine(self,line): - return line.replace(\ - ";", " ").replace(\ - '"', ' ').replace(\ - "{", " ").replace(\ - "}", " ").replace(\ - ",", " ").replace(\ - "'", " ") - - #------------------------------------------------------------------ - # CREATE MATERIALS - #------------------------------------------------------------------ - def loadMaterials(self, nr_mat, mat_list, tex_list): - - def load_image(name): - try: - return Image.Load(Blender.sys.join(my_path,name)) - except: - return None - - mat = bpy.data.materials.new() - line = self.lines[nr_mat + 1] - fixed_line = self.CleanLine(line) - words = fixed_line.split() - mat.rgbCol = [float(words[0]),float(words[1]),float(words[2])] - mat.setAlpha(float(words[3])) - mat_list.append(mat) - l = self.lines[nr_mat + 5] - fix_3_line = self.CleanLine(l) - tex_n = fix_3_line.split() - - if tex_n and tex_n[0] == "TextureFilename" : - - if len(tex_n) > 1: - tex_list.append(load_image(tex_n[1])) - - if len(tex_n) <= 1 : - - l_succ = self.lines[nr_mat + 6] - fix_3_succ = self.CleanLine(l_succ) - tex_n_succ = fix_3_succ.split() - tex_list.append(load_image(tex_n_succ[0])) - else : - tex_list.append(None) # no texture for this index - - return mat_list, tex_list - #------------------------------------------------------------------ - # SET MATERIALS - #------------------------------------------------------------------ - def loadMeshMaterials(self, nr_fc_mat, mesh): - for face in mesh.faces: - nr_fc_mat += 1 - line = self.lines[nr_fc_mat] - fixed_line = self.CleanLine(line) - wrd = fixed_line.split() - mat_idx = int(wrd[0]) - face.mat = mat_idx - -#------------------------------------------------------------------ -# MAIN -#------------------------------------------------------------------ -def my_callback(filename): - if not filename.lower().endswith('.x'): print "Not an .x file" - ximport = xImport(filename) - ximport.Import() - -arg = __script__['arg'] - -if __name__ == '__main__': - Blender.Window.FileSelector(my_callback, "Import DirectX", "*.x") - -#my_callback('/fe/x/directxterrain.x') -#my_callback('/fe/x/Male_Normal_MAX.X') -#my_callback('/fe/x/male_ms3d.x') diff --git a/release/scripts/IDPropBrowser.py b/release/scripts/IDPropBrowser.py deleted file mode 100644 index 2a14760270a..00000000000 --- a/release/scripts/IDPropBrowser.py +++ /dev/null @@ -1,523 +0,0 @@ -#!BPY - -""" -Name: 'ID Property Browser' -Blender: 242 -Group: 'Help' -Tooltip: 'Browse ID properties' -""" - -__author__ = "Joe Eagar" -__version__ = "0.3.108" -__email__ = "joeedh@gmail.com" -__bpydoc__ = """\ - -Allows browsing, creating and editing of ID Properties -for various ID block types such as mesh, scene, object, -etc. -""" - -# -------------------------------------------------------------------------- -# ID Property Browser. -# -------------------------------------------------------------------------- -# ***** 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 ***** -# -------------------------------------------------------------------------- - - -from Blender import * -from Blender.BGL import * -from Blender.Types import IDGroupType, IDArrayType -import Blender - -def IsInRectWH(mx, my, x, y, wid, hgt): - if mx >= x and mx <= x + wid: - if my >= y and my <= y + hgt: - return 1 - return 0 - -Button_Back = 1 -Button_New = 2 -Button_MatMenu = 3 -Button_TypeMenu = 4 - -ButStart = 55 - -IDP_String = 0 -IDP_Int = 1 -IDP_Float = 2 -IDP_Array = 5 -IDP_Group = 6 - -ButDelStart = 255 -#max limit for string input button -strmax = 100 - -State_Normal = 0 -State_InArray = 1 - -#IDTypeModules entries are of form [module, active_object_index, module_name] -IDTypeModules = [[Scene, 0, "Scenes"], [Object, 0, "Objects"], [Mesh, 0, "Meshes"]] -IDTypeModules += [[Material, 0, "Materials"], [Texture, 0, "Textures"]] -IDTypeModules += [[Image, 0, "Images"]] - -class IDArrayBrowser: - array = 0 - parentbrowser = 0 - buts = 0 - - def __init__(self): - self.buts = [] - - def Draw(self): - pb = self.parentbrowser - x = pb.x - y = pb.y - width = pb.width - height = pb.height - pad = pb.pad - itemhgt = pb.itemhgt - cellwid = 65 - y = y + height - itemhgt - pad - - Draw.PushButton("Back", Button_Back, x, y, 40, 20) - y -= itemhgt + pad - - self.buts = [] - Draw.BeginAlign() - for i in xrange(len(self.array)): - st = "" - if type(self.array[0]) == float: - st = "%.5f" % self.array[i] - else: st = str(self.array[i]) - - b = Draw.String("", ButStart+i, x, y, cellwid, itemhgt, st, 30) - self.buts.append(b) - x += cellwid + pad - if x + cellwid + pad > width: - x = 0 - y -= itemhgt + pad - Draw.EndAlign() - def Button(self, bval): - if bval == Button_Back: - self.parentbrowser.state = State_Normal - self.parentbrowser.array = 0 - self.buts = [] - Draw.Draw() - self.array = 0 - elif bval >= ButStart: - i = bval - ButStart - st = self.buts[i].val - n = 0 - if type(self.array[0]) == float: - try: - n = int(st) - except: - return - elif type(self.array[0]) == int: - try: - n = float(st) - except: - return - - self.array[i] = n - Draw.Draw() - - def Evt(self, evt, val): - if evt == Draw.ESCKEY: - Draw.Exit() - -class IDPropertyBrowser: - width = 0 - height = 0 - x = 0 - y = 0 - scrollx = 0 - scrolly = 0 - itemhgt = 22 - pad = 2 - - group = 0 - parents = 0 #list stack of parent groups - active_item = -1 - mousecursor = 0 - _i = 0 - buts = [] - - state = 0 - array = 0 - prop = 0 - - IDList = 0 - idindex = 0 - idblock = 0 - - type = 0 # attach buildin type() method to class - # since oddly it's not available to button - # callbacks! EEK! :( - - def __init__(self, idgroup, mat, x, y, wid, hgt): - self.group = idgroup - self.prop = idgroup - self.x = x - self.y = y - self.width = wid - self.height = hgt - self.mousecursor = [0, 0] - self.parents = [] - self.idblock = mat - self.type = type - - def DrawBox(self, glmode, x, y, width, height): - glBegin(glmode) - glVertex2f(x, y) - glVertex2f(x+width, y) - glVertex2f(x+width, y+height) - glVertex2f(x, y+height) - glEnd() - - def Draw(self): - global IDTypeModules - - #first draw outlining box :) - glColor3f(0, 0, 0) - self.DrawBox(GL_LINE_LOOP, self.x, self.y, self.width, self.height) - - itemhgt = self.itemhgt - pad = self.pad - x = self.x - y = self.y + self.height - itemhgt - pad - - if self.state == State_InArray: - self.array.Draw() - return - - plist = [] - self.buts = [] - for p in self.group.iteritems(): - plist.append(p) - - #-------do top buttons----------# - Draw.BeginAlign() - Draw.PushButton("New", Button_New, x, y, 40, 20) - x += 40 + pad - #do the menu button for all materials - st = "" - - blocks = IDTypeModules[self.IDList][0].Get() - i = 1 - mi = 0 - for m in blocks: - if m.name == self.idblock.name: - mi = i - st += m.name + " %x" + str(i) + "|" - i += 1 - - self.menubut = Draw.Menu(st, Button_MatMenu, x, y, 100, 20, mi) - - x += 100 + pad - - st = "" - i = 0 - for e in IDTypeModules: - st += e[2] + " %x" + str(i+1) + "|" - i += 1 - - cur = self.IDList + 1 - self.idmenu = Draw.Menu(st, Button_TypeMenu, x, y, 100, 20, cur) - x = self.x - y -= self.itemhgt + self.pad - Draw.EndAlign() - - - #-----------do property items---------# - i = 0 - while y > self.y - 20 - pad and i < len(plist): - k = plist[i][0] - p = plist[i][1] - if i == self.active_item: - glColor3f(0.5, 0.4, 0.3) - self.DrawBox(GL_POLYGON, x+pad, y, self.width-pad*2, itemhgt) - - glColor3f(0, 0, 0) - self.DrawBox(GL_LINE_LOOP, x+pad, y, self.width-pad*2, itemhgt) - - glRasterPos2f(x+pad*2, y+5) - Draw.Text(str(k)) #str(self.mousecursor) + " " + str(self.active_item)) #p.name) - tlen = Draw.GetStringWidth(str(k)) - - type_p = type(p) - if type_p == str: - b = Draw.String("", ButStart+i, x+pad*5+tlen, y, 200, itemhgt, p, strmax) - self.buts.append(b) - elif type_p in [int, float]: - #only do precision to 5 points on floats - st = "" - if type_p == float: - st = "%.5f" % p - else: st = str(p) - b = Draw.String("", ButStart+i, x+pad*5+tlen, y, 75, itemhgt, st, strmax) - self.buts.append(b) - else: - glRasterPos2f(x+pad*2 +tlen+10, y+5) - if type_p == Types.IDArrayType: - Draw.Text('(array, click to edit)') - elif type_p == Types.IDGroupType: - Draw.Text('(group, click to edit)') - - - self.buts.append(None) - - Draw.PushButton("Del", ButDelStart+i, x+self.width-35, y, 30, 20) - - i += 1 - y -= self.itemhgt + self.pad - - if len(self.parents) != 0: - Draw.PushButton("Back", Button_Back, x, y, 40, 20) - x = x + 40 + pad - - def SetActive(self): - m = self.mousecursor - itemhgt = self.itemhgt - pad = self.pad - - x = self.x + pad - y = self.y + self.height - itemhgt - pad - itemhgt - - plist = [] - for p in self.group.iteritems(): - plist.append(p) - - self.active_item = -1 - i = 0 - while y > self.y and i < len(plist): - p = plist[i] - if IsInRectWH(m[0], m[1], x, y, self.width-pad, itemhgt): - self.active_item = i - - i += 1 - y -= self.itemhgt + self.pad - - def EventIn(self, evt, val): - if self.state == State_InArray: - self.array.Evt(evt, val) - - if evt == Draw.ESCKEY: - Draw.Exit() - if evt == Draw.MOUSEX or evt == Draw.MOUSEY: - size = Buffer(GL_FLOAT, 4) - glGetFloatv(GL_SCISSOR_BOX, size) - if evt == Draw.MOUSEX: - self.mousecursor[0] = val - size[0] - else: - self.mousecursor[1] = val - size[1] - del size - - self.SetActive() - self._i += 1 - if self._i == 5: - Draw.Draw() - self._i = 0 - - - if evt == Draw.LEFTMOUSE and val == 1: - plist = list(self.group.iteritems()) - a = self.active_item - if a >= 0 and a < len(plist): - p = plist[a] - - basictypes = [IDGroupType, float, str, int] - if type(p[1]) == IDGroupType: - self.parents.append(self.group) - self.group = p[1] - self.active_item = -1 - Draw.Draw() - elif type(p[1]) == IDArrayType: - self.array = IDArrayBrowser() - self.array.array = p[1] - self.array.parentbrowser = self - self.state = State_InArray - Draw.Draw() - - if evt == Draw.TKEY and val == 1: - try: - self.prop['float'] = 0.0 - self.prop['int'] = 1 - self.prop['string'] = "hi!" - self.prop['float array'] = [0, 0, 1.0, 0] - self.prop['int array'] = [0, 0, 0, 0] - self.prop.data['a subgroup'] = {"int": 0, "float": 0.0, "anothergroup": {"a": 0.0, "intarr": [0, 0, 0, 0]}} - Draw.Draw() - except: - Draw.PupMenu("Can only do T once per block, the test names are already taken!") - - - def Button(self, bval): - global IDTypeModules - if self.state == State_InArray: - self.array.Button(bval) - return - - if bval == Button_MatMenu: - global IDTypeModules - - val = self.idindex = self.menubut.val - 1 - i = self.IDList - block = IDTypeModules[i][0].Get()[val] - self.idblock = block - self.prop = block.properties - self.group = self.prop - self.active_item = -1 - self.parents = [] - Draw.Draw() - - if bval == Button_TypeMenu: - i = IDTypeModules[self.idmenu.val-1] - if len(i[0].Get()) == 0: - Draw.PupMenu("Error%t|There are no " + i[2] + "!") - return - - IDTypeModules[self.IDList][1] = self.idindex - self.IDList = self.idmenu.val-1 - val = self.idindex = IDTypeModules[self.IDList][1] - i = self.IDList - block = IDTypeModules[i][0].Get()[val] - self.idblock = block - self.prop = block.properties - self.group = self.prop - self.active_item = -1 - self.parents = [] - Draw.Draw() - - if bval >= ButDelStart: - plist = [p for p in self.group] - prop = plist[bval - ButDelStart] - del self.group[prop] - Draw.Draw() - - elif bval >= ButStart: - plist = list(self.group.iteritems()) - - prop = plist[bval - ButStart] - print prop - - if self.type(prop[1]) == str: - self.group[prop[0]] = self.buts[bval - ButStart].val - elif self.type(prop[1]) == int: - i = self.buts[bval - ButStart].val - try: - i = int(i) - self.group[prop[0]] = i - except: - Draw.Draw() - return - Draw.Draw() - elif self.type(prop[1]) == float: - f = self.buts[bval - ButStart].val - try: - f = float(f) - self.group[prop[0]] = f - except: - Draw.Draw() - return - Draw.Draw() - - elif bval == Button_Back: - self.group = self.parents[len(self.parents)-1] - self.parents.pop(len(self.parents)-1) - Draw.Draw() - - elif bval == Button_New: - name = Draw.Create("untitled") - stype = Draw.Create(0) - gtype = Draw.Create(0) - ftype = Draw.Create(0) - itype = Draw.Create(0) - atype = Draw.Create(0) - - block = [] - block.append(("Name: ", name, 0, 30, "Click to type in the name of the new ID property")) - block.append("Type") - block.append(("String", stype)) - block.append(("Subgroup", gtype)) - block.append(("Float", ftype)) - block.append(("Int", itype)) - block.append(("Array", atype)) - - retval = Blender.Draw.PupBlock("New IDProperty", block) - if retval == 0: return - - name = name.val - i = 1 - stop = 0 - while stop == 0: - stop = 1 - for p in self.group: - if p == name: - d = name.rfind(".") - if d != -1: - name = name[:d] - name = name + "." + str(i).zfill(3) - i += 1 - stop = 0 - - type = "String" - if stype.val: - self.group[name] = "" - elif gtype.val: - self.group[name] = {} - elif ftype.val: - self.group[name] = 0.0 - elif itype.val: - self.group[name] = 0 #newProperty("Int", name, 0) - elif atype.val: - arrfloat = Draw.Create(1) - arrint = Draw.Create(0) - arrlen = Draw.Create(3) - block = [] - block.append("Type") - block.append(("Float", arrfloat, "Make a float array")) - block.append(("Int", arrint, "Make an integer array")) - block.append(("Len", arrlen, 2, 200)) - - if Blender.Draw.PupBlock("Array Properties", block): - if arrfloat.val: - tmpl = 0.0 - elif arrint.val: - tmpl = 0 - else: - return - - self.group[name] = [tmpl] * arrlen.val - - - def Go(self): - Draw.Register(self.Draw, self.EventIn, self.Button) - -scenes = Scene.Get() - -size = Window.GetAreaSize() -browser = IDPropertyBrowser(scenes[0].properties, scenes[0], 2, 2, size[0], size[1]) -browser.Go() - -#a = prop.newProperty("String", "hwello!", "bleh") -#b = prop.newProperty("Group", "subgroup") - -#for p in prop: - #print p.name diff --git a/release/scripts/ac3d_export.py b/release/scripts/ac3d_export.py deleted file mode 100644 index 57f27c7e3a2..00000000000 --- a/release/scripts/ac3d_export.py +++ /dev/null @@ -1,828 +0,0 @@ -#!BPY - -""" Registration info for Blender menus: -Name: 'AC3D (.ac)...' -Blender: 243 -Group: 'Export' -Tip: 'Export selected meshes to AC3D (.ac) format' -""" - -__author__ = "Willian P. Germano" -__url__ = ("blender", "blenderartists.org", "AC3D's homepage, http://www.ac3d.org", - "PLib 3d gaming lib, http://plib.sf.net") -__version__ = "2.44 2007-05-05" - -__bpydoc__ = """\ -This script exports selected Blender meshes to AC3D's .ac file format. - -AC3D is a simple commercial 3d modeller also built with OpenGL. -The .ac file format is an easy to parse text format well supported, -for example, by the PLib 3d gaming library (AC3D 3.x). - -Supported:<br> - UV-textured meshes with hierarchy (grouping) information. - -Missing:<br> - The 'url' tag, specific to AC3D. It is easy to add by hand to the exported -file, if needed. - -Known issues:<br> - The ambient and emit data we can retrieve from Blender are single values, -that this script copies to R, G, B, giving shades of gray.<br> - Loose edges (lines) receive the first material found in the mesh, if any, or a default white material.<br> - In AC3D 4 "compatibility mode":<br> - - shininess of materials is taken from the shader specularity value in Blender, mapped from [0.0, 2.0] to [0, 128];<br> - - crease angle is exported, but in Blender it is limited to [1, 80], since there are other more powerful ways to control surface smoothing. In AC3D 4.0 crease's range is [0.0, 180.0]; - -Config Options:<br> - toggle:<br> - - AC3D 4 mode: unset it to export without the 'crease' tag that was -introduced with AC3D 4.0 and with the old material handling;<br> - - global coords: transform all vertices of all meshes to global coordinates;<br> - - skip data: set it if you don't want mesh names (ME:, not OB: field) -to be exported as strings for AC's "data" tags (19 chars max);<br> - - rgb mirror color can be exported as ambient and/or emissive if needed, -since Blender handles these differently;<br> - - default mat: a default (white) material is added if some mesh was -left without mats -- it's better to always add your own materials;<br> - - no split: don't split meshes (see above);<br> - - set texture dir: override the actual textures path with a given default -path (or simply export the texture names, without dir info, if the path is -empty);<br> - - per face 1 or 2 sided: override the "Double Sided" button that defines this behavior per whole mesh in favor of the UV Face Select mode "twosided" per face atribute;<br> - - only selected: only consider selected objects when looking for meshes -to export (read notes below about tokens, too);<br> - strings:<br> - - export dir: default dir to export to;<br> - - texture dir: override textures path with this path if 'set texture dir' -toggle is "on". - -Notes:<br> - This version updates:<br> - - modified meshes are correctly exported, no need to apply the modifiers in Blender;<br> - - correctly export each used material, be it assigned to the object or to its mesh data;<br> - - exporting lines (edges) is again supported; color comes from first material found in the mesh, if any, or a default white one.<br> - - there's a new option to choose between exporting meshes with transformed (global) coordinates or local ones;<br> - Multiple textures per mesh are supported (mesh gets split);<br> - Parents are exported as a group containing both the parent and its children;<br> - Start mesh object names (OB: field) with "!" or "#" if you don't want them to be exported;<br> - Start mesh object names (OB: field) with "=" or "$" to prevent them from being split (meshes with multiple textures or both textured and non textured faces are split unless this trick is used or the "no split" option is set. -""" - -# $Id$ -# -# -------------------------------------------------------------------------- -# AC3DExport version 2.44 -# Program versions: Blender 2.42+ and AC3Db files (means version 0xb) -# new: updated for new Blender version and Mesh module; supports lines (edges) again; -# option to export vertices transformed to global coordinates or not; now the modified -# (by existing mesh modifiers) mesh is exported; materials are properly exported, no -# matter if each of them is linked to the mesh or to the object. New (2.43.1): loose -# edges use color of first material found in the mesh, if any. -# -------------------------------------------------------------------------- -# Thanks: Steve Baker for discussions and inspiration; for testing, bug -# reports, suggestions, patches: David Megginson, Filippo di Natale, -# Franz Melchior, Campbell Barton, Josh Babcock, Ralf Gerlich, Stewart Andreason. -# -------------------------------------------------------------------------- -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Copyright (C) 2004-2007: Willian P. Germano, wgermano _at_ ig.com.br -# -# 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, -# -------------------------------------------------------------------------- - -import Blender -from Blender import Object, Mesh, Material, Image, Mathutils, Registry -from Blender import sys as bsys - -# Globals -REPORT_DATA = { - 'main': [], - 'errors': [], - 'warns': [], - 'nosplit': [], - 'noexport': [] -} -TOKENS_DONT_EXPORT = ['!', '#'] -TOKENS_DONT_SPLIT = ['=', '$'] - -MATIDX_ERROR = 0 - -# flags: -LOOSE = Mesh.EdgeFlags['LOOSE'] -FACE_TWOSIDED = Mesh.FaceModes['TWOSIDE'] -MESH_TWOSIDED = Mesh.Modes['TWOSIDED'] - -REG_KEY = 'ac3d_export' - -# config options: -GLOBAL_COORDS = True -SKIP_DATA = False -MIRCOL_AS_AMB = False -MIRCOL_AS_EMIS = False -ADD_DEFAULT_MAT = True -SET_TEX_DIR = True -TEX_DIR = '' -AC3D_4 = True # export crease value, compatible with AC3D 4 loaders -NO_SPLIT = False -ONLY_SELECTED = True -EXPORT_DIR = '' -PER_FACE_1_OR_2_SIDED = True - -tooltips = { - 'GLOBAL_COORDS': "transform all vertices of all meshes to global coordinates", - 'SKIP_DATA': "don't export mesh names as data fields", - 'MIRCOL_AS_AMB': "export mirror color as ambient color", - 'MIRCOL_AS_EMIS': "export mirror color as emissive color", - 'ADD_DEFAULT_MAT': "always add a default white material", - 'SET_TEX_DIR': "don't export default texture paths (edit also \"tex dir\")", - 'EXPORT_DIR': "default / last folder used to export .ac files to", - 'TEX_DIR': "(see \"set tex dir\") dir to prepend to all exported texture names (leave empty for no dir)", - 'AC3D_4': "compatibility mode, adds 'crease' tag and slightly better material support", - 'NO_SPLIT': "don't split meshes with multiple textures (or both textured and non textured polygons)", - 'ONLY_SELECTED': "export only selected objects", - 'PER_FACE_1_OR_2_SIDED': "override \"Double Sided\" button in favor of per face \"twosided\" attribute (UV Face Select mode)" -} - -def update_RegistryInfo(): - d = {} - d['SKIP_DATA'] = SKIP_DATA - d['MIRCOL_AS_AMB'] = MIRCOL_AS_AMB - d['MIRCOL_AS_EMIS'] = MIRCOL_AS_EMIS - d['ADD_DEFAULT_MAT'] = ADD_DEFAULT_MAT - d['SET_TEX_DIR'] = SET_TEX_DIR - d['TEX_DIR'] = TEX_DIR - d['AC3D_4'] = AC3D_4 - d['NO_SPLIT'] = NO_SPLIT - d['EXPORT_DIR'] = EXPORT_DIR - d['ONLY_SELECTED'] = ONLY_SELECTED - d['PER_FACE_1_OR_2_SIDED'] = PER_FACE_1_OR_2_SIDED - d['tooltips'] = tooltips - d['GLOBAL_COORDS'] = GLOBAL_COORDS - Registry.SetKey(REG_KEY, d, True) - -# Looking for a saved key in Blender.Registry dict: -rd = Registry.GetKey(REG_KEY, True) - -if rd: - try: - AC3D_4 = rd['AC3D_4'] - SKIP_DATA = rd['SKIP_DATA'] - MIRCOL_AS_AMB = rd['MIRCOL_AS_AMB'] - MIRCOL_AS_EMIS = rd['MIRCOL_AS_EMIS'] - ADD_DEFAULT_MAT = rd['ADD_DEFAULT_MAT'] - SET_TEX_DIR = rd['SET_TEX_DIR'] - TEX_DIR = rd['TEX_DIR'] - EXPORT_DIR = rd['EXPORT_DIR'] - ONLY_SELECTED = rd['ONLY_SELECTED'] - NO_SPLIT = rd['NO_SPLIT'] - PER_FACE_1_OR_2_SIDED = rd['PER_FACE_1_OR_2_SIDED'] - GLOBAL_COORDS = rd['GLOBAL_COORDS'] - except KeyError: update_RegistryInfo() - -else: - update_RegistryInfo() - -VERBOSE = True -CONFIRM_OVERWRITE = True - -# check General scripts config key for default behaviors -rd = Registry.GetKey('General', True) -if rd: - try: - VERBOSE = rd['verbose'] - CONFIRM_OVERWRITE = rd['confirm_overwrite'] - except: pass - - -# The default material to be used when necessary (see ADD_DEFAULT_MAT) -DEFAULT_MAT = \ -'MATERIAL "DefaultWhite" rgb 1 1 1 amb 1 1 1 emis 0 0 0 \ -spec 0.5 0.5 0.5 shi 64 trans 0' - -# This transformation aligns Blender and AC3D coordinate systems: -BLEND_TO_AC3D_MATRIX = Mathutils.Matrix([1,0,0,0], [0,0,-1,0], [0,1,0,0], [0,0,0,1]) - -def Round_s(f): - "Round to default precision and turn value to a string" - r = round(f,6) # precision set to 10e-06 - if r == int(r): - return str(int(r)) - else: - return str(r) - -def transform_verts(verts, m): - vecs = [] - for v in verts: - x, y, z = v.co - vec = Mathutils.Vector([x, y, z, 1]) - vecs.append(vec*m) - return vecs - -def get_loose_edges(mesh): - loose = LOOSE - return [e for e in mesh.edges if e.flag & loose] - -# --- - -# meshes with more than one texture assigned -# are split and saved as these foomeshes -class FooMesh: - - class FooVert: - def __init__(self, v): - self.v = v - self.index = 0 - - class FooFace: - def __init__(self, foomesh, f): - self.f = f - foov = foomesh.FooVert - self.v = [foov(f.v[0]), foov(f.v[1])] - len_fv = len(f.v) - if len_fv > 2 and f.v[2]: - self.v.append(foov(f.v[2])) - if len_fv > 3 and f.v[3]: self.v.append(foov(f.v[3])) - - def __getattr__(self, attr): - if attr == 'v': return self.v - return getattr(self.f, attr) - - def __len__(self): - return len(self.f) - - def __init__(self, tex, faces, mesh): - self.name = mesh.name - self.mesh = mesh - self.looseEdges = [] - self.faceUV = mesh.faceUV - self.degr = mesh.degr - vidxs = [0]*len(mesh.verts) - foofaces = [] - for f in faces: - foofaces.append(self.FooFace(self, f)) - for v in f.v: - if v: vidxs[v.index] = 1 - i = 0 - fooverts = [] - for v in mesh.verts: - if vidxs[v.index]: - fooverts.append(v) - vidxs[v.index] = i - i += 1 - for f in foofaces: - for v in f.v: - if v: v.index = vidxs[v.v.index] - self.faces = foofaces - self.verts = fooverts - - -class AC3DExport: # the ac3d exporter part - - def __init__(self, scene_objects, file): - - global ARG, SKIP_DATA, ADD_DEFAULT_MAT, DEFAULT_MAT - - header = 'AC3Db' - self.file = file - self.buf = '' - self.mbuf = [] - self.mlist = [] - world_kids = 0 - parents_list = self.parents_list = [] - kids_dict = self.kids_dict = {} - objs = [] - exp_objs = self.exp_objs = [] - tree = {} - - file.write(header+'\n') - - objs = \ - [o for o in scene_objects if o.type in ['Mesh', 'Empty']] - - # create a tree from parents to children objects - - for obj in objs[:]: - parent = obj.parent - lineage = [obj] - - while parent: - parents_list.append(parent.name) - obj = parent - parent = parent.getParent() - lineage.insert(0, obj) - - d = tree - for i in xrange(len(lineage)): - lname = lineage[i].getType()[:2] + lineage[i].name - if lname not in d.keys(): - d[lname] = {} - d = d[lname] - - # traverse the tree to get an ordered list of names of objects to export - self.traverse_dict(tree) - - world_kids = len(tree.keys()) - - # get list of objects to export, start writing the .ac file - - objlist = [Object.Get(name) for name in exp_objs] - - meshlist = [o for o in objlist if o.type == 'Mesh'] - - # create a temporary mesh to hold actual (modified) mesh data - TMP_mesh = Mesh.New('tmp_for_ac_export') - - # write materials - - self.MATERIALS(meshlist, TMP_mesh) - mbuf = self.mbuf - if not mbuf or ADD_DEFAULT_MAT: - mbuf.insert(0, "%s\n" % DEFAULT_MAT) - mbuf = "".join(mbuf) - file.write(mbuf) - - file.write('OBJECT world\nkids %s\n' % world_kids) - - # write the objects - - for obj in objlist: - self.obj = obj - - objtype = obj.type - objname = obj.name - kidsnum = kids_dict[objname] - - # A parent plus its children are exported as a group. - # If the parent is a mesh, its rot and loc are exported as the - # group rot and loc and the mesh (w/o rot and loc) is added to the group. - if kidsnum: - self.OBJECT('group') - self.name(objname) - if objtype == 'Mesh': - kidsnum += 1 - if not GLOBAL_COORDS: - localmatrix = obj.getMatrix('localspace') - if not obj.getParent(): - localmatrix *= BLEND_TO_AC3D_MATRIX - self.rot(localmatrix.rotationPart()) - self.loc(localmatrix.translationPart()) - self.kids(kidsnum) - - if objtype == 'Mesh': - mesh = TMP_mesh # temporary mesh to hold actual (modified) mesh data - mesh.getFromObject(objname) - self.mesh = mesh - if mesh.faceUV: - meshes = self.split_mesh(mesh) - else: - meshes = [mesh] - if len(meshes) > 1: - if NO_SPLIT or self.dont_split(objname): - self.export_mesh(mesh, ob) - REPORT_DATA['nosplit'].append(objname) - else: - self.OBJECT('group') - self.name(objname) - self.kids(len(meshes)) - counter = 0 - for me in meshes: - self.export_mesh(me, obj, - name = '%s_%s' % (obj.name, counter), foomesh = True) - self.kids() - counter += 1 - else: - self.export_mesh(mesh, obj) - self.kids() - - - def traverse_dict(self, d): - kids_dict = self.kids_dict - exp_objs = self.exp_objs - keys = d.keys() - keys.sort() # sort for predictable output - keys.reverse() - for k in keys: - objname = k[2:] - klen = len(d[k]) - kids_dict[objname] = klen - if self.dont_export(objname): - d.pop(k) - parent = Object.Get(objname).getParent() - if parent: kids_dict[parent.name] -= 1 - REPORT_DATA['noexport'].append(objname) - continue - if klen: - self.traverse_dict(d[k]) - exp_objs.insert(0, objname) - else: - if k.find('Em', 0) == 0: # Empty w/o children - d.pop(k) - parent = Object.Get(objname).getParent() - if parent: kids_dict[parent.name] -= 1 - else: - exp_objs.insert(0, objname) - - def dont_export(self, name): # if name starts with '!' or '#' - length = len(name) - if length >= 1: - if name[0] in TOKENS_DONT_EXPORT: # '!' or '#' doubled (escaped): export - if length > 1 and name[1] == name[0]: - return 0 - return 1 - - def dont_split(self, name): # if name starts with '=' or '$' - length = len(name) - if length >= 1: - if name[0] in TOKENS_DONT_SPLIT: # '=' or '$' doubled (escaped): split - if length > 1 and name[1] == name[0]: - return 0 - return 1 - - def split_mesh(self, mesh): - tex_dict = {0:[]} - for f in mesh.faces: - if f.image: - if not f.image.name in tex_dict: tex_dict[f.image.name] = [] - tex_dict[f.image.name].append(f) - else: tex_dict[0].append(f) - keys = tex_dict.keys() - len_keys = len(keys) - if not tex_dict[0]: - len_keys -= 1 - tex_dict.pop(0) - keys.remove(0) - elif len_keys > 1: - lines = [] - anyimgkey = [k for k in keys if k != 0][0] - for f in tex_dict[0]: - if len(f.v) < 3: - lines.append(f) - if len(tex_dict[0]) == len(lines): - for l in lines: - tex_dict[anyimgkey].append(l) - len_keys -= 1 - tex_dict.pop(0) - if len_keys > 1: - foo_meshes = [] - for k in keys: - faces = tex_dict[k] - foo_meshes.append(FooMesh(k, faces, mesh)) - foo_meshes[0].edges = get_loose_edges(mesh) - return foo_meshes - return [mesh] - - def export_mesh(self, mesh, obj, name = None, foomesh = False): - file = self.file - self.OBJECT('poly') - if not name: name = obj.name - self.name(name) - if not SKIP_DATA: - meshname = obj.getData(name_only = True) - self.data(len(meshname), meshname) - if mesh.faceUV: - texline = self.texture(mesh.faces) - if texline: file.write(texline) - if AC3D_4: - self.crease(mesh.degr) - - # If exporting using local coordinates, children object coordinates should not be - # transformed to ac3d's coordinate system, since that will be accounted for in - # their topmost parents (the parents w/o parents) transformations. - if not GLOBAL_COORDS: - # We hold parents in a list, so they also don't get transformed, - # because for each parent we create an ac3d group to hold both the - # parent and its children. - if obj.name not in self.parents_list: - localmatrix = obj.getMatrix('localspace') - if not obj.getParent(): - localmatrix *= BLEND_TO_AC3D_MATRIX - self.rot(localmatrix.rotationPart()) - self.loc(localmatrix.translationPart()) - matrix = None - else: - matrix = obj.getMatrix() * BLEND_TO_AC3D_MATRIX - - self.numvert(mesh.verts, matrix) - self.numsurf(mesh, foomesh) - - def MATERIALS(self, meshlist, me): - for meobj in meshlist: - me.getFromObject(meobj) - mats = me.materials - mbuf = [] - mlist = self.mlist - for m in mats: - if not m: continue - name = m.name - if name not in mlist: - mlist.append(name) - M = Material.Get(name) - material = 'MATERIAL "%s"' % name - mirCol = "%s %s %s" % (Round_s(M.mirCol[0]), Round_s(M.mirCol[1]), - Round_s(M.mirCol[2])) - rgb = "rgb %s %s %s" % (Round_s(M.R), Round_s(M.G), Round_s(M.B)) - ambval = Round_s(M.amb) - amb = "amb %s %s %s" % (ambval, ambval, ambval) - spec = "spec %s %s %s" % (Round_s(M.specCol[0]), - Round_s(M.specCol[1]), Round_s(M.specCol[2])) - if AC3D_4: - emit = Round_s(M.emit) - emis = "emis %s %s %s" % (emit, emit, emit) - shival = int(M.spec * 64) - else: - emis = "emis 0 0 0" - shival = 72 - shi = "shi %s" % shival - trans = "trans %s" % (Round_s(1 - M.alpha)) - if MIRCOL_AS_AMB: - amb = "amb %s" % mirCol - if MIRCOL_AS_EMIS: - emis = "emis %s" % mirCol - mbuf.append("%s %s %s %s %s %s %s\n" \ - % (material, rgb, amb, emis, spec, shi, trans)) - self.mlist = mlist - self.mbuf.append("".join(mbuf)) - - def OBJECT(self, type): - self.file.write('OBJECT %s\n' % type) - - def name(self, name): - if name[0] in TOKENS_DONT_EXPORT or name[0] in TOKENS_DONT_SPLIT: - if len(name) > 1: name = name[1:] - self.file.write('name "%s"\n' % name) - - def kids(self, num = 0): - self.file.write('kids %s\n' % num) - - def data(self, num, str): - self.file.write('data %s\n%s\n' % (num, str)) - - def texture(self, faces): - tex = "" - for f in faces: - if f.image: - tex = f.image.name - break - if tex: - image = Image.Get(tex) - texfname = image.filename - if SET_TEX_DIR: - texfname = bsys.basename(texfname) - if TEX_DIR: - texfname = bsys.join(TEX_DIR, texfname) - buf = 'texture "%s"\n' % texfname - xrep = image.xrep - yrep = image.yrep - buf += 'texrep %s %s\n' % (xrep, yrep) - self.file.write(buf) - - def rot(self, matrix): - rot = '' - not_I = 0 # not identity - matstr = [] - for i in [0, 1, 2]: - r = map(Round_s, matrix[i]) - not_I += (r[0] != '0')+(r[1] != '0')+(r[2] != '0') - not_I -= (r[i] == '1') - for j in [0, 1, 2]: - matstr.append(' %s' % r[j]) - if not_I: # no need to write identity - self.file.write('rot%s\n' % "".join(matstr)) - - def loc(self, loc): - loc = map(Round_s, loc) - if loc != ['0', '0', '0']: # no need to write default - self.file.write('loc %s %s %s\n' % (loc[0], loc[1], loc[2])) - - def crease(self, crease): - self.file.write('crease %f\n' % crease) - - def numvert(self, verts, matrix): - file = self.file - nvstr = [] - nvstr.append("numvert %s\n" % len(verts)) - - if matrix: - verts = transform_verts(verts, matrix) - for v in verts: - v = map (Round_s, v) - nvstr.append("%s %s %s\n" % (v[0], v[1], v[2])) - else: - for v in verts: - v = map(Round_s, v.co) - nvstr.append("%s %s %s\n" % (v[0], v[1], v[2])) - - file.write("".join(nvstr)) - - def numsurf(self, mesh, foomesh = False): - - global MATIDX_ERROR - - # local vars are faster and so better in tight loops - lc_ADD_DEFAULT_MAT = ADD_DEFAULT_MAT - lc_MATIDX_ERROR = MATIDX_ERROR - lc_PER_FACE_1_OR_2_SIDED = PER_FACE_1_OR_2_SIDED - lc_FACE_TWOSIDED = FACE_TWOSIDED - lc_MESH_TWOSIDED = MESH_TWOSIDED - - faces = mesh.faces - hasFaceUV = mesh.faceUV - if foomesh: - looseEdges = mesh.looseEdges - else: - looseEdges = get_loose_edges(mesh) - - file = self.file - - file.write("numsurf %s\n" % (len(faces) + len(looseEdges))) - - if not foomesh: verts = list(self.mesh.verts) - - materials = self.mesh.materials - mlist = self.mlist - matidx_error_reported = False - objmats = [] - for omat in materials: - if omat: objmats.append(omat.name) - else: objmats.append(None) - for f in faces: - if not objmats: - m_idx = 0 - elif objmats[f.mat] in mlist: - m_idx = mlist.index(objmats[f.mat]) - else: - if not lc_MATIDX_ERROR: - rdat = REPORT_DATA['warns'] - rdat.append("Object %s" % self.obj.name) - rdat.append("has at least one material *index* assigned but not") - rdat.append("defined (not linked to an existing material).") - rdat.append("Result: some faces may be exported with a wrong color.") - rdat.append("You can assign materials in the Edit Buttons window (F9).") - elif not matidx_error_reported: - midxmsg = "- Same for object %s." % self.obj.name - REPORT_DATA['warns'].append(midxmsg) - lc_MATIDX_ERROR += 1 - matidx_error_reported = True - m_idx = 0 - if lc_ADD_DEFAULT_MAT: m_idx -= 1 - refs = len(f) - flaglow = 0 # polygon - if lc_PER_FACE_1_OR_2_SIDED and hasFaceUV: # per face attribute - two_side = f.mode & lc_FACE_TWOSIDED - else: # global, for the whole mesh - two_side = self.mesh.mode & lc_MESH_TWOSIDED - two_side = (two_side > 0) << 1 - flaghigh = f.smooth | two_side - surfstr = "SURF 0x%d%d\n" % (flaghigh, flaglow) - if lc_ADD_DEFAULT_MAT and objmats: m_idx += 1 - matstr = "mat %s\n" % m_idx - refstr = "refs %s\n" % refs - u, v, vi = 0, 0, 0 - fvstr = [] - if foomesh: - for vert in f.v: - fvstr.append(str(vert.index)) - if hasFaceUV: - u = f.uv[vi][0] - v = f.uv[vi][1] - vi += 1 - fvstr.append(" %s %s\n" % (u, v)) - else: - for vert in f.v: - fvstr.append(str(verts.index(vert))) - if hasFaceUV: - u = f.uv[vi][0] - v = f.uv[vi][1] - vi += 1 - fvstr.append(" %s %s\n" % (u, v)) - - fvstr = "".join(fvstr) - - file.write("%s%s%s%s" % (surfstr, matstr, refstr, fvstr)) - - # material for loose edges - edges_mat = 0 # default to first material - for omat in objmats: # but look for a material from this mesh - if omat in mlist: - edges_mat = mlist.index(omat) - if lc_ADD_DEFAULT_MAT: edges_mat += 1 - break - - for e in looseEdges: - fvstr = [] - #flaglow = 2 # 1 = closed line, 2 = line - #flaghigh = 0 - #surfstr = "SURF 0x%d%d\n" % (flaghigh, flaglow) - surfstr = "SURF 0x02\n" - - fvstr.append("%d 0 0\n" % verts.index(e.v1)) - fvstr.append("%d 0 0\n" % verts.index(e.v2)) - fvstr = "".join(fvstr) - - matstr = "mat %d\n" % edges_mat # for now, use first material - refstr = "refs 2\n" # 2 verts - - file.write("%s%s%s%s" % (surfstr, matstr, refstr, fvstr)) - - MATIDX_ERROR = lc_MATIDX_ERROR - -# End of Class AC3DExport - -from Blender.Window import FileSelector - -def report_data(): - global VERBOSE - - if not VERBOSE: return - - d = REPORT_DATA - msgs = { - '0main': '%s\nExporting meshes to AC3D format' % str(19*'-'), - '1warns': 'Warnings', - '2errors': 'Errors', - '3nosplit': 'Not split (because name starts with "=" or "$")', - '4noexport': 'Not exported (because name starts with "!" or "#")' - } - if NO_SPLIT: - l = msgs['3nosplit'] - l = "%s (because OPTION NO_SPLIT is set)" % l.split('(')[0] - msgs['3nosplit'] = l - keys = msgs.keys() - keys.sort() - for k in keys: - msgk = msgs[k] - msg = '\n'.join(d[k[1:]]) - if msg: - print '\n-%s:' % msgk - print msg - -# File Selector callback: -def fs_callback(filename): - global EXPORT_DIR, OBJS, CONFIRM_OVERWRITE, VERBOSE - - if not filename.endswith('.ac'): filename = '%s.ac' % filename - - if bsys.exists(filename) and CONFIRM_OVERWRITE: - if Blender.Draw.PupMenu('OVERWRITE?%t|File exists') != 1: - return - - Blender.Window.WaitCursor(1) - starttime = bsys.time() - - export_dir = bsys.dirname(filename) - if export_dir != EXPORT_DIR: - EXPORT_DIR = export_dir - update_RegistryInfo() - - try: - file = open(filename, 'w') - except IOError, (errno, strerror): - error = "IOError #%s: %s" % (errno, strerror) - REPORT_DATA['errors'].append("Saving failed - %s." % error) - error_msg = "Couldn't save file!%%t|%s" % error - Blender.Draw.PupMenu(error_msg) - return - - try: - test = AC3DExport(OBJS, file) - except: - file.close() - raise - else: - file.close() - endtime = bsys.time() - starttime - REPORT_DATA['main'].append("Done. Saved to: %s" % filename) - REPORT_DATA['main'].append("Data exported in %.3f seconds." % endtime) - - if VERBOSE: report_data() - Blender.Window.WaitCursor(0) - - -# -- End of definitions - -scn = Blender.Scene.GetCurrent() - -if ONLY_SELECTED: - OBJS = list(scn.objects.context) -else: - OBJS = list(scn.objects) - -if not OBJS: - Blender.Draw.PupMenu('ERROR: no objects selected') -else: - fname = bsys.makename(ext=".ac") - if EXPORT_DIR: - fname = bsys.join(EXPORT_DIR, bsys.basename(fname)) - FileSelector(fs_callback, "Export AC3D", fname) diff --git a/release/scripts/ac3d_import.py b/release/scripts/ac3d_import.py deleted file mode 100644 index 2f5512e7150..00000000000 --- a/release/scripts/ac3d_import.py +++ /dev/null @@ -1,783 +0,0 @@ -#!BPY - -""" Registration info for Blender menus: -Name: 'AC3D (.ac)...' -Blender: 243 -Group: 'Import' -Tip: 'Import an AC3D (.ac) file.' -""" - -__author__ = "Willian P. Germano" -__url__ = ("blender", "blenderartists.org", "AC3D's homepage, http://www.ac3d.org", - "PLib 3d gaming lib, http://plib.sf.net") -__version__ = "2.48.1 2009-01-11" - -__bpydoc__ = """\ -This script imports AC3D models into Blender. - -AC3D is a simple and affordable commercial 3d modeller also built with OpenGL. -The .ac file format is an easy to parse text format well supported, -for example, by the PLib 3d gaming library. - -Supported:<br> - UV-textured meshes with hierarchy (grouping) information. - -Missing:<br> - The url tag is irrelevant for Blender. - -Known issues:<br> - - Some objects may be imported with wrong normals due to wrong information in the model itself. This can be noticed by strange shading, like darker than expected parts in the model. To fix this, select the mesh with wrong normals, enter edit mode and tell Blender to recalculate the normals, either to make them point outside (the usual case) or inside.<br> - -Config Options:<br> - - display transp (toggle): if "on", objects that have materials with alpha < 1.0 are shown with translucency (transparency) in the 3D View.<br> - - subdiv (toggle): if "on", ac3d objects meant to be subdivided receive a SUBSURF modifier in Blender.<br> - - emis as mircol: store the emissive rgb color from AC3D as mirror color in Blender -- this is a hack to preserve the values and be able to export them using the equivalent option in the exporter.<br> - - textures dir (string): if non blank, when imported texture paths are -wrong in the .ac file, Blender will also look for them at this dir. - -Notes:<br> - - When looking for assigned textures, Blender tries in order: the actual -paths from the .ac file, the .ac file's dir and the default textures dir path -users can configure (see config options above). -""" - -# $Id$ -# -# -------------------------------------------------------------------------- -# AC3DImport version 2.43.1 Feb 21, 2007 -# Program versions: Blender 2.43 and AC3Db files (means version 0xb) -# changed: better triangulation of ngons, more fixes to support bad .ac files, -# option to display transp mats in 3d view, support "subdiv" tag (via SUBSURF modifier) -# -------------------------------------------------------------------------- -# Thanks: Melchior Franz for extensive bug testing and reporting, making this -# version cope much better with old or bad .ac files, among other improvements; -# Stewart Andreason for reporting a serious crash; Francesco Brisa for the -# emis as mircol functionality (w/ patch). -# -------------------------------------------------------------------------- -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Copyright (C) 2004-2009: Willian P. Germano, wgermano _at_ ig.com.br -# -# 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 ***** -# -------------------------------------------------------------------------- - -from math import radians - -import Blender -from Blender import Scene, Object, Mesh, Lamp, Registry, sys as bsys, Window, Image, Material, Modifier -from Blender.sys import dirsep -from Blender.Mathutils import Vector, Matrix, Euler -from Blender.Geometry import PolyFill - -# Default folder for AC3D textures, to override wrong paths, change to your -# liking or leave as "": -TEXTURES_DIR = "" - -DISPLAY_TRANSP = True - -SUBDIV = True - -EMIS_AS_MIRCOL = False - - -tooltips = { - 'DISPLAY_TRANSP': 'Turn transparency on in the 3d View for objects using materials with alpha < 1.0.', - 'SUBDIV': 'Apply a SUBSURF modifier to objects meant to appear subdivided.', - 'TEXTURES_DIR': 'Additional folder to look for missing textures.', - 'EMIS_AS_MIRCOL': 'Store emis color as mirror color in Blender.' -} - -def update_registry(): - global TEXTURES_DIR, DISPLAY_TRANSP, EMIS_AS_MIRCOL - rd = dict([('tooltips', tooltips), ('TEXTURES_DIR', TEXTURES_DIR), ('DISPLAY_TRANSP', DISPLAY_TRANSP), ('SUBDIV', SUBDIV), ('EMIS_AS_MIRCOL', EMIS_AS_MIRCOL)]) - Registry.SetKey('ac3d_import', rd, True) - -rd = Registry.GetKey('ac3d_import', True) - -if rd: - if 'GROUP' in rd: - update_registry() - try: - TEXTURES_DIR = rd['TEXTURES_DIR'] - DISPLAY_TRANSP = rd['DISPLAY_TRANSP'] - SUBDIV = rd['SUBDIV'] - EMIS_AS_MIRCOL = rd['EMIS_AS_MIRCOL'] - except: - update_registry() -else: update_registry() - -if TEXTURES_DIR: - oldtexdir = TEXTURES_DIR - if dirsep == '/': TEXTURES_DIR = TEXTURES_DIR.replace('\\', '/') - if TEXTURES_DIR[-1] != dirsep: TEXTURES_DIR = "%s%s" % (TEXTURES_DIR, dirsep) - if oldtexdir != TEXTURES_DIR: update_registry() - - -VERBOSE = True -rd = Registry.GetKey('General', True) -if rd: - if rd.has_key('verbose'): - VERBOSE = rd['verbose'] - - -errmsg = "" - -# Matrix to align ac3d's coordinate system with Blender's one, -# it's a -90 degrees rotation around the x axis: -AC_TO_BLEND_MATRIX = Matrix([1, 0, 0], [0, 0, 1], [0, -1, 0]) - -AC_WORLD = 0 -AC_GROUP = 1 -AC_POLY = 2 -AC_LIGHT = 3 -AC_OB_TYPES = { - 'world': AC_WORLD, - 'group': AC_GROUP, - 'poly': AC_POLY, - 'light': AC_LIGHT - } - -AC_OB_BAD_TYPES_LIST = [] # to hold references to unknown (wrong) ob types - -def inform(msg): - global VERBOSE - if VERBOSE: print msg - -def euler_in_radians(eul): - "Used while there's a bug in the BPY API" - eul.x = radians(eul.x) - eul.y = radians(eul.y) - eul.z = radians(eul.z) - return eul - -class Obj: - - def __init__(self, type): - self.type = type - self.dad = None - self.name = '' - self.data = '' - self.tex = '' - self.texrep = [1,1] - self.texoff = None - self.loc = [] - self.rot = [] - self.size = [] - self.crease = 30 - self.subdiv = 0 - self.vlist = [] - self.flist_cfg = [] - self.flist_v = [] - self.flist_uv = [] - self.elist = [] - self.matlist = [] - self.kids = 0 - - self.bl_obj = None # the actual Blender object created from this data - -class AC3DImport: - - def __init__(self, filename): - - global errmsg - - self.scene = Scene.GetCurrent() - - self.i = 0 - errmsg = '' - self.importdir = bsys.dirname(filename) - try: - file = open(filename, 'r') - except IOError, (errno, strerror): - errmsg = "IOError #%s: %s" % (errno, strerror) - Blender.Draw.PupMenu('ERROR: %s' % errmsg) - inform(errmsg) - return None - header = file.read(5) - header, version = header[:4], header[-1] - if header != 'AC3D': - file.close() - errmsg = 'AC3D header not found (invalid file)' - Blender.Draw.PupMenu('ERROR: %s' % errmsg) - inform(errmsg) - return None - elif version != 'b': - inform('AC3D file version 0x%s.' % version) - inform('This importer is for version 0xb, so it may fail.') - - self.token = {'OBJECT': self.parse_obj, - 'numvert': self.parse_vert, - 'numsurf': self.parse_surf, - 'name': self.parse_name, - 'data': self.parse_data, - 'kids': self.parse_kids, - 'loc': self.parse_loc, - 'rot': self.parse_rot, - 'MATERIAL': self.parse_mat, - 'texture': self.parse_tex, - 'texrep': self.parse_texrep, - 'texoff': self.parse_texoff, - 'subdiv': self.parse_subdiv, - 'crease': self.parse_crease} - - self.objlist = [] - self.mlist = [] - self.kidsnumlist = [] - self.dad = None - - self.lines = file.readlines() - self.lines.append('') - self.parse_file() - file.close() - - self.testAC3DImport() - - def parse_obj(self, value): - kidsnumlist = self.kidsnumlist - if kidsnumlist: - while not kidsnumlist[-1]: - kidsnumlist.pop() - if kidsnumlist: - self.dad = self.dad.dad - else: - inform('Ignoring unexpected data at end of file.') - return -1 # bad file with more objects than reported - kidsnumlist[-1] -= 1 - if value in AC_OB_TYPES: - new = Obj(AC_OB_TYPES[value]) - else: - if value not in AC_OB_BAD_TYPES_LIST: - AC_OB_BAD_TYPES_LIST.append(value) - inform('Unexpected object type keyword: "%s". Assuming it is of type: "poly".' % value) - new = Obj(AC_OB_TYPES['poly']) - new.dad = self.dad - new.name = value - self.objlist.append(new) - - def parse_kids(self, value): - kids = int(value) - if kids: - self.kidsnumlist.append(kids) - self.dad = self.objlist[-1] - self.objlist[-1].kids = kids - - def parse_name(self, value): - name = value.split('"')[1] - self.objlist[-1].name = name - - def parse_data(self, value): - data = self.lines[self.i].strip() - self.objlist[-1].data = data - - def parse_tex(self, value): - line = self.lines[self.i - 1] # parse again to properly get paths with spaces - texture = line.split('"')[1] - self.objlist[-1].tex = texture - - def parse_texrep(self, trash): - trep = self.lines[self.i - 1] - trep = trep.split() - trep = [float(trep[1]), float(trep[2])] - self.objlist[-1].texrep = trep - self.objlist[-1].texoff = [0, 0] - - def parse_texoff(self, trash): - toff = self.lines[self.i - 1] - toff = toff.split() - toff = [float(toff[1]), float(toff[2])] - self.objlist[-1].texoff = toff - - def parse_mat(self, value): - i = self.i - 1 - lines = self.lines - line = lines[i].split() - mat_name = '' - mat_col = mat_amb = mat_emit = mat_spec_col = mat_mir_col = [0,0,0] - mat_alpha = 1 - mat_spec = 1.0 - - while line[0] == 'MATERIAL': - mat_name = line[1].split('"')[1] - mat_col = map(float,[line[3],line[4],line[5]]) - v = map(float,[line[7],line[8],line[9]]) - mat_amb = (v[0]+v[1]+v[2]) / 3.0 - v = map(float,[line[11],line[12],line[13]]) - mat_emit = (v[0]+v[1]+v[2]) / 3.0 - if EMIS_AS_MIRCOL: - mat_emit = 0 - mat_mir_col = map(float,[line[11],line[12],line[13]]) - - mat_spec_col = map(float,[line[15],line[16],line[17]]) - mat_spec = float(line[19]) / 64.0 - mat_alpha = float(line[-1]) - mat_alpha = 1 - mat_alpha - self.mlist.append([mat_name, mat_col, mat_amb, mat_emit, mat_spec_col, mat_spec, mat_mir_col, mat_alpha]) - i += 1 - line = lines[i].split() - - self.i = i - - def parse_rot(self, trash): - i = self.i - 1 - ob = self.objlist[-1] - rot = self.lines[i].split(' ', 1)[1] - rot = map(float, rot.split()) - matrix = Matrix(rot[:3], rot[3:6], rot[6:]) - ob.rot = matrix - size = matrix.scalePart() # vector - ob.size = size - - def parse_loc(self, trash): - i = self.i - 1 - loc = self.lines[i].split(' ', 1)[1] - loc = map(float, loc.split()) - self.objlist[-1].loc = Vector(loc) - - def parse_crease(self, value): - # AC3D: range is [0.0, 180.0]; Blender: [1, 80] - value = float(value) - self.objlist[-1].crease = int(value) - - def parse_subdiv(self, value): - self.objlist[-1].subdiv = int(value) - - def parse_vert(self, value): - i = self.i - lines = self.lines - obj = self.objlist[-1] - vlist = obj.vlist - n = int(value) - - while n: - line = lines[i].split() - line = map(float, line) - vlist.append(line) - n -= 1 - i += 1 - - if vlist: # prepend a vertex at 1st position to deal with vindex 0 issues - vlist.insert(0, line) - - self.i = i - - def parse_surf(self, value): - i = self.i - is_smooth = 0 - double_sided = 0 - lines = self.lines - obj = self.objlist[-1] - vlist = obj.vlist - matlist = obj.matlist - numsurf = int(value) - NUMSURF = numsurf - - badface_notpoly = badface_multirefs = 0 - - while numsurf: - flags = lines[i].split()[1][2:] - if len(flags) > 1: - flaghigh = int(flags[0]) - flaglow = int(flags[1]) - else: - flaghigh = 0 - flaglow = int(flags[0]) - - is_smooth = flaghigh & 1 - twoside = flaghigh & 2 - nextline = lines[i+1].split() - if nextline[0] != 'mat': # the "mat" line may be missing (found in one buggy .ac file) - matid = 0 - if not matid in matlist: matlist.append(matid) - i += 2 - else: - matid = int(nextline[1]) - if not matid in matlist: matlist.append(matid) - nextline = lines[i+2].split() - i += 3 - refs = int(nextline[1]) - face = [] - faces = [] - edges = [] - fuv = [] - fuvs = [] - rfs = refs - - while rfs: - line = lines[i].split() - v = int(line[0]) + 1 # + 1 to avoid vindex == 0 - uv = [float(line[1]), float(line[2])] - face.append(v) - fuv.append(Vector(uv)) - rfs -= 1 - i += 1 - - if flaglow: # it's a line or closed line, not a polygon - while len(face) >= 2: - cut = face[:2] - edges.append(cut) - face = face[1:] - - if flaglow == 1 and edges: # closed line - face = [edges[-1][-1], edges[0][0]] - edges.append(face) - - else: # polygon - - # check for bad face, that references same vertex more than once - lenface = len(face) - if lenface < 3: - # less than 3 vertices, not a face - badface_notpoly += 1 - elif sum(map(face.count, face)) != lenface: - # multiple references to the same vertex - badface_multirefs += 1 - else: # ok, seems fine - if len(face) > 4: # ngon, triangulate it - polyline = [] - for vi in face: - polyline.append(Vector(vlist[vi])) - tris = PolyFill([polyline]) - for t in tris: - tri = [face[t[0]], face[t[1]], face[t[2]]] - triuvs = [fuv[t[0]], fuv[t[1]], fuv[t[2]]] - faces.append(tri) - fuvs.append(triuvs) - else: # tri or quad - faces.append(face) - fuvs.append(fuv) - - obj.flist_cfg.extend([[matid, is_smooth, twoside]] * len(faces)) - obj.flist_v.extend(faces) - obj.flist_uv.extend(fuvs) - obj.elist.extend(edges) # loose edges - - numsurf -= 1 - - if badface_notpoly or badface_multirefs: - inform('Object "%s" - ignoring bad faces:' % obj.name) - if badface_notpoly: - inform('\t%d face(s) with less than 3 vertices.' % badface_notpoly) - if badface_multirefs: - inform('\t%d face(s) with multiple references to a same vertex.' % badface_multirefs) - - self.i = i - - def parse_file(self): - i = 1 - lines = self.lines - line = lines[i].split() - - while line: - kw = '' - for k in self.token.keys(): - if line[0] == k: - kw = k - break - i += 1 - if kw: - self.i = i - result = self.token[kw](line[1]) - if result: - break # bad .ac file, stop parsing - i = self.i - line = lines[i].split() - - # for each group of meshes we try to find one that can be used as - # parent of the group in Blender. - # If not found, we can use an Empty as parent. - def found_parent(self, groupname, olist): - l = [o for o in olist if o.type == AC_POLY \ - and not o.kids and not o.rot and not o.loc] - if l: - for o in l: - if o.name == groupname: - return o - #return l[0] - return None - - def build_hierarchy(self): - blmatrix = AC_TO_BLEND_MATRIX - - olist = self.objlist[1:] - olist.reverse() - - scene = self.scene - - newlist = [] - - for o in olist: - kids = o.kids - if kids: - children = newlist[-kids:] - newlist = newlist[:-kids] - if o.type == AC_GROUP: - parent = self.found_parent(o.name, children) - if parent: - children.remove(parent) - o.bl_obj = parent.bl_obj - else: # not found, use an empty - empty = scene.objects.new('Empty', o.name) - o.bl_obj = empty - - bl_children = [c.bl_obj for c in children if c.bl_obj != None] - - o.bl_obj.makeParent(bl_children, 0, 1) - for child in children: - blob = child.bl_obj - if not blob: continue - if child.rot: - eul = euler_in_radians(child.rot.toEuler()) - blob.setEuler(eul) - if child.size: - blob.size = child.size - if not child.loc: - child.loc = Vector(0.0, 0.0, 0.0) - blob.setLocation(child.loc) - - newlist.append(o) - - for o in newlist: # newlist now only has objs w/o parents - blob = o.bl_obj - if not blob: - continue - if o.size: - o.bl_obj.size = o.size - if not o.rot: - blob.setEuler([1.5707963267948966, 0, 0]) - else: - matrix = o.rot * blmatrix - eul = euler_in_radians(matrix.toEuler()) - blob.setEuler(eul) - if o.loc: - o.loc *= blmatrix - else: - o.loc = Vector(0.0, 0.0, 0.0) - blob.setLocation(o.loc) # forces DAG update, so we do it even for 0, 0, 0 - - # XXX important: until we fix the BPy API so it doesn't increase user count - # when wrapping a Blender object, this piece of code is needed for proper - # object (+ obdata) deletion in Blender: - for o in self.objlist: - if o.bl_obj: - o.bl_obj = None - - def testAC3DImport(self): - - FACE_TWOSIDE = Mesh.FaceModes['TWOSIDE'] - FACE_TEX = Mesh.FaceModes['TEX'] - MESH_AUTOSMOOTH = Mesh.Modes['AUTOSMOOTH'] - - MAT_MODE_ZTRANSP = Material.Modes['ZTRANSP'] - MAT_MODE_TRANSPSHADOW = Material.Modes['TRANSPSHADOW'] - - scene = self.scene - - bl_images = {} # loaded texture images - missing_textures = [] # textures we couldn't find - - objlist = self.objlist[1:] # skip 'world' - - bmat = [] - has_transp_mats = False - for mat in self.mlist: - name = mat[0] - m = Material.New(name) - m.rgbCol = (mat[1][0], mat[1][1], mat[1][2]) - m.amb = mat[2] - m.emit = mat[3] - m.specCol = (mat[4][0], mat[4][1], mat[4][2]) - m.spec = mat[5] - m.mirCol = (mat[6][0], mat[6][1], mat[6][2]) - m.alpha = mat[7] - if m.alpha < 1.0: - m.mode |= MAT_MODE_ZTRANSP - has_transp_mats = True - bmat.append(m) - - if has_transp_mats: - for mat in bmat: - mat.mode |= MAT_MODE_TRANSPSHADOW - - obj_idx = 0 # index of current obj in loop - for obj in objlist: - if obj.type == AC_GROUP: - continue - elif obj.type == AC_LIGHT: - light = Lamp.New('Lamp') - object = scene.objects.new(light, obj.name) - #object.select(True) - obj.bl_obj = object - if obj.data: - light.name = obj.data - continue - - # type AC_POLY: - - # old .ac files used empty meshes as groups, convert to a real ac group - if not obj.vlist and obj.kids: - obj.type = AC_GROUP - continue - - mesh = Mesh.New() - object = scene.objects.new(mesh, obj.name) - #object.select(True) - obj.bl_obj = object - if obj.data: mesh.name = obj.data - mesh.degr = obj.crease # will auto clamp to [1, 80] - - if not obj.vlist: # no vertices? nothing more to do - continue - - mesh.verts.extend(obj.vlist) - - objmat_indices = [] - for mat in bmat: - if bmat.index(mat) in obj.matlist: - objmat_indices.append(bmat.index(mat)) - mesh.materials += [mat] - if DISPLAY_TRANSP and mat.alpha < 1.0: - object.transp = True - - for e in obj.elist: - mesh.edges.extend(e) - - if obj.flist_v: - mesh.faces.extend(obj.flist_v) - - facesnum = len(mesh.faces) - - if facesnum == 0: # shouldn't happen, of course - continue - - mesh.faceUV = True - - # checking if the .ac file had duplicate faces (Blender ignores them) - if facesnum != len(obj.flist_v): - # it has, ugh. Let's clean the uv list: - lenfl = len(obj.flist_v) - flist = obj.flist_v - uvlist = obj.flist_uv - cfglist = obj.flist_cfg - for f in flist: - f.sort() - fi = lenfl - while fi > 0: # remove data related to duplicates - fi -= 1 - if flist[fi] in flist[:fi]: - uvlist.pop(fi) - cfglist.pop(fi) - - img = None - if obj.tex != '': - if obj.tex in bl_images.keys(): - img = bl_images[obj.tex] - elif obj.tex not in missing_textures: - texfname = None - objtex = obj.tex - baseimgname = bsys.basename(objtex) - if bsys.exists(objtex) == 1: - texfname = objtex - elif bsys.exists(bsys.join(self.importdir, objtex)): - texfname = bsys.join(self.importdir, objtex) - else: - if baseimgname.find('\\') > 0: - baseimgname = bsys.basename(objtex.replace('\\','/')) - objtex = bsys.join(self.importdir, baseimgname) - if bsys.exists(objtex) == 1: - texfname = objtex - else: - objtex = bsys.join(TEXTURES_DIR, baseimgname) - if bsys.exists(objtex): - texfname = objtex - if texfname: - try: - img = Image.Load(texfname) - # Commented because it's unnecessary: - #img.xrep = int(obj.texrep[0]) - #img.yrep = int(obj.texrep[1]) - if img: - bl_images[obj.tex] = img - except: - inform("Couldn't load texture: %s" % baseimgname) - else: - missing_textures.append(obj.tex) - inform("Couldn't find texture: %s" % baseimgname) - - for i in range(facesnum): - f = obj.flist_cfg[i] - fmat = f[0] - is_smooth = f[1] - twoside = f[2] - bface = mesh.faces[i] - bface.smooth = is_smooth - if twoside: bface.mode |= FACE_TWOSIDE - if img: - bface.mode |= FACE_TEX - bface.image = img - bface.mat = objmat_indices.index(fmat) - fuv = obj.flist_uv[i] - if obj.texoff: - uoff = obj.texoff[0] - voff = obj.texoff[1] - urep = obj.texrep[0] - vrep = obj.texrep[1] - for uv in fuv: - uv[0] *= urep - uv[1] *= vrep - uv[0] += uoff - uv[1] += voff - - mesh.faces[i].uv = fuv - - # finally, delete the 1st vertex we added to prevent vindices == 0 - mesh.verts.delete(0) - - mesh.calcNormals() - - mesh.mode = MESH_AUTOSMOOTH - - # subdiv: create SUBSURF modifier in Blender - if SUBDIV and obj.subdiv > 0: - subdiv = obj.subdiv - subdiv_render = subdiv - # just to be safe: - if subdiv_render > 6: subdiv_render = 6 - if subdiv > 3: subdiv = 3 - modif = object.modifiers.append(Modifier.Types.SUBSURF) - modif[Modifier.Settings.LEVELS] = subdiv - modif[Modifier.Settings.RENDLEVELS] = subdiv_render - - obj_idx += 1 - - self.build_hierarchy() - scene.update() - -# End of class AC3DImport - -def filesel_callback(filename): - - inform("\nTrying to import AC3D model(s) from:\n%s ..." % filename) - Window.WaitCursor(1) - starttime = bsys.time() - test = AC3DImport(filename) - Window.WaitCursor(0) - endtime = bsys.time() - starttime - inform('Done! Data imported in %.3f seconds.\n' % endtime) - -Window.EditMode(0) - -Window.FileSelector(filesel_callback, "Import AC3D", "*.ac") diff --git a/release/scripts/add_mesh_empty.py b/release/scripts/add_mesh_empty.py deleted file mode 100644 index 537bd1e2c3d..00000000000 --- a/release/scripts/add_mesh_empty.py +++ /dev/null @@ -1,13 +0,0 @@ -#!BPY -""" -Name: 'Empty mesh' -Blender: 243 -Group: 'AddMesh' -""" -import BPyAddMesh -import Blender - -def main(): - BPyAddMesh.add_mesh_simple('EmptyMesh', [], [], []) - -main()
\ No newline at end of file diff --git a/release/scripts/add_mesh_torus.py b/release/scripts/add_mesh_torus.py deleted file mode 100644 index 2941c56420e..00000000000 --- a/release/scripts/add_mesh_torus.py +++ /dev/null @@ -1,69 +0,0 @@ -#!BPY -""" -Name: 'Torus' -Blender: 243 -Group: 'AddMesh' -""" -import BPyAddMesh -import Blender -try: from math import cos, sin, pi -except: math = None - -def add_torus(PREF_MAJOR_RAD, PREF_MINOR_RAD, PREF_MAJOR_SEG, PREF_MINOR_SEG): - Vector = Blender.Mathutils.Vector - RotationMatrix = Blender.Mathutils.RotationMatrix - verts = [] - faces = [] - i1 = 0 - tot_verts = PREF_MAJOR_SEG * PREF_MINOR_SEG - for major_index in xrange(PREF_MAJOR_SEG): - verts_tmp = [] - mtx = RotationMatrix( 360 * float(major_index)/PREF_MAJOR_SEG, 3, 'z' ) - - for minor_index in xrange(PREF_MINOR_SEG): - angle = 2*pi*minor_index/PREF_MINOR_SEG - - verts.append( Vector(PREF_MAJOR_RAD+(cos(angle)*PREF_MINOR_RAD), 0, (sin(angle)*PREF_MINOR_RAD)) * mtx ) - if minor_index+1==PREF_MINOR_SEG: - i2 = (major_index)*PREF_MINOR_SEG - i3 = i1 + PREF_MINOR_SEG - i4 = i2 + PREF_MINOR_SEG - - else: - i2 = i1 + 1 - i3 = i1 + PREF_MINOR_SEG - i4 = i3 + 1 - - if i2>=tot_verts: i2 = i2-tot_verts - if i3>=tot_verts: i3 = i3-tot_verts - if i4>=tot_verts: i4 = i4-tot_verts - - faces.append( (i3,i4,i2,i1) ) - i1+=1 - - return verts, faces - -def main(): - Draw = Blender.Draw - PREF_MAJOR_RAD = Draw.Create(1.0) - PREF_MINOR_RAD = Draw.Create(0.25) - PREF_MAJOR_SEG = Draw.Create(48) - PREF_MINOR_SEG = Draw.Create(16) - - if not Draw.PupBlock('Add Torus', [\ - ('Major Radius:', PREF_MAJOR_RAD, 0.01, 100, 'Radius for the main ring of the torus'),\ - ('Minor Radius:', PREF_MINOR_RAD, 0.01, 100, 'Radius for the minor ring of the torus setting the thickness of the ring'),\ - ('Major Segments:', PREF_MAJOR_SEG, 3, 256, 'Number of segments for the main ring of the torus'),\ - ('Minor Segments:', PREF_MINOR_SEG, 3, 256, 'Number of segments for the minor ring of the torus'),\ - ]): - return - - verts, faces = add_torus(PREF_MAJOR_RAD.val, PREF_MINOR_RAD.val, PREF_MAJOR_SEG.val, PREF_MINOR_SEG.val) - - BPyAddMesh.add_mesh_simple('Torus', verts, [], faces) - -if cos and sin and pi: - main() -else: - Blender.Draw.PupMenu("Error%t|This script requires a full python installation") - diff --git a/release/scripts/animation_bake_constraints.py b/release/scripts/animation_bake_constraints.py deleted file mode 100644 index 16855828460..00000000000 --- a/release/scripts/animation_bake_constraints.py +++ /dev/null @@ -1,792 +0,0 @@ -#!BPY - -""" -Name: 'Bake Constraints' -Blender: 246 -Group: 'Animation' -Tooltip: 'Bake a Constrained object/rig to IPOs' -Fillename: 'Bake_Constraint.py' -""" - -__author__ = "Roger Wickes (rogerwickes(at)yahoo.com)" -__script__ = "Animation Bake Constraints" -__version__ = "0.7" -__url__ = ["Communicate problems and errors, http://www.blenderartists.com/forum/private.php?do=newpm to PapaSmurf"] -__email__= ["Roger Wickes, rogerwickes@yahoo.com", "scripts"] -__bpydoc__ = """\ - -bake_constraints - -This script bakes the real-world LocRot of an object (the net effect of any constraints - -(Copy, Limit, Track, Follow, - that affect Location, Rotation) -(usually one constrained to match another's location and/or Tracked to another) -and creates a clone with a set of Ipo Curves named Ipo<objname> -These curves control a non-constrained object and thus make it mimic the constrained object -Actions can be then be edited without the need for the drivers/constraining objects - -Developed for use with MoCap data, where a bone is constrained to point at an empty -moving through space and time. This records the actual locrot of the armature -so that the motion can be edited, reoriented, scaled, and used as NLA Actions - -see also wiki Scripts/Manual/ Tutorial/Motion Capture <br> - -Usage: <br> - - Select the reference Object(s) you want to bake <br> - - Set the frame range to bake in the Anim Panel <br> - - Set the test code (if you want a self-test) in the RT field in the Anim Panel <br> - -- Set RT:1 to create a test armature <br> - -- Set RT: up to 100 for more debug messages and status updates <br> -<br> - - Run the script <br> - - The clone copy of the object is created and it has an IPO curve assigned to it. <br> - - The clone shadows the object by an offset locrot (see usrDelta) <br> - - That Object has Ipo Location and Rotation curves that make the clone mimic the movement <br> - of the selected object, but without using constraints. <br> - - If the object was an Armature, the clone's bones move identically in relation to the <br> - original armature, and an Action is created that drives the bone movements. <br> - -Version History: - 0.1: bakes Loc Rot for a constrained object - 0.2: bakes Loc and Rot for the bones within Armature object - 0.3: UI for setting options - 0.3.1 add manual to script library - 0.4: bake multiple objects - 0.5: root bone worldspace rotation - 0.6: re-integration with BPyArmature - 0.7: bakes parents and leaves clones selected - -License, Copyright, and Attribution: - by Roger WICKES May 2008, released under Blender Artistic Licence to Public Domain - feel free to add to any Blender Python Scripts Bundle. - Thanks to Jean-Baptiste PERIN, IdeasMan42 (Campbell Barton), Basil_Fawlty/Cage_drei (Andrew Cruse) - much lifted/learned from blender.org/documentation/245PytonDoc and wiki - some modules based on c3D_Import.py, PoseLib16.py and IPO/Armature code examples e.g. camera jitter - -Pseudocode: - Initialize - If at least one object is selected - For each selected object, - create a cloned object - remove any constraints on the clone - create or reset an ipo curve named like the object - for each frame - set the clone's locrot key based on the reference object - if it's an armature, - create an action (which is an Ipo for each bone) - for each frame of the animation - for each bone in the armature - set the key - Else you're a smurf - -Test Conditions and Regressions: - 1. (v0.1) Non-armatures (the cube), with ipo curve and constraints at the object level - 2. armatures, with ipo curve and constraints at the object level - 3. armatures, with bones that have ipo curves and constraints - 4. objects without parents, children with unselected parents, select children first. - -Naming conventions: - arm = a specific objec type armature - bone = bones that make up the skeleton of an armature - - ob = object, an instance of an object type - ebone = edit bone, a bone in edit mode - pbone = pose bone, a posed bone in an object - tst = testing, self-test routines - usr = user-entered or designated stuff -""" -######################################## - -import Blender -from Blender import * -from Blender.Mathutils import * -import struct -import string -import bpy -import BPyMessages -import BPyArmature -# reload(BPyArmature) -from BPyArmature import getBakedPoseData - -Vector= Blender.Mathutils.Vector -Euler= Blender.Mathutils.Euler -Matrix= Blender.Mathutils.Matrix #invert() function at least -RotationMatrix = Blender.Mathutils.RotationMatrix -TranslationMatrix= Blender.Mathutils.TranslationMatrix -Quaternion = Blender.Mathutils.Quaternion -Vector = Blender.Mathutils.Vector -POSE_XFORM= [Blender.Object.Pose.LOC, Blender.Object.Pose.ROT] - -#================= -# Global Variables -#================= - -# set senstitivity for displaying debug/console messages. 0=none, 100=max -# then call debug(num,string) to conditionally display status/info in console window -MODE=Blender.Get('rt') #execution mode: 0=run normal, 1=make test armature -DEBUG=Blender.Get('rt') #how much detail on internal processing for user to see. range 0-100 -BATCH=False #called from command line? is someone there? Would you like some cake? - -#there are two coordinate systems, the real, or absolute 3D space, -# and the local relative to a parent. -COORDINATE_SYSTEMS = ['local','real'] -COORD_LOCAL = 0 -COORD_REAL = 1 - -# User Settings - Change these options manually or via GUI (future TODO) -usrCoord = COORD_REAL # what the user wants -usrParent = False # True=clone keeps original parent, False = clone's parent is the clone of the original parent (if cloned) -usrFreeze = 2 #2=yes, 0=no. Freezes shadow object in place at current frame as origin -# delta is amount to offset/change from the reference object. future set in a ui, so technically not a constant -usrDelta = [10,10,0,0,0,0] #order specific - Loc xyz Rot xyz -usrACTION = True # Offset baked Action frames to start at frame 1 - -CURFRAME = 'curframe' #keyword to use when getting the frame number that the scene is presently on -ARMATURE = 'Armature' #en anglais -BONE_SPACES = ['ARMATURESPACE','BONESPACE'] - # 'ARMATURESPACE' - this matrix of the bone in relation to the armature - # 'BONESPACE' - the matrix of the bone in relation to itself - -#Ipo curves created are prefixed with a name, like Ipo_ or Bake_ followed by the object/bone name -#bakedArmName = "b." #used for both the armature class and object instance -usrObjectNamePrefix= "" -#ipoBoneNamePrefix = "" -# for example, if on entry an armature named Man was selected, and the object prefix was "a." -# on exit an armature and an IPO curve named a.Man exists for the object as a whole -# if that armature had bones (spine, neck, arm) and the bone prefix was "a." -# the bones and IPO curves will be (a.spine, a.neck, a.arm) - -R2D = 18/3.141592653589793 # radian to grad -BLENDER_VERSION = Blender.Get('version') - -# Gets the current scene, there can be many scenes in 1 blend file. -scn = Blender.Scene.GetCurrent() - -#================= -# Methods -#================= -######################################## -def debug(num,msg): #use log4j or just console here. - if DEBUG >= num: - if BATCH == False: - print 'debug: '[:num/10+7]+msg - #TODO: else write out to file (runs faster if it doesnt have to display details) - return - -######################################## -def error(str): - debug(0,'ERROR: '+str) - if BATCH == False: - Draw.PupMenu('ERROR%t|'+str) - return - -######################################## -def getRenderInfo(): - context=scn.getRenderingContext() - staframe = context.startFrame() - endframe = context.endFrame() - if endframe<staframe: endframe=staframe - curframe = Blender.Get(CURFRAME) - debug(90,'Scene is on frame %i and frame range is %i to %i' % (curframe,staframe,endframe)) - return (staframe,endframe,curframe) - -######################################## -def sortObjects(obs): #returns a list of objects sorted based on parent dependency - obClones= [] - while len(obClones) < len(obs): - for ob in obs: - if not ob in obClones: - par= ob.getParent() - #if no parent, or the parent is not scheduled to be cloned - if par==None: - obClones.append(ob) # add the independent - elif par not in obs: # parent will not be cloned - obClones.append(ob) # add the child - elif par in obClones: # is it on the list? - obClones.append(ob) # add the child - # parent may be a child, so it will be caught next time thru - debug(100,'clone object order: \n%s' % obClones) - return obClones # ordered list of (ob, par) tuples - -######################################## -def sortBones(xbones): #returns a sorted list of bones that should be added,sorted based on parent dependency -# while there are bones to add, -# look thru the list of bones we need to add -# if we have not already added this bone -# if it does not have a parent -# add it -# else, it has a parent -# if we already added it's parent -# add it now. -# else #we need to keep cycling and catch its parent -# else it is a root bone -# add it -# else skip it, it's already in there -# endfor -# endwhile - xboneNames=[] - for xbone in xbones: xboneNames.append(xbone.name) - debug (80,'reference bone order: \n%s' % xboneNames) - eboneNames=[] - while len(eboneNames) < len(xboneNames): - for xbone in xbones: - if not xbone.name in eboneNames: - if not xbone.parent: - eboneNames.append(xbone.name) - else: - if xbone.parent.name in eboneNames: - eboneNames.append(xbone.name) - #else skip it - #endif - #else prego - #endfor - #endwhile - debug (80,'clone bone order: \n%s' % eboneNames) - return eboneNames - -######################################## -def dupliArmature(ob): #makes a copy in current scn of the armature used by ob and its bones - ob_mat = ob.matrixWorld - ob_data = ob.getData() - debug(49,'Reference object uses %s' % ob_data) - arm_ob = Armature.Get(ob_data.name) #the armature used by the passed object - - arm = Blender.Armature.New() - debug(20,'Cloning Armature %s to create %s' % (arm_ob.name, arm.name)) - arm.drawType = Armature.STICK #set the draw type - - arm.makeEditable() #enter editmode - - # for each bone in the object's armature, - xbones=ob.data.bones.values() - usrSpace = 0 #0=armature, 1=local - space=[BONE_SPACES[usrSpace]][0] - - #we have to make a list of bones, then figure out our parents, then add to the arm - #when creating a child, we cannot link to a parent if it does not yet exist in our armature - ebones = [] #list of the bones I want to create for my arm - - eboneNames = sortBones(xbones) - - i=0 - # error('bones sorted. continue?') - for abone in eboneNames: #set all editable attributes to fully define the bone. - for bone in xbones: - if bone.name == abone: break # get the reference bone - ebone = Armature.Editbone() #throw me a bone, bone-man! - ebones.append(ebone) #you're on my list, buddy - - ebone.name = bone.name - ebone.headRadius = bone.headRadius - ebone.tailRadius = bone.tailRadius - ebone.weight = bone.weight - ebone.options = bone.options - - ebone.head = bone.head[space] #dictionary lookups - ebone.tail = bone.tail[space] - ebone.matrix = bone.matrix[space] - ebone.roll = bone.roll[space] - - debug(30,'Generating new %s as child of %s' % (bone,bone.parent)) - if bone.hasParent(): -# parent=bone.parent.name -# debug(100,'looking for %s' % parent) -# for parbone in xbones: if parbone.name == parent: break # get the parent bone -# ebone.parent = arm.bones[ebones[j].name] - ebone.parent = arm.bones[bone.parent.name] -# else: -# ebone.parent = None - debug(30,'Generating new editbone %s as child of %s' % (ebone,ebone.parent)) - arm.bones[ebone.name] = ebone # i would have expected an append or add function, but this works - - debug (100,'arm.bones: \n%s' % arm.bones) - debug (20,'Cloned %i bones now in armature %s' %(len(arm.bones),arm.name)) - - myob = scn.objects.new(arm) #interestingly, object must be created before - arm.update() #armature can be saved - debug(40,'dupArm finished %s instanced as object %s' % (arm.name,myob.getName())) - print ob.matrix - print myob.matrix - - return myob -######################################## -def scrub(): # scrubs to startframe - staFrame,endFrame,curFrame = getRenderInfo() - - # eye-candy, go from current to start, fwd or back - if not BATCH: - debug(100, "Positioning to start...") - frameinc=(staFrame-curFrame)/10 - if abs(frameinc) >= 1: - for i in range(10): - curFrame+=frameinc - Blender.Set(CURFRAME,curFrame) # computes the constrained location of the 'real' objects - Blender.Redraw() - Blender.Set(CURFRAME, staFrame) - return - -######################################## -def bakeBones(ref_ob,arm_ob): #copy pose from ref_ob to arm_ob - scrub() - staFrame,endFrame,curFrame = getRenderInfo() - act = getBakedPoseData(ref_ob, staFrame, endFrame, ACTION_BAKE = True, ACTION_BAKE_FIRST_FRAME = usrACTION) # bake the pose positions of the reference ob to the armature ob - arm_ob.action = act - scrub() - - # user comprehension feature - change action name and channel ipo names to match the names of the bone they drive - debug (80,'Renaming each action ipo to match the bone they pose') - act.name = arm_ob.name - arm_channels = act.getAllChannelIpos() - pose= arm_ob.getPose() - pbones= pose.bones.values() #we want the bones themselves, not the dictionary lookup - for pbone in pbones: - debug (100,'Channel listing for %s: %s' % (pbone.name,arm_channels[pbone.name] )) - ipo=arm_channels[pbone.name] - ipo.name = pbone.name # since bone names are unique within an armature, the pose names can be the same since they are within an Action - - return - -######################################## -def getOrCreateCurve(ipo, curvename): - """ - Retrieve or create a Blender Ipo Curve named C{curvename} in the C{ipo} Ipo - Either an ipo curve named C{curvename} exists before the call then this curve is returned, - Or such a curve doesn't exist before the call .. then it is created into the c{ipo} Ipo and returned - """ - try: - mycurve = ipo.getCurve(curvename) - if mycurve != None: - pass - else: - mycurve = ipo.addCurve(curvename) - except: - mycurve = ipo.addCurve(curvename) - return mycurve - -######################################## -def eraseCurve(ipo,numCurves): - debug(90,'Erasing %i curves for %' % (numCurves,ipo.GetName())) - for i in range(numCurves): - nbBezPoints= ipo.getNBezPoints(i) - for j in range(nbBezPoints): - ipo.delBezPoint(i) - return - -######################################## -def resetIPO(ipo): - debug(60,'Resetting ipo curve named %s' %ipo.name) - numCurves = ipo.getNcurves() #like LocX, LocY, etc - if numCurves > 0: - eraseCurve(ipo, numCurves) #erase data if one exists - return - -######################################## -def resetIPOs(ob): #resets all IPO curvess assocated with an object and its bones - debug(30,'Resetting any ipo curves linked to %s' %ob.getName()) - ipo = ob.getIpo() #may be None - ipoName = ipo.getName() #name of the IPO that guides/controls this object - debug(70,'Object IPO is %s' %ipoName) - try: - ipo = Ipo.Get(ipoName) - except: - ipo = Ipo.New('Object', ipoName) - resetIPO(ipo) - if ob.getType() == ARMATURE: - arm_data=ob.getData() - bones=arm_data.bones.values() - for bone in bones: - #for each bone: get the name and check for a Pose IPO - debug(10,'Processing '+ bone.name) - return - -######################################## -def parse(string,delim): - index = string.find(delim) # -1 if not found, else pointer to delim - if index+1: return string[:index] - return string - -######################################## -def newIpo(ipoName): #add a new Ipo object to the Blender scene - ipo=Blender.Ipo.New('Object',ipoName) - - ipo.addCurve('LocX') - ipo.addCurve('LocY') - ipo.addCurve('LocZ') - ipo.addCurve('RotX') - ipo.addCurve('RotY') - ipo.addCurve('RotZ') - return ipo - -######################################## -def makeUpaName(type,name): #i know this exists in Blender somewhere... - debug(90,'Making up a new %s name using %s as a basis.' % (type,name)) - name = (parse(name,'.')) - if type == 'Ipo': - ipoName = name # maybe we get lucky today - ext = 0 - extlen = 3 # 3 digit extensions, like hello.002 - success = False - while not(success): - try: - debug(100,'Trying %s' % ipoName) - ipo = Ipo.Get(ipoName) - #that one exists if we get here. add on extension and keep trying - ext +=1 - if ext>=10**extlen: extlen +=1 # go to more digits if 999 not found - ipoName = '%s.%s' % (name, str(ext).zfill(extlen)) - except: # could not find it - success = True - name=ipoName - else: - debug (0,'FATAL ERROR: I dont know how to make up a new %s name based on %s' % (type,ob)) - return None - return name - -######################################## -def createIpo(ob): #create an Ipo and curves and link them to this object - #first, we have to create a unique name - #try first with just the name of the object to keep things simple. - ipoName = makeUpaName('Ipo',ob.getName()) # make up a name for a new Ipo based on the object name - debug(20,'Ipo and LocRot curves called %s' % ipoName) - ipo=newIpo(ipoName) - ob.setIpo(ipo) #link them - return ipo - -######################################## -def getLocLocal(ob): - key = [ - ob.LocX, - ob.LocY, - ob.LocZ, - ob.RotX*R2D, #get the curves in this order - ob.RotY*R2D, - ob.RotZ*R2D - ] - return key - -######################################## -def getLocReal(ob): - obMatrix = ob.matrixWorld #Thank you IdeasMan42 - loc = obMatrix.translationPart() - rot = obMatrix.toEuler() - key = [ - loc.x, - loc.y, - loc.z, - rot.x/10, - rot.y/10, - rot.z/10 - ] - return key - -######################################## -def getLocRot(ob,space): - if space in xrange(len(COORDINATE_SYSTEMS)): - if space == COORD_LOCAL: - key = getLocLocal(ob) - return key - elif space == COORD_REAL: - key = getLocReal(ob) - return key - else: #hey, programmers make mistakes too. - debug(0,'Fatal Error: getLoc called with %i' % space) - return - -######################################## -def getCurves(ipo): - ipos = [ - ipo[Ipo.OB_LOCX], - ipo[Ipo.OB_LOCY], - ipo[Ipo.OB_LOCZ], - ipo[Ipo.OB_ROTX], #get the curves in this order - ipo[Ipo.OB_ROTY], - ipo[Ipo.OB_ROTZ] - ] - return ipos - -######################################## -def addPoint(time,keyLocRot,ipos): - if BLENDER_VERSION < 245: - debug(0,'WARNING: addPoint uses BezTriple') - for i in range(len(ipos)): - point = BezTriple.New() #this was new with Blender 2.45 API - point.pt = (time, keyLocRot[i]) - point.handleTypes = [1,1] - - ipos[i].append(point) - return ipos - -######################################## -def bakeFrames(ob,myipo): #bakes an object in a scene, returning the IPO containing the curves - myipoName = myipo.getName() - debug(20,'Baking frames for scene %s object %s to ipo %s' % (scn.getName(),ob.getName(),myipoName)) - ipos = getCurves(myipo) - #TODO: Gui setup idea: myOffset - # reset action to start at frame 1 or at location - myOffset=0 #=1-staframe - #loop through frames in the animation. Often, there is rollup and the mocap starts late - staframe,endframe,curframe = getRenderInfo() - for frame in range(staframe, endframe+1): - debug(80,'Baking Frame %i' % frame) - #tell Blender to advace to frame - Blender.Set(CURFRAME,frame) # computes the constrained location of the 'real' objects - if not BATCH: Blender.Redraw() # no secrets, let user see what we are doing - - #using the constrained Loc Rot of the object, set the location of the unconstrained clone. Yea! Clones are FreeMen - key = getLocRot(ob,usrCoord) #a key is a set of specifed exact channel values (LocRotScale) for a certain frame - key = [a+b for a,b in zip(key, usrDelta)] #offset to the new location - - myframe= frame+myOffset - Blender.Set(CURFRAME,myframe) - - time = Blender.Get('curtime') #for BezTriple - ipos = addPoint(time,key,ipos) #add this data at this time to the ipos - debug(100,'%s %i %.3f %.2f %.2f %.2f %.2f %.2f %.2f' % (myipoName, myframe, time, key[0], key[1], key[2], key[3], key[4], key[5])) - # eye-candy - smoothly rewind the animation, showing now how the clone match moves - if endframe-staframe <400 and not BATCH: - for frame in range (endframe,staframe,-1): #rewind - Blender.Set(CURFRAME,frame) # computes the constrained location of the 'real' objects - Blender.Redraw() - Blender.Set(CURFRAME,staframe) - Blender.Redraw() - - return ipos - -######################################## -def duplicateLinked(ob): - obType = ob.type - debug(10,'Duplicating %s Object named %s' % (obType,ob.getName())) - scn.objects.selected = [ob] -## rdw: simplified by just duplicating armature. kept code as reference for creating armatures -## disadvantage is that you cant have clone as stick and original as octahedron -## since they share the same Armature. User can click Make Single User button. -## if obType == ARMATURE: #build a copy from scratch -## myob= dupliArmature(ob) -## else: - Blender.Object.Duplicate() # Duplicate linked, including pose constraints. - myobs = Object.GetSelected() #duplicate is top on the list - myob = myobs[0] - if usrParent == False: - myob.clrParent(usrFreeze) - debug(20,'=myob= was created as %s' % myob.getName()) - return myob - -######################################## -def removeConstraints(ob): - for const in ob.constraints: - debug(90,'removed %s => %s' % (ob.name, const)) - ob.constraints.remove(const) - return - -######################################## -def removeConstraintsOb(ob): # from object or armature - debug(40,'Removing constraints from '+ob.getName()) - if BLENDER_VERSION > 241: #constraints module not available before 242 - removeConstraints(ob) - if ob.getType() == ARMATURE: - pose = ob.getPose() - for pbone in pose.bones.values(): - #bone = pose.bones[bonename] - removeConstraints(pbone) - #should also check if it is a deflector? - return - -######################################## -def deLinkOb(type,ob): #remove linkages - if type == 'Ipo': - success = ob.clearIpo() #true=there was one - if success: debug(80,'deLinked Ipo curve to %s' % ob.getName()) - return - -######################################## -def bakeObject(ob): #bakes the core object locrot and assigns the Ipo to a Clone - if ob != None: - # Clone the object - duplicate it, clean the clone, and create an ipo curve for the clone - myob = duplicateLinked(ob) #clone it - myob.setName(usrObjectNamePrefix + ob.getName()) - removeConstraintsOb(myob) #my object is a free man - deLinkOb('Ipo',myob) #kids, it's not nice to share. you've been lied to - if ob.getType() != ARMATURE: # baking armatures is based on bones, not object - myipo = createIpo(myob) #create own IPO and curves for the clone object - ipos = bakeFrames(ob,myipo) #bake the locrot for this obj for the scene frames - return myob - -######################################## -def bake(ob,par): #bakes an object of any type, linking it to parent - debug(0,'Baking %s object %s' % (ob.getType(), ob)) - clone = bakeObject(ob) #creates and bakes the object motion - if par!= None: - par.makeParent([clone]) - debug(20,"assigned object to parent %s" % par) - if ob.getType() == ARMATURE: -## error('Object baked. Continue with bones?') - bakeBones(ob,clone) #go into the bones and copy from -> to in frame range - #future idea: bakeMesh (net result of Shapekeys, Softbody, Cloth, Fluidsim,...) - return clone - -######################################## -def tstCreateArm(): #create a test armature in scene - # rip-off from http://www.blender.org/documentation/245PythonDoc/Pose-module.html - thank you! - - debug(0,'Making Test Armature') - # New Armature - arm_data= Armature.New('myArmature') - print arm_data - arm_ob = scn.objects.new(arm_data) - arm_data.makeEditable() - - # Add 4 bones - ebones = [Armature.Editbone(), Armature.Editbone(), Armature.Editbone(), Armature.Editbone()] - - # Name the editbones - ebones[0].name = 'Bone.001' - ebones[1].name = 'Bone.002' - ebones[2].name = 'Bone.003' - ebones[3].name = 'Bone.004' - - # Assign the editbones to the armature - for eb in ebones: - arm_data.bones[eb.name]= eb - - # Set the locations of the bones - ebones[0].head= Mathutils.Vector(0,0,0) - ebones[0].tail= Mathutils.Vector(0,0,1) #tip - ebones[1].head= Mathutils.Vector(0,0,1) - ebones[1].tail= Mathutils.Vector(0,0,2) - ebones[2].head= Mathutils.Vector(0,0,2) - ebones[2].tail= Mathutils.Vector(0,0,3) - ebones[3].head= Mathutils.Vector(0,0,3) - ebones[3].tail= Mathutils.Vector(0,0,4) - - ebones[1].parent= ebones[0] - ebones[2].parent= ebones[1] - ebones[3].parent= ebones[2] - - arm_data.update() - # Done with editing the armature - - # Assign the pose animation - arm_pose = arm_ob.getPose() - - act = arm_ob.getAction() - if not act: # Add a pose action if we dont have one - act = Armature.NLA.NewAction() - act.setActive(arm_ob) - - xbones=arm_ob.data.bones.values() - pbones = arm_pose.bones.values() - - frame = 1 - for pbone in pbones: # set bones to no rotation - pbone.quat[:] = 1.000,0.000,0.000,0.0000 - pbone.insertKey(arm_ob, frame, Object.Pose.ROT) - - # Set a different rotation at frame 25 - pbones[0].quat[:] = 1.000,0.1000,0.2000,0.20000 - pbones[1].quat[:] = 1.000,0.6000,0.5000,0.40000 - pbones[2].quat[:] = 1.000,0.1000,0.3000,0.40000 - pbones[3].quat[:] = 1.000,-0.2000,-0.3000,0.30000 - - frame = 25 - for i in xrange(4): - pbones[i].insertKey(arm_ob, frame, Object.Pose.ROT) - - pbones[0].quat[:] = 1.000,0.000,0.000,0.0000 - pbones[1].quat[:] = 1.000,0.000,0.000,0.0000 - pbones[2].quat[:] = 1.000,0.000,0.000,0.0000 - pbones[3].quat[:] = 1.000,0.000,0.000,0.0000 - - frame = 50 - for pbone in pbones: # set bones to no rotation - pbone.quat[:] = 1.000,0.000,0.000,0.0000 - pbone.insertKey(arm_ob, frame, Object.Pose.ROT) - - return arm_ob - -######################################## -def tstMoveOb(ob): # makes a simple LocRot animation of object in the scene - anim = [ - #Loc Rot/10 - # - ( 0,0,0, 0, 0, 0), #frame 1 origin - ( 1,0,0, 0, 0, 0), #frame 2 - ( 1,1,0, 0, 0, 0), - ( 1,1,1, 0, 0, 0), - ( 1,1,1,4.5, 0, 0), - ( 1,1,1,4.5,4.5, 0), - ( 1,1,1,4.5,4.5,4.5) - ] - space = COORD_LOCAL - ipo = createIpo(ob) #create an Ipo and curves for this object - ipos = getCurves(ipo) - - # span this motion over the currently set anim range - # to set points, i need time but do not know how it is computed, so will have to advance the animation - staframe,endframe,curframe = getRenderInfo() - - frame = staframe #x position of new ipo datapoint. set to staframe if you want a match - frameDelta=(endframe-staframe)/(len(anim)) #accomplish the animation in frame range - for key in anim: #effectively does a getLocRot() - #tell Blender to advace to frame - Blender.Set('curframe',frame) # computes the constrained location of the 'real' objects - time = Blender.Get('curtime') - - ipos = addPoint(time,key,ipos) #add this data at this time to the ipos - - debug(100,'%s %i %.3f %.2f %.2f %.2f %.2f %.2f %.2f' % (ipo.name, frame, time, key[0], key[1], key[2], key[3], key[4], key[5])) - frame += frameDelta - Blender.Set(CURFRAME,curframe) # reset back to where we started - return -#================= -# Program Template -#================= -######################################## -def main(): - # return code set via rt button in Blender Buttons Scene Context Anim panel - if MODE == 1: #create test armature #1 - ob = tstCreateArm() # make test arm and select it - tstMoveOb(ob) - scn.objects.selected = [ob] - - obs= Blender.Object.GetSelected() #scn.objects.selected - obs= sortObjects(obs) - debug(0,'Baking %i objects' % len(obs)) - - if len(obs) >= 1: # user might have multiple objects selected - i= 0 - clones=[] # my clone army - for ob in obs: - par= ob.getParent() - if not usrParent: - if par in obs: - par= clones[obs.index(par)] - clones.append(bake(ob,par)) - scn.objects.selected = clones - else: - error('Please select at least one object') - return - -######################################## -def benchmark(): # This lets you benchmark (time) the script's running duration - Window.WaitCursor(1) - t = sys.time() - debug(60,'%s began at %.0f' %(__script__,sys.time())) - - # Run the function on the active scene - in_editmode = Window.EditMode() - if in_editmode: Window.EditMode(0) - - main() - - if in_editmode: Window.EditMode(1) - - # Timing the script is a good way to be aware on any speed hits when scripting - debug(0,'%s Script finished in %.2f seconds' % (__script__,sys.time()-t) ) - Window.WaitCursor(0) - return - -######################################## -# This lets you can import the script without running it -if __name__ == '__main__': - debug(0, "------------------------------------") - debug(0, "%s %s Script begins with mode=%i debug=%i batch=%s" % (__script__,__version__,MODE,DEBUG,BATCH)) - benchmark() diff --git a/release/scripts/animation_clean.py b/release/scripts/animation_clean.py deleted file mode 100644 index fc44f264ac1..00000000000 --- a/release/scripts/animation_clean.py +++ /dev/null @@ -1,192 +0,0 @@ -#!BPY - -""" -Name: 'Clean Animation Curves' -Blender: 249 -Group: 'Animation' -Tooltip: 'Remove unused keyframes for ipo curves' -""" - -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Copyright (C) 2008-2009: Blender Foundation -# -# 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, -# -------------------------------------------------------------------------- - -import bpy -from Blender import IpoCurve, Draw, Window - -def clean_ipos(ipos): - eul = 0.001 - - def isflat(vec): - prev_y = vec[0][1] - mid_y = vec[1][1] - next_y = vec[2][1] - - # flat status for prev and next - return abs(mid_y-prev_y) < eul, abs(mid_y-next_y) < eul - - - - X=0 - Y=1 - PREV=0 - MID=1 - NEXT=2 - - LEFT = 0 - RIGHT = 1 - - TOT = 0 - TOTBEZ = 0 - # for ipo in bpy.data.ipos: - for ipo in ipos: - if ipo.lib: - continue - # print ipo - for icu in ipo: - interp = icu.interpolation - extend = icu.extend - - bezierPoints = icu.bezierPoints - bezierVecs = [bez.vec for bez in bezierPoints] - - l = len(bezierPoints) - - TOTBEZ += l - - # our aim is to simplify this ipo as much as possible! - if interp == IpoCurve.InterpTypes.BEZIER or interp == interp == IpoCurve.InterpTypes.LINEAR: - #print "Not yet supported" - - if interp == IpoCurve.InterpTypes.BEZIER: - flats = [isflat(bez) for bez in bezierVecs] - else: - # A bit of a waste but fake the locations for these so they will always be flats - # IS better then too much duplicate code. - flats = [(True, True)] * l - for v in bezierVecs: - v[PREV][Y] = v[NEXT][Y] = v[MID][Y] - - - # remove middle points - if l>2: - done_nothing = False - - while not done_nothing and len(bezierVecs) > 2: - done_nothing = True - i = l-2 - - while i > 0: - #print i - #print i, len(bezierVecs) - if flats[i]==(True,True) and flats[i-1][RIGHT] and flats[i+1][LEFT]: - - if abs(bezierVecs[i][MID][Y] - bezierVecs[i-1][MID][Y]) < eul and abs(bezierVecs[i][MID][Y] - bezierVecs[i+1][MID][Y]) < eul: - done_nothing = False - - del flats[i] - del bezierVecs[i] - icu.delBezier(i) - TOT += 1 - l-=1 - i-=1 - - # remove endpoints - if extend == IpoCurve.ExtendTypes.CONST and len(bezierVecs) > 1: - #print l, len(bezierVecs) - # start - - while l > 2 and (flats[0][RIGHT] and flats[1][LEFT] and (abs(bezierVecs[0][MID][Y] - bezierVecs[1][MID][Y]) < eul)): - print "\tremoving 1 point from start of the curve" - del flats[0] - del bezierVecs[0] - icu.delBezier(0) - TOT += 1 - l-=1 - - - # End - while l > 2 and flats[-2][RIGHT] and flats[-1][LEFT] and (abs(bezierVecs[-2][MID][Y] - bezierVecs[-1][MID][Y]) < eul): - print "\tremoving 1 point from end of the curve", l - del flats[l-1] - del bezierVecs[l-1] - icu.delBezier(l-1) - TOT += 1 - l-=1 - - - - if l==2: - if isflat( bezierVecs[0] )[RIGHT] and isflat( bezierVecs[1] )[LEFT] and abs(bezierVecs[0][MID][Y] - bezierVecs[1][MID][Y]) < eul: - # remove the second point - print "\tremoving 1 point from 2 point bez curve" - # remove the second point - del flats[1] - del bezierVecs[1] - icu.delBezier(1) - TOT+=1 - l-=1 - - # Change to linear for faster evaluation - ''' - if l==1: - print 'Linear' - icu.interpolation = IpoCurve.InterpTypes.LINEAR - ''' - - - - - if interp== IpoCurve.InterpTypes.CONST: - print "Not yet supported" - - print 'total', TOT, TOTBEZ - return TOT, TOTBEZ - -def main(): - ret = Draw.PupMenu('Clean Selected Objects Ipos%t|Object IPO%x1|Object Action%x2|%l|All IPOs (be careful!)%x3') - - sce = bpy.data.scenes.active - ipos = [] - - if ret == 3: - ipos.extend(list(bpy.data.ipos)) - else: - for ob in sce.objects.context: - if ret == 1: - ipo = ob.ipo - if ipo: - ipos.append(ipo) - - elif ret == 2: - action = ob.action - if action: - ipos.extend([ipo for ipo in action.getAllChannelIpos().values() if ipo]) - - - - if not ipos: - Draw.PupMenu('Error%t|No ipos found') - else: - total_removed, total = clean_ipos(ipos) - Draw.PupMenu('Done!%t|Removed ' + str(total_removed) + ' of ' + str(total) + ' points') - - Window.RedrawAll() - - -if __name__ == '__main__': - main() diff --git a/release/scripts/animation_trajectory.py b/release/scripts/animation_trajectory.py deleted file mode 100644 index 55a670b66b1..00000000000 --- a/release/scripts/animation_trajectory.py +++ /dev/null @@ -1,575 +0,0 @@ -#!BPY - -""" Registration info for Blender menus: <- these words are ignored -Name: 'Trajectory' -Blender: 243 -Group: 'Animation' -Tip: 'See Trajectory of selected object' -""" - -__author__ = '3R - R3gis' -__version__ = '2.43' -__url__ = ["Script's site , http://blenderfrance.free.fr/python/Trajectory_en.htm","Author's site , http://cybercreator.free.fr", "French Blender support forum, http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender"] -__email__=["3R, r3gis@free.fr"] - - -__bpydoc__ = """ - -Usage: - -* Launch with alt+P (or put it in .script folder) - -Allow to see in real time trajectory of selected object. - -On first run, it ask you -- If you want that actually selected object have they trajectory always shown -- If you want to use Space Handler or a Scriptlink in Redraw mode -- Future and Past : it is the frame in past and future -of the beggining and the end of the path -- Width of line that represent the trajectory - -Then the object's trajectory will be shown in all 3D areas. -When trajectory is red, you can modifiy it by moving object. -When trajectory is blue and you want to be able to modify it, inser a Key (I-Key) - -Points appears on trajectory : -- Left Clic to modify position -- Right Clic to go to the frame it represents - -Notes:<br> -In scriptlink mode, it create one script link so make sure that 'Enable Script Link' toogle is on -In SpaceHandler mode, you have to go in View>>SpaceHandlerScript menu to activate Trajectory - - -""" - - -# -------------------------------------------------------------------------- -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Copyright (C) 2004-2006: Regis Montoya -# -# 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 ***** -# -------------------------------------------------------------------------- -################################# -# by 3R - 26/08/05 -# for any problem : -# r3gis@free.fr -# ou sur le newsgroup: -# http://zoo-logique.org/3D.Blender/ -################################# -#Many thanks to cambo for his fixes -################################# - - - -import Blender - - -scene= Blender.Scene.GetCurrent() - - -#Writing -def write_script(name, script): - global scene - #List texts and their name - #write : type of writing : 1->New, 2->Overwrite - scripting= None - for text in Blender.Text.Get(): - if text.name==name and text.asLines()[1] != "#"+str(__version__): - scripting = text - scripting.clear() - scripting.write(script) - break - - if not scripting: - scripting= Blender.Text.New(name) - scripting.write(script) - -def link_script(name, type): - global scene - scriptlinks = scene.getScriptLinks(type) # none or list - if not scriptlinks or name not in scriptlinks: - scene.addScriptLink(name, type) - - -#Deleting of a text -def text_remove(name): - global scene - #try to delete text if already linked - try: - text= Blender.Text.Get(name) - # Texte.clear() - scene.clearScriptLinks([name]) - Blender.Text.unlink(text) - except: - print('---Initialisation of Trajectory_'+str(__version__)+'.py---') - -#Whether is already running, also check if it's the last version of the script : second line contain the version fo the script -ask_modif= 0 # Default -for text in Blender.Text.Get(): - if text.name == 'Trajectory' and text.asLines()[1] == "#"+str(__version__): - #We ask if script modify his seetings, keep it or stop script - ask_modif= Blender.Draw.PupMenu("Script already launch %t|Modify settings%x0|Keep settings%x1|Stop script%x2|") - if ask_modif==-1: # user canceled. - ask_modif= 1 - break - -selection_mode= 0 -future= 35 -past= 20 -width= 2 - -#In modify case -if ask_modif==0: - handle_mode= Blender.Draw.Create(0) - selection_mode= Blender.Draw.Create(0) - future= Blender.Draw.Create(35) - past= Blender.Draw.Create(20) - width= Blender.Draw.Create(2) - - block= [] - block.append(("Space Handlers", handle_mode, "You have to activate for each area by View>>SpaceHandler")) #You can delete this option... - block.append(("Always Draw", selection_mode, "Selected object will have their trajectory always shown")) - block.append(("Past :", past, 1, 900)) - block.append(("Futur:", future, 1, 900)) - block.append(("Width:", width, 1,5)) - - if not Blender.Draw.PupBlock("Trajectory seetings", block): - ask_modif=1 - - handle_mode= handle_mode.val - selection_mode= selection_mode.val - future= future.val - past= past.val - width= width.val - - -#put names of selected objects in objects_select if option choosen by user -if selection_mode==1: - objects_select= [ob.name for ob in scene.objects.context] -else: - objects_select= [] - - -try: - if handle_mode==1: - DrawPart="#SPACEHANDLER.VIEW3D.DRAW\n" - else: - DrawPart="#!BPY\n" -except:DrawPart="#BadlyMade" - - -#Here is the script to write in Blender and to link, options are also written now -DrawPart=DrawPart+"#"+str(__version__)+""" -#This script is a part of Trajectory.py and have to be linked to the scene in Redraw if not in HANDLER mode. -#Author : 3R - Regis Montoya -#It's better to use the Trajectory_"version_number".py -#You can modify the two following value to change the path settings -future="""+str(future)+""" -past="""+str(past)+""" -object_init_names="""+str(objects_select)+""" - - -import Blender, math -from Blender import BGL, Draw, Ipo -from Blender.BGL import * -from Blender.Draw import * -from math import * - -from Blender.Mathutils import Vector - -#take actual frame -frameC=Blender.Get('curframe') -scene = Blender.Scene.GetCurrent() -render_context=scene.getRenderingContext() -#ajust number of frames with NewMap and OldMapvalue values -k=1.00*render_context.oldMapValue()/render_context.newMapValue() -if k<1: - tr=-1*int(log(k*0.1, 10)) -else: - tr=-1*int(log(k, 10)) -#The real and integer frame to compare to ipos keys frames -frameCtr=round(frameC*k, tr) -frameCr=frameC*k -frameC=int(round(frameC*k, 0)) - - -#List objects that we have to show trajectory in $objects -# In this case, using a dict for unique objects is the fastest way. -object_dict= dict([(ob.name, ob) for ob in scene.objects.context]) -for obname in object_init_names: - if not object_dict.has_key(obname): - try: # Object may be removed. - object_dict[obname]= Blender.Object.Get(obname) - except: - pass # object was removed. - -#This fonction give the resulting matrix of all parents at a given frame -#parent_list is the list of all parents [object, matrix, locX_ipo, locY, Z, rotX, Y, Z, sizeX, Y, Z] of current object -def matrixForTraj(frame, parent_list): - DecMatC=Blender.Mathutils.Matrix([1,0,0,0], [0,1,0,0], [0,0,1,0], [0,0,0,1]) - - for parent_data in parent_list: - parent_ob= parent_data[0] - - try: X= parent_data[5][frame]*pi/18 - except: X= parent_ob.RotX - try: Y= parent_data[6][frame]*pi/18 - except: Y= parent_ob.RotY - try: Z= parent_data[7][frame]*pi/18 - except: Z= parent_ob.RotZ - try: LX= parent_data[2][frame] - except: LX= parent_ob.LocX - try: LY= parent_data[3][frame] - except: LY= parent_ob.LocY - try: LZ= parent_data[4][frame] - except: LZ= parent_ob.LocZ - try: SX= parent_data[8][frame] - except: SX= parent_ob.SizeX - try: SY= parent_data[9][frame] - except: SY= parent_ob.SizeY - try: SZ= parent_data[10][frame] - except: SZ= parent_ob.SizeZ - - NMat=Blender.Mathutils.Matrix([cos(Y)*cos(Z)*SX,SX*cos(Y)*sin(Z),-SX*sin(Y),0], - [(-cos(X)*sin(Z)+sin(Y)*sin(X)*cos(Z))*SY,(sin(X)*sin(Y)*sin(Z)+cos(X)*cos(Z))*SY,sin(X)*cos(Y)*SY,0], - [(cos(X)*sin(Y)*cos(Z)+sin(X)*sin(Z))*SZ,(cos(X)*sin(Y)*sin(Z)-sin(X)*cos(Z))*SZ,SZ*cos(X)*cos(Y),0], - [LX,LY,LZ,1]) - DecMatC=DecMatC*parent_data[1]*NMat - return DecMatC - -##### -TestLIST=[] -matview=Blender.Window.GetPerspMatrix() -########### -#Fonction to draw trajectories -########### - -def Trace_Traj(ob): - global TestLIST, matview - #we draw trajectories for all objects in list - - LocX=[] - LocY=[] - LocZ=[] - #List with trajectories' vertexs - vertexX=[] - - contextIpo= ob.ipo - if contextIpo: - ipoLocX=contextIpo[Ipo.OB_LOCX] - ipoLocY=contextIpo[Ipo.OB_LOCY] - ipoLocZ=contextIpo[Ipo.OB_LOCZ] - ipoTime=contextIpo[Ipo.OB_TIME] - else: # only do if there is no IPO (if no ipo curves : return None object and don't go in this except) - ipoLocX= ipoLocY= ipoLocZ= ipoTime= None - - if ipoTime: - return 0 - - #Get all parents of ob - parent=ob.parent - backup_ob= ob - child= ob - parent_list= [] - - #Get parents's infos : - #list of [name, initial matrix at make parent, ipo in X,Y,Z,rotX,rotY,rotZ,sizeX,Y,Z] - while parent: - Init_Mat=Blender.Mathutils.Matrix(child.getMatrix('worldspace')) #must be done like it (it isn't a matrix otherwise) - Init_Mat.invert() - Init_Mat=Init_Mat*child.getMatrix('localspace') - Init_Mat=parent.getMatrix()*Init_Mat - Init_Mat.invert() - - contextIpo= parent.ipo # None or IPO - if contextIpo: - ipo_Parent_LocX=contextIpo[Ipo.OB_LOCX] - ipo_Parent_LocY=contextIpo[Ipo.OB_LOCY] - ipo_Parent_LocZ=contextIpo[Ipo.OB_LOCZ] - ipo_Parent_RotX=contextIpo[Ipo.OB_ROTX] - ipo_Parent_RotY=contextIpo[Ipo.OB_ROTY] - ipo_Parent_RotZ=contextIpo[Ipo.OB_ROTZ] - ipo_Parent_SizeX=contextIpo[Ipo.OB_SIZEX] - ipo_Parent_SizeY=contextIpo[Ipo.OB_SIZEY] - ipo_Parent_SizeZ=contextIpo[Ipo.OB_SIZEZ] - else: - ipo_Parent_LocX=ipo_Parent_LocY=ipo_Parent_LocZ=\ - ipo_Parent_RotX=ipo_Parent_RotY=ipo_Parent_RotZ=\ - ipo_Parent_SizeX=ipo_Parent_SizeY=ipo_Parent_SizeZ= None - - parent_list.append([parent, Init_Mat, ipo_Parent_LocX, ipo_Parent_LocY, ipo_Parent_LocZ, ipo_Parent_RotX, ipo_Parent_RotY, ipo_Parent_RotZ, ipo_Parent_SizeX, ipo_Parent_SizeY, ipo_Parent_SizeZ]) - - child=parent - parent=parent.parent - - #security : if one of parents object are a path>>follow : trajectory don't work properly so it have to draw nothing - for parent in parent_list: - if parent[0].type == 'Curve': - if parent[0].data.flag & 1<<4: # Follow path, 4th bit - return 1 - - #ob >> re-assign obj and not parent - ob= backup_ob - ob= backup_ob - - - if ipoLocX: LXC= ipoLocX[frameC] - else: LXC= ob.LocX - if ipoLocY: LYC= ipoLocY[frameC] - else: LYC= ob.LocY - if ipoLocZ: LZC= ipoLocZ[frameC] - else: LZC= ob.LocZ - - vect= Vector([ob.LocX, ob.LocY, ob.LocZ, 1]) - color=[0, 1] - - #If trajectory is being modified and we are at a frame where a ipo key already exist - if round(ob.LocX, 5)!=round(LXC, 5): - for bez in ipoLocX.bezierPoints: - if round(bez.pt[0], tr)==frameCtr: - bez.pt = [frameCr, vect[0]] - ipoLocX.recalc() - if round(ob.LocY, 5)!=round(LYC, 5): - for bez in ipoLocY.bezierPoints: - if round(bez.pt[0], tr)==frameCtr: - bez.pt = [frameCr, vect[1]] - ipoLocY.recalc() - if round(ob.LocZ, 5)!=round(LZC, 5): - for bez in ipoLocZ.bezierPoints: - if round(bez.pt[0], tr)==frameCtr: - bez.pt = [frameCr, vect[2]] - ipoLocZ.recalc() - - #change trajectory color if at an ipoKey - VertexFrame=[] - bezier_Coord=0 - if ipoLocX: # FIXED like others it was just in case ipoLocX==None - for bez in ipoLocX.bezierPoints: - bezier_Coord=round(bez.pt[0], tr) - if bezier_Coord not in VertexFrame: - VertexFrame.append(bezier_Coord) - if bezier_Coord==frameCtr: - color=[1, color[1]-0.3] - if ipoLocY: # FIXED - for bez in ipoLocY.bezierPoints: - bezier_Coord=round(bez.pt[0], tr) - if bezier_Coord not in VertexFrame: - VertexFrame.append(bezier_Coord) - if round(bez.pt[0], tr)==frameCtr: - color=[1, color[1]-0.3] - if ipoLocZ: # FIXED - for bez in ipoLocZ.bezierPoints: - bezier_Coord=round(bez.pt[0], tr) - if bezier_Coord not in VertexFrame: - VertexFrame.append(bezier_Coord) - if round(bez.pt[0], tr)==frameCtr: - color=[1, color[1]-0.3] - - - #put in LocX, LocY and LocZ all points of trajectory - for frame in xrange(frameC-past, frameC+future): - DecMat=matrixForTraj(frame, parent_list) - - if ipoLocX: LX= ipoLocX[frame] - else: LX= ob.LocX - if ipoLocY: LY= ipoLocY[frame] - else: LY= ob.LocY - if ipoLocZ: LZ= ipoLocZ[frame] - else: LZ= ob.LocZ - - vect=Vector(LX, LY, LZ)*DecMat - LocX.append(vect[0]) - LocY.append(vect[1]) - LocZ.append(vect[2]) - - - #draw part : get current view - MatPreBuff= [matview[i][j] for i in xrange(4) for j in xrange(4)] - - MatBuff=BGL.Buffer(GL_FLOAT, 16, MatPreBuff) - - glLoadIdentity() - glMatrixMode(GL_PROJECTION) - glPushMatrix() - glLoadMatrixf(MatBuff) - - #draw trajectory line - glLineWidth("""+str(width)+""") - - glBegin(GL_LINE_STRIP) - for i in xrange(len(LocX)): - glColor3f((i+1)*1.00/len(LocX)*color[0], 0, (i+1)*1.00/len(LocX)*color[1]) - glVertex3f(LocX[i], LocY[i], LocZ[i]) - - glEnd() - - #draw trajectory's "vertexs" - if not Blender.Window.EditMode(): - glPointSize(5) - glBegin(GL_POINTS) - TestPOINTS=[] - TestFRAME=[] - i=0 - for frame in VertexFrame: - ix=int(frame)-frameC+past - if ix>=0 and ix<len(LocX): - glColor3f(1, 0.7, 0.2) - glVertex3f(LocX[ix], LocY[ix], LocZ[ix]) - TestPOINTS.append(Vector([LocX[ix], LocY[ix], LocZ[ix], 1])) - TestFRAME.append(int(frame)) - i+=1 - glEnd() - #this list contains info about where to check if we click over a "vertex" in 3D view - TestLIST.append((ob, TestPOINTS, TestFRAME)) - - glLineWidth(1) - return 0 - - -for ob in object_dict.itervalues(): - Trace_Traj(ob) - -########### -#Fonction to handle trajectories -########### - -def Manip(): - #use TestLIST and matview defined by Trace_Traj - global TestLIST, matview - for screen in Blender.Window.GetScreenInfo(Blender.Window.Types.VIEW3D): - if screen['id']==Blender.Window.GetAreaID(): - x0, y0, x1, y1= screen['vertices'] - break - - #Projection of GL matrix in 3D view - glPushMatrix() - glMatrixMode(GL_PROJECTION) - glPushMatrix() - glLoadIdentity() - #Global coordinates' matrix - glOrtho(x0, x1, y0, y1, -1, 0) - glMatrixMode(GL_MODELVIEW) - glLoadIdentity() - #Test mouse clics and other events - - - if Blender.Window.QTest(): - evt, val= Blender.Window.QRead() - if (evt==LEFTMOUSE or evt==RIGHTMOUSE) and not Blender.Window.EditMode(): - mouse_co=Blender.Window.GetMouseCoords() - #if click on trajectory "vertexs"... - for ob, TestPOINTS, TestFRAME in TestLIST: # ob is now used, line 552 to know what object it had to select - for k, Vect in enumerate(TestPOINTS): - proj=Vect*matview - - pt=[(proj[0]/proj[3])*(x1-x0)/2+(x1+x0)/2, (proj[1]/proj[3])*(y1-y0)/2+(y1+y0)/2] - - if mouse_co[0]<pt[0]+4 and mouse_co[0]>pt[0]-4 and mouse_co[1]>pt[1]-4 and mouse_co[1]<pt[1]+4: - if evt==LEFTMOUSE: - #remember current selected object - object_names=[obj.name for obj in Blender.Object.GetSelected()] - #this script allow to simulate a GKey, but I have to write a script - #another way would made a infinit redraw or don't allow to move object - #it auto unlink and delete itself - script=\"\"\" -import Blender -from Blender import Draw, Window -from Blender.Window import * -from Blender.Draw import * - -from Blender.Mathutils import Vector - -# The following code is a bit of a hack, it allows clicking on the points and dragging directly -#It simulate user press GKey -#It also set the cursor position at center (because user have previously clic on area and moved the cursor): -#And I can't get previous cursor position : redraw appear after it has been moved -#If there is no better way you can remove this comments -f= GetAreaID() -SetCursorPos(0,0,0) -#SetKeyQualifiers(1) #FIXED : the bug in older versions seems to have been fixed -SetKeyQualifiers(0) -QAdd(f, Blender.Draw.GKEY, 1, 0) -QHandle(f) -Blender.Redraw() -done=0 -while not done: - while Blender.Window.QTest(): - ev=Blender.Window.QRead()[0] - if ev not in (4, 5, 18, 112, 213): #all event needed to move object - #SetKeyQualifiers(1) #FIXED too, same reason that above - #SetKeyQualifiers(0) - SetKeyQualifiers(Blender.Window.GetKeyQualifiers()) - QAdd(f, ev, 1, 0) - QHandle(f) - Blender.Redraw() - if ev in (RIGHTMOUSE, LEFTMOUSE, ESCKEY): - done=1 -Blender.Set('curframe',\"\"\"+str(Blender.Get('curframe'))+\"\"\") -Blender.Object.GetSelected()[0].sel= False -for obname in \"\"\"+str(object_names)+\"\"\": - ob=Blender.Object.Get(obname) - ob.sel= True -SetCursorPos(0,0,0) -scripting=Blender.Text.Get('Edit_Trajectory') -scripting.clear() -Blender.Text.unlink(scripting) - \"\"\" - - #FIXED Edit_Trajectory was longer : all SetKeyQualifiers removed - scene=Blender.Scene.GetCurrent() - try: - scripting=Blender.Text.Get('Edit_Trajectory') - scripting.clear() - except: - scripting=Blender.Text.New('Edit_Trajectory') - - scripting.write(script) - #script= scripting #FIXED seems not needed anymore - - #Go to frame that correspond to selected "vertex" - Blender.Set('curframe', TestFRAME[k]) - - scene.objects.selected = [] #un select all objects - - #FIXED TestLIST[j][0].sel=0, but no j. So ob.sel and above variable changed in obj - ob.sel= True - Blender.Run('Edit_Trajectory') - - #work well now !!! - if evt==RIGHTMOUSE : - Blender.Set('curframe', TestFRAME[k]) - -Manip() -#retrieve a normal matrix -glPopMatrix() -glMatrixMode(GL_PROJECTION) -glPopMatrix() -glMatrixMode(GL_MODELVIEW) -""" - -if ask_modif==0: - text_remove('Trajectory') - write_script('Trajectory', DrawPart) - if handle_mode==1: - Blender.UpdateMenus() - else: - link_script('Trajectory', 'Redraw') -if ask_modif==2: - text_remove('Trajectory') - print("---End of Trajectory_"+str(__version__)+".py---\n--- Thanks for use ---") diff --git a/release/scripts/armature_symmetry.py b/release/scripts/armature_symmetry.py deleted file mode 100644 index 5ee4e086fb0..00000000000 --- a/release/scripts/armature_symmetry.py +++ /dev/null @@ -1,325 +0,0 @@ -#!BPY - -""" -Name: 'Armature Symmetry' -Blender: 242 -Group: 'Armature' -Tooltip: 'Make an Armature symmetrical' -""" - -__author__ = "Campbell Barton" -__url__ = ("blender", "blenderartist") -__version__ = "1.0 2006-7-26" - -__doc__ = """\ -This script creates perfectly symmetrical armatures, -based on the best fit when comparing the mirrored locations of 2 bones. -Hidden bones are ignored, and optionally only operate on selected bones. -""" - -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Script copyright (C) Campbell J Barton 2006 -# -# 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 ***** -# -------------------------------------------------------------------------- - -import Blender -import bpy -Vector= Blender.Mathutils.Vector - - -def VecXFlip(vec): - ''' - Return a copy of this vector x flipped. - ''' - x,y,z= vec - return Vector(-x,y,z) - -def editbone_mirror_diff(editbone1, editbone2): - ''' - X Mirror bone compare - return a float representing the difference between the 2 bones - the smaller the better the match - ''' - h1= editbone1.head - h2= editbone2.head - - t1= editbone1.tail - t2= editbone2.tail - - # Mirror bone2's location - h2= VecXFlip(h2) - t2= VecXFlip(t2) - - #return (h1-h2).length + (t1-t2).length # returns the length only - - # For this function its easier to return the bones also - return ((h1-h2).length + (t1-t2).length)/2, editbone1, editbone2 - -def editbone_mirror_merge(editbone1, editbone2, PREF_MODE_L2R, PREF_MODE_R2L): - ''' - Merge these 2 bones to their mirrored locations - ''' - h1= editbone1.head - h2= editbone2.head - - t1= editbone1.tail - t2= editbone2.tail - - if PREF_MODE_L2R and PREF_MODE_R2L: - # Median, flip bone2's locations and average, then apply to editbone1, flip and apply to editbone2 - h2_f= VecXFlip(h2) - t2_f= VecXFlip(t2) - - h_med= (h1+h2_f)*0.5 # middle between t1 and flipped t2 - t_med= (t1+t2_f)*0.5 # middle between h1 and flipped h2 - - # Apply the median to editbone1 - editbone1.head= h_med - editbone1.tail= t_med - - # Flip in place for editbone2 - h_med.x= -h_med.x - t_med.x= -t_med.x - - # Apply the median to editbone2 - editbone2.head= h_med - editbone2.tail= t_med - - # Average the roll, this might need some logical work, but looks good for now. - r1= editbone1.roll - r2= -editbone2.roll - # print 'rolls are', r1,r2 - r_med= (r1+r2)/2 - # print 'new roll is', r_med - editbone1.roll= r_med - editbone2.roll= -r_med # mirror roll - - else: # Copy from 1 side to another - - # Crafty function we can use so L>R and R>L can use the same code - def IS_XMIRROR_SOURCE(xval): - '''Source means is this the value we want to copy from''' - - if PREF_MODE_L2R: - if xval<0: return True - else: return False - else: # PREF_MODE_R2L - if xval<0: return False - else: return True - - if IS_XMIRROR_SOURCE( h1.x ):# head bone 1s negative, so copy it to h2 - editbone2.head= VecXFlip(h1) - else: - ''' - assume h2.x<0 - not a big deal if were wrong, - its unlikely to ever happen because the bones would both be on the same side. - ''' - - # head bone 2s negative, so copy it to h1 - editbone1.head= VecXFlip(h2) - - # Same as above for tail - if IS_XMIRROR_SOURCE(t1.x): - editbone2.tail= VecXFlip(t1) - else: - editbone1.tail= VecXFlip(t2) - - # Copy roll from 1 bone to another, use the head's location to decide which side it's on. - if IS_XMIRROR_SOURCE(editbone1.head): - editbone2.roll= -editbone1.roll - else: - editbone1.roll= -editbone2.roll - - -def armature_symetry(\ - arm_ob,\ - PREF_MAX_DIST,\ - PREF_XMID_SNAP,\ - PREF_XZERO_THRESH,\ - PREF_MODE_L2R,\ - PREF_MODE_R2L,\ - PREF_SEL_ONLY): - - ''' - Main function that does all the work, - return the number of - ''' - arm_data= arm_ob.data - arm_data.makeEditable() - - # Get the bones - bones= [] - HIDDEN_EDIT= Blender.Armature.HIDDEN_EDIT - BONE_SELECTED= Blender.Armature.BONE_SELECTED - - if PREF_SEL_ONLY: - for eb in arm_data.bones.values(): - options= eb.options - if HIDDEN_EDIT not in options and BONE_SELECTED in options: - bones.append(eb) - else: - # All non hidden bones - for eb in arm_data.bones.values(): - options= eb.options - if HIDDEN_EDIT not in options: - bones.append(eb) - - del HIDDEN_EDIT # remove temp variables - del BONE_SELECTED - - # Store the numder of bones we have modified for a message - tot_editbones= len(bones) - tot_editbones_modified= 0 - - if PREF_XMID_SNAP: - # Remove bones that are in the middle (X Zero) - # reverse loop so we can remove items in the list. - for eb_idx in xrange(len(bones)-1, -1, -1): - edit_bone= bones[eb_idx] - if abs(edit_bone.head.x) + abs(edit_bone.tail.x) <= PREF_XZERO_THRESH/2: - - # This is a center bone, clamp and remove from the bone list so we dont use again. - if edit_bone.tail.x or edit_bone.head.x: - tot_editbones_modified += 1 - - edit_bone.tail.x= edit_bone.head.x= 0 - del bones[eb_idx] - - - - - bone_comparisons= [] - - # Compare every bone with every other bone, shouldn't be too slow. - # These 2 "for" loops only compare once - for eb_idx_a in xrange(len(bones)-1, -1, -1): - edit_bone_a= bones[eb_idx_a] - for eb_idx_b in xrange(eb_idx_a-1, -1, -1): - edit_bone_b= bones[eb_idx_b] - # Error float the first value from editbone_mirror_diff() so we can sort the resulting list. - bone_comparisons.append(editbone_mirror_diff(edit_bone_a, edit_bone_b)) - - - bone_comparisons.sort() # best matches first - - # Make a dict() of bone names that have been used so we dont mirror more then once - bone_mirrored= {} - - for error, editbone1, editbone2 in bone_comparisons: - # print 'Trying to merge at error %.3f' % error - if error > PREF_MAX_DIST: - # print 'breaking, max error limit reached PREF_MAX_DIST: %.3f' % PREF_MAX_DIST - break - - if not bone_mirrored.has_key(editbone1.name) and not bone_mirrored.has_key(editbone2.name): - # Were not used, execute the mirror - editbone_mirror_merge(editbone1, editbone2, PREF_MODE_L2R, PREF_MODE_R2L) - # print 'Merging bones' - - # Add ourselves so we aren't touched again - bone_mirrored[editbone1.name] = None # dummy value, would use sets in python 2.4 - bone_mirrored[editbone2.name] = None - - # If both options are enabled, then we have changed 2 bones - tot_editbones_modified+= PREF_MODE_L2R + PREF_MODE_R2L - - arm_data.update() # get out of armature editmode - return tot_editbones, tot_editbones_modified - - -def main(): - ''' - User interface function that gets the options and calls armature_symetry() - ''' - - scn= bpy.data.scenes.active - arm_ob= scn.objects.active - - if not arm_ob or arm_ob.type!='Armature': - Blender.Draw.PupMenu('No Armature object selected.') - return - - # Cant be in editmode for armature.makeEditable() - is_editmode= Blender.Window.EditMode() - if is_editmode: Blender.Window.EditMode(0) - Draw= Blender.Draw - - # Defaults for the user input - PREF_XMID_SNAP= Draw.Create(1) - PREF_MAX_DIST= Draw.Create(0.4) - PREF_XZERO_THRESH= Draw.Create(0.02) - - PREF_MODE_L2R= Draw.Create(1) - PREF_MODE_R2L= Draw.Create(0) - PREF_SEL_ONLY= Draw.Create(1) - - pup_block = [\ - 'Left (-), Right (+)',\ - ('Left > Right', PREF_MODE_L2R, 'Copy from the Left to Right of the mesh. Enable Both for a mid loc.'),\ - ('Right > Left', PREF_MODE_R2L, 'Copy from the Right to Left of the mesh. Enable Both for a mid loc.'),\ - '',\ - ('MaxDist:', PREF_MAX_DIST, 0.0, 4.0, 'Maximum difference in mirror bones to match up pairs.'),\ - ('XZero limit:', PREF_XZERO_THRESH, 0.0, 2.0, 'Tolerance for locking bones into the middle (X/zero).'),\ - ('XMidSnap Bones', PREF_XMID_SNAP, 'Snap middle verts to X Zero (uses XZero limit)'),\ - ('Selected Only', PREF_SEL_ONLY, 'Only xmirror selected bones.'),\ - ] - - # Popup, exit if the user doesn't click OK - if not Draw.PupBlock("X Mirror mesh tool", pup_block): - return - - # Replace the variables with their button values. - PREF_XMID_SNAP= PREF_XMID_SNAP.val - PREF_MAX_DIST= PREF_MAX_DIST.val - PREF_MODE_L2R= PREF_MODE_L2R.val - PREF_MODE_R2L= PREF_MODE_R2L.val - PREF_XZERO_THRESH= PREF_XZERO_THRESH.val - PREF_SEL_ONLY= PREF_SEL_ONLY.val - - # If both are off assume mid-point and enable both - if not PREF_MODE_R2L and not PREF_MODE_L2R: - PREF_MODE_R2L= PREF_MODE_L2R= True - - - tot_editbones, tot_editbones_modified = armature_symetry(\ - arm_ob,\ - PREF_MAX_DIST,\ - PREF_XMID_SNAP,\ - PREF_XZERO_THRESH,\ - PREF_MODE_L2R,\ - PREF_MODE_R2L,\ - PREF_SEL_ONLY) - - if is_editmode: Blender.Window.EditMode(1) - - # Redraw all views before popup - Blender.Window.RedrawAll() - - # Print results - if PREF_SEL_ONLY: - msg= 'moved %i bones of %i selected' % (tot_editbones_modified, tot_editbones) - else: - msg= 'moved %i bones of %i visible' % (tot_editbones_modified, tot_editbones) - - - Blender.Draw.PupMenu(msg) - -# Check for __main__ so this function can be imported by other scripts without running the script. -if __name__=='__main__': - main() diff --git a/release/scripts/bevel_center.py b/release/scripts/bevel_center.py deleted file mode 100644 index 637ed08127f..00000000000 --- a/release/scripts/bevel_center.py +++ /dev/null @@ -1,474 +0,0 @@ -#!BPY -# -*- coding: utf-8 -*- -""" Registration info for Blender menus -Name: 'Bevel Center' -Blender: 243 -Group: 'Mesh' -Tip: 'Bevel selected faces, edges, and vertices' -""" - -__author__ = "Loic BERTHE" -__url__ = ("blender", "blenderartists.org") -__version__ = "2.0" - -__bpydoc__ = """\ -This script implements vertex and edges bevelling in Blender. - -Usage: - -Select the mesh you want to work on, enter Edit Mode and select the edges -to bevel. Then run this script from the 3d View's Mesh->Scripts menu. - -You can control the thickness of the bevel with the slider -- redefine the -end points for bigger or smaller ranges. The thickness can be changed even -after applying the bevel, as many times as needed. - -For an extra smoothing after or instead of direct bevel, set the level of -recursiveness and use the "Recursive" button. - -This "Recursive" Button, won't work in face select mode, unless you choose -"faces" in the select mode menu. - -Notes:<br> - You can undo and redo your steps just like with normal mesh operations in -Blender. -""" - -###################################################################### -# Bevel Center v2.0 for Blender - -# This script lets you bevel the selected vertices or edges and control the -# thickness of the bevel - -# (c) 2004-2006 Loïc Berthe (loic+blender@lilotux.net) -# released under Blender Artistic License - -###################################################################### - -import Blender -from Blender import NMesh, Window, Scene -from Blender.Draw import * -from Blender.Mathutils import * -from Blender.BGL import * -import BPyMessages -#PY23 NO SETS# -''' -try: - set() -except: - from sets import set -''' - -###################################################################### -# Functions to handle the global structures of the script NF, NE and NC -# which contain informations about faces and corners to be created - -global E_selected -E_selected = NMesh.EdgeFlags['SELECT'] - -old_dist = None - -def act_mesh_ob(): - scn = Scene.GetCurrent() - ob = scn.objects.active - if ob == None or ob.type != 'Mesh': - BPyMessages.Error_NoMeshActive() - return - - if ob.getData(mesh=1).multires: - BPyMessages.Error_NoMeshMultiresEdit() - return - - return ob - -def make_sel_vert(*co): - v= NMesh.Vert(*co) - v.sel = 1 - me.verts.append(v) - return v - -def make_sel_face(verts): - f = NMesh.Face(verts) - f.sel = 1 - me.addFace(f) - -def add_to_NV(old,dir,new): - try: - NV[old][dir] = new - except: - NV[old] = {dir:new} - -def get_v(old, *neighbors): - # compute the direction of the new vert - if len(neighbors) == 1: dir = (neighbors[0].co - old.co).normalize() - #dir - else: dir = (neighbors[0].co - old.co).normalize() + (neighbors[1].co-old.co).normalize() - - # look in NV if this vert already exists - key = tuple(dir) - if old in NV and key in NV[old] : return NV[old][key] - - # else, create it - new = old.co + dist.val*dir - v = make_sel_vert(new.x,new.y,new.z) - add_to_NV(old,key,v) - return v - -def make_faces(): - """ Analyse the mesh, make the faces corresponding to selected faces and - fill the structures NE and NC """ - - # make the differents flags consistent - for e in me.edges: - if e.flag & E_selected : - e.v1.sel = 1 - e.v2.sel = 1 - - NF =[] # NF : New faces - for f in me.faces: - V = f.v - nV = len(V) - enumV = range(nV) - E = [me.findEdge(V[i],V[(i+1) % nV]) for i in enumV] - Esel = [x.flag & E_selected for x in E] - - # look for selected vertices and creates a list containing the new vertices - newV = V[:] - changes = False - for (i,v) in enumerate(V): - if v.sel : - changes = True - if Esel[i-1] == 0 and Esel[i] == 1 : newV[i] = get_v(v,V[i-1]) - elif Esel[i-1] == 1 and Esel[i] == 0 : newV[i] = get_v(v,V[(i+1) % nV]) - elif Esel[i-1] == 1 and Esel[i] == 1 : newV[i] = get_v(v,V[i-1],V[(i+1) % nV]) - else : newV[i] = [get_v(v,V[i-1]),get_v(v,V[(i+1) % nV])] - - if changes: - # determine and store the face to be created - - lenV = [len(x) for x in newV] - if 2 not in lenV : - new_f = NMesh.Face(newV) - if sum(Esel) == nV : new_f.sel = 1 - NF.append(new_f) - - else : - nb2 = lenV.count(2) - - if nV == 4 : # f is a quad - if nb2 == 1 : - ind2 = lenV.index(2) - NF.append(NMesh.Face([newV[ind2-1],newV[ind2][0],newV[ind2][1],newV[ind2-3]])) - NF.append(NMesh.Face([newV[ind2-1],newV[ind2-2],newV[ind2-3]])) - - elif nb2 == 2 : - # We must know if the tuples are neighbours - ind2 = ''.join([str(x) for x in lenV+lenV[:1]]).find('22') - - if ind2 != -1 : # They are - NF.append(NMesh.Face([newV[ind2][0],newV[ind2][1],newV[ind2-3][0],newV[ind2-3][1]])) - NF.append(NMesh.Face([newV[ind2][0],newV[ind2-1],newV[ind2-2],newV[ind2-3][1]])) - - else: # They aren't - ind2 = lenV.index(2) - NF.append(NMesh.Face([newV[ind2][0],newV[ind2][1],newV[ind2-2][0],newV[ind2-2][1]])) - NF.append(NMesh.Face([newV[ind2][1],newV[ind2-3],newV[ind2-2][0]])) - NF.append(NMesh.Face([newV[ind2][0],newV[ind2-1],newV[ind2-2][1]])) - - elif nb2 == 3 : - ind2 = lenV.index(3) - NF.append(NMesh.Face([newV[ind2-1][1],newV[ind2],newV[ind2-3][0]])) - NF.append(NMesh.Face([newV[ind2-1][0],newV[ind2-1][1],newV[ind2-3][0],newV[ind2-3][1]])) - NF.append(NMesh.Face([newV[ind2-3][1],newV[ind2-2][0],newV[ind2-2][1],newV[ind2-1][0]])) - - else: - if (newV[0][1].co-newV[3][0].co).length + (newV[1][0].co-newV[2][1].co).length \ - < (newV[0][0].co-newV[1][1].co).length + (newV[2][0].co-newV[3][1].co).length : - ind2 = 0 - else : - ind2 = 1 - NF.append(NMesh.Face([newV[ind2-1][0],newV[ind2-1][1],newV[ind2][0],newV[ind2][1]])) - NF.append(NMesh.Face([newV[ind2][1],newV[ind2-3][0],newV[ind2-2][1],newV[ind2-1][0]])) - NF.append(NMesh.Face([newV[ind2-3][0],newV[ind2-3][1],newV[ind2-2][0],newV[ind2-2][1]])) - - else : # f is a tri - if nb2 == 1: - ind2 = lenV.index(2) - NF.append(NMesh.Face([newV[ind2-2],newV[ind2-1],newV[ind2][0],newV[ind2][1]])) - - elif nb2 == 2: - ind2 = lenV.index(3) - NF.append(NMesh.Face([newV[ind2-1][1],newV[ind2],newV[ind2-2][0]])) - NF.append(NMesh.Face([newV[ind2-2][0],newV[ind2-2][1],newV[ind2-1][0],newV[ind2-1][1]])) - - else: - ind2 = min( [((newV[i][1].co-newV[i-1][0].co).length, i) for i in enumV] )[1] - NF.append(NMesh.Face([newV[ind2-1][1],newV[ind2][0],newV[ind2][1],newV[ind2-2][0]])) - NF.append(NMesh.Face([newV[ind2-2][0],newV[ind2-2][1],newV[ind2-1][0],newV[ind2-1][1]])) - - # Preparing the corners - for i in enumV: - if lenV[i] == 2 : NC.setdefault(V[i],[]).append(newV[i]) - - - old_faces.append(f) - - # Preparing the Edges - for i in enumV: - if Esel[i]: - verts = [newV[i],newV[(i+1) % nV]] - if V[i].index > V[(i+1) % nV].index : verts.reverse() - NE.setdefault(E[i],[]).append(verts) - - # Create the faces - for f in NF: me.addFace(f) - -def make_edges(): - """ Make the faces corresponding to selected edges """ - - for old,new in NE.iteritems() : - if len(new) == 1 : # This edge was on a border - oldv = [old.v1, old.v2] - if old.v1.index < old.v2.index : oldv.reverse() - - make_sel_face(oldv+new[0]) - - me.findEdge(*oldv).flag |= E_selected - me.findEdge(*new[0]).flag |= E_selected - - #PY23 NO SETS# for v in oldv : NV_ext.add(v) - for v in oldv : NV_ext[v]= None - - else: - make_sel_face(new[0] + new[1][::-1]) - - me.findEdge(*new[0]).flag |= E_selected - me.findEdge(*new[1]).flag |= E_selected - -def make_corners(): - """ Make the faces corresponding to corners """ - - for v in NV.iterkeys(): - V = NV[v].values() - nV = len(V) - - if nV == 1: pass - - elif nV == 2 : - #PY23 NO SETS# if v in NV_ext: - if v in NV_ext.iterkeys(): - make_sel_face(V+[v]) - me.findEdge(*V).flag |= E_selected - - else: - #PY23 NO SETS# if nV == 3 and v not in NV_ext : make_sel_face(V) - if nV == 3 and v not in NV_ext.iterkeys() : make_sel_face(V) - - - else : - - # We need to know which are the edges around the corner. - # First, we look for the quads surrounding the corner. - eed = [] - for old, new in NE.iteritems(): - if v in (old.v1,old.v2) : - if v.index == min(old.v1.index,old.v2.index) : ind = 0 - else : ind = 1 - - if len(new) == 1: eed.append([v,new[0][ind]]) - else : eed.append([new[0][ind],new[1][ind]]) - - # We will add the edges coming from faces where only one vertice is selected. - # They are stored in NC. - if v in NC: eed = eed+NC[v] - - # Now we have to sort these vertices - hc = {} - for (a,b) in eed : - hc.setdefault(a,[]).append(b) - hc.setdefault(b,[]).append(a) - - for x0,edges in hc.iteritems(): - if len(edges) == 1 : break - - b = [x0] # b will contain the sorted list of vertices - - for i in xrange(len(hc)-1): - for x in hc[x0] : - if x not in b : break - b.append(x) - x0 = x - - b.append(b[0]) - - # Now we can create the faces - if len(b) == 5: make_sel_face(b[:4]) - - else: - New_V = Vector(0.0, 0.0,0.0) - New_d = [0.0, 0.0,0.0] - - for x in hc.iterkeys(): New_V += x.co - for dir in NV[v] : - for i in xrange(3): New_d[i] += dir[i] - - New_V *= 1./len(hc) - for i in xrange(3) : New_d[i] /= nV - - center = make_sel_vert(New_V.x,New_V.y,New_V.z) - add_to_NV(v,tuple(New_d),center) - - for k in xrange(len(b)-1): make_sel_face([center, b[k], b[k+1]]) - - if 2 < nV and v in NC : - for edge in NC[v] : me.findEdge(*edge).flag |= E_selected - -def clear_old(): - """ Erase old faces and vertices """ - - for f in old_faces: me.removeFace(f) - - for v in NV.iterkeys(): - #PY23 NO SETS# if v not in NV_ext : me.verts.remove(v) - if v not in NV_ext.iterkeys() : me.verts.remove(v) - - for e in me.edges: - if e.flag & E_selected : - e.v1.sel = 1 - e.v2.sel = 1 - - -###################################################################### -# Interface - -global dist - -dist = Create(0.2) -left = Create(0.0) -right = Create(1.0) -num = Create(2) - -# Events -EVENT_NOEVENT = 1 -EVENT_BEVEL = 2 -EVENT_UPDATE = 3 -EVENT_RECURS = 4 -EVENT_EXIT = 5 - -def draw(): - global dist, left, right, num, old_dist - global EVENT_NOEVENT, EVENT_BEVEL, EVENT_UPDATE, EVENT_RECURS, EVENT_EXIT - - glClear(GL_COLOR_BUFFER_BIT) - Button("Bevel",EVENT_BEVEL,10,100,280,25) - - BeginAlign() - left=Number('', EVENT_NOEVENT,10,70,45, 20,left.val,0,right.val,'Set the minimum of the slider') - dist=Slider("Thickness ",EVENT_UPDATE,60,70,180,20,dist.val,left.val,right.val,0, \ - "Thickness of the bevel, can be changed even after bevelling") - right = Number("",EVENT_NOEVENT,245,70,45,20,right.val,left.val,200,"Set the maximum of the slider") - - EndAlign() - glRasterPos2d(8,40) - Text('To finish, you can use recursive bevel to smooth it') - - - if old_dist != None: - num=Number('', EVENT_NOEVENT,10,10,40, 16,num.val,1,100,'Recursion level') - Button("Recursive",EVENT_RECURS,55,10,100,16) - - Button("Exit",EVENT_EXIT,210,10,80,20) - -def event(evt, val): - if ((evt == QKEY or evt == ESCKEY) and not val): Exit() - -def bevent(evt): - if evt == EVENT_EXIT : Exit() - elif evt == EVENT_BEVEL : bevel() - elif evt == EVENT_UPDATE : - try: bevel_update() - except NameError : pass - elif evt == EVENT_RECURS : recursive() - -Register(draw, event, bevent) - -###################################################################### -def bevel(): - """ The main function, which creates the bevel """ - global me,NV,NV_ext,NE,NC, old_faces,old_dist - - ob = act_mesh_ob() - if not ob: return - - Window.WaitCursor(1) # Change the Cursor - t= Blender.sys.time() - is_editmode = Window.EditMode() - if is_editmode: Window.EditMode(0) - - me = ob.data - - NV = {} - #PY23 NO SETS# NV_ext = set() - NV_ext= {} - NE = {} - NC = {} - old_faces = [] - - make_faces() - make_edges() - make_corners() - clear_old() - - old_dist = dist.val - print '\tbevel in %.6f sec' % (Blender.sys.time()-t) - me.update(1) - if is_editmode: Window.EditMode(1) - Window.WaitCursor(0) - Blender.Redraw() - -def bevel_update(): - """ Use NV to update the bevel """ - global dist, old_dist - - if old_dist == None: - # PupMenu('Error%t|Must bevel first.') - return - - is_editmode = Window.EditMode() - if is_editmode: Window.EditMode(0) - - fac = dist.val - old_dist - old_dist = dist.val - - for old_v in NV.iterkeys(): - for dir in NV[old_v].iterkeys(): - for i in xrange(3): - NV[old_v][dir].co[i] += fac*dir[i] - - me.update(1) - if is_editmode: Window.EditMode(1) - Blender.Redraw() - -def recursive(): - """ Make a recursive bevel... still experimental """ - global dist - from math import pi, sin - - if num.val > 1: - a = pi/4 - ang = [] - for k in xrange(num.val): - ang.append(a) - a = (pi+2*a)/4 - - l = [2*(1-sin(x))/sin(2*x) for x in ang] - R = dist.val/sum(l) - l = [x*R for x in l] - - dist.val = l[0] - bevel_update() - - for x in l[1:]: - dist.val = x - bevel() - diff --git a/release/scripts/blenderLipSynchro.py b/release/scripts/blenderLipSynchro.py deleted file mode 100644 index c4815811512..00000000000 --- a/release/scripts/blenderLipSynchro.py +++ /dev/null @@ -1,729 +0,0 @@ -#!BPY -# coding: utf-8 -""" -Name: 'BlenderLipSynchro' -Blender: 242 -Group: 'Animation' -Tooltip: 'Import phonemes from Papagayo or JLipSync for lip synchronization' -""" - -__author__ = "Dienben: Benoit Foucque dienben_mail@yahoo.fr" -__url__ = ["blenderLipSynchro Blog, http://blenderlipsynchro.blogspot.com/", -"Papagayo (Python), http://www.lostmarble.com/papagayo/index.shtml", -"JLipSync (Java), http://jlipsync.sourceforge.net/"] -__version__ = "2.0" -__bpydoc__ = """\ -Description: - -This script imports Voice Export made by Papagayo or JLipSync and maps the export with your shapes. - -Usage: - -Import a Papagayo or JLipSync voice export file and link it with your shapes. - -Note:<br> -- Naturally, you need files exported from one of the supported lip synching -programs. Check their sites to learn more and download them. - -""" - -# -------------------------------------------------------------------------- -# BlenderLipSynchro -# -------------------------------------------------------------------------- -# ***** 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 ***** -# -------------------------------------------------------------------------- - - - -#il y a 3 etapes -#la deuxieme on charge le dictionnaire de correspondance -#la troisieme on fait le choix des correpondance -#la quatrieme on construit les cles a partir du fichiers frame - -#there are 3 stages -#the second one load the mapping dictionnary -#the tird make the mapping -#the fourth make the key in the IPO Curve - -#voici mes differents imports -#the imports -import os -import Blender - -from Blender import Ipo -from Blender.Draw import * -from Blender.BGL import * -from Blender.sys import basename - - - -#ici commencent mes fonctions -#here begin my functions -#cette fonction trace l'interface graphique -#this functions draw the User interface -def trace(): - #voici mes variables pouvant etre modifie - #my variables - global nbr_phoneme, mon_fichier_dico - global let01, let02, let03, let04,let05, let06, let07, let08, let09, let10 - global let11, let12, let13, let14,let15, let16, let17, let18, let19, let20 - global let21, let22, let23, let24 - - global let01selectkey,let02selectkey,let03selectkey,let04selectkey,let05selectkey - global let06selectkey,let07selectkey,let08selectkey,let09selectkey,let10selectkey,let11selectkey - global let12selectkey,let13selectkey,let14selectkey,let15selectkey,let16selectkey,let17selectkey - global let18selectkey,let19selectkey,let20selectkey,let21selectkey,let22selectkey,let23selectkey - global let24selectkey - - glClearColor(0.4,0.5,0.6 ,0.0) - glClear(GL_COLOR_BUFFER_BIT) - - glColor3d(1,1,1) - glRasterPos2i(87, 375) - Text("Blendersynchro V 2.0") - glColor3d(1,1,1) - glRasterPos2i(84, 360) - Text("Programming: Dienben") - - glColor3d(0,0,0) - glRasterPos2i(13, 342) - Text("Lip Synchronization Tool") - glColor3d(0,0,0) - glRasterPos2i(13, 326) - Text("Thanks to Chris Clawson and Liubomir Kovatchev") - - glColor3d(1,1,1) - glRasterPos2i(5, 320) - Text("_______________________________________________________") - glColor3d(0,0,0) - glRasterPos2i(6, 318) - Text("_______________________________________________________") - - - if (etape==1): - #cette etape permet de choisi la correspondance entre les phonemes et les cles - #this stage offer the possibility to choose the mapping between phonems and shapes - - glColor3d(1,1,1) - glRasterPos2i(140, 300) - Text("Objet: "+Blender.Object.GetSelected()[0].getName() ) - - glColor3d(1,1,1) - glRasterPos2i(5, 215) - Text("Assign phonems to shapes:") - - #on mesure la taille de la liste de phonemes - #this is the lenght of the phonem list - nbr_phoneme=len(liste_phoneme) - - #on dessine les listes de choix - #we draw the choice list - - # - if (nbr_phoneme > 0): - let01 = String(" ", 4, 5, 185, 30, 16, liste_phoneme[0], 3) - glColor3d(0,0,0) - glRasterPos2i(40, 188) - Text("=") - let01selectkey = Menu(key_menu, 50, 50, 185, 70, 16, let01selectkey.val) - - # - if (nbr_phoneme > 1): - let02 = String(" ", 4, 150, 185, 30, 16, liste_phoneme[1], 2) - glColor3d(0,0,0) - glRasterPos2i(185, 188) - Text("=") - let02selectkey = Menu(key_menu, 51, 195, 185, 70, 16, let02selectkey.val) - - # - if (nbr_phoneme > 2): - let03 = String(" ", 4, 5, 165, 30, 16, liste_phoneme[2], 2) - glColor3d(0,0,0) - glRasterPos2i(40, 168) - Text("=") - let03selectkey = Menu(key_menu, 52, 50, 165, 70, 16, let03selectkey.val) - - # - if (nbr_phoneme > 3): - let04 = String(" ", 4, 150, 165, 30, 16, liste_phoneme[3], 2) - glColor3d(0,0,0) - glRasterPos2i(185, 168) - Text("=") - let04selectkey = Menu(key_menu, 53, 195, 165, 70, 16, let04selectkey.val) - - # - if (nbr_phoneme > 4): - let05 = String(" ", 4, 5, 145, 30, 16, liste_phoneme[4], 2) - glColor3d(0,0,0) - glRasterPos2i(40, 148) - Text("=") - let05selectkey = Menu(key_menu, 54, 50, 145, 70, 16, let05selectkey.val) - - # - if (nbr_phoneme > 5): - let06 = String(" ", 4, 150, 145, 30, 16, liste_phoneme[5], 2) - glColor3d(0,0,0) - glRasterPos2i(185, 148) - Text("=") - let06selectkey = Menu(key_menu, 55, 195, 145, 70, 16, let06selectkey.val) - - # - if (nbr_phoneme > 6): - let07 = String(" ", 4, 5, 125, 30, 16, liste_phoneme[6], 2) - glColor3d(0,0,0) - glRasterPos2i(40, 128) - Text("=") - let07selectkey = Menu(key_menu, 56, 50, 125, 70, 16, let07selectkey.val) - - # - if (nbr_phoneme > 7): - let08 = String(" ", 4, 150, 125, 30, 16, liste_phoneme[7], 2) - glColor3d(0,0,0) - glRasterPos2i(185, 128) - Text("=") - let08selectkey = Menu(key_menu, 57, 195, 125, 70, 16,let08selectkey.val) - - # - if (nbr_phoneme > 8): - let09 = String(" ", 4, 5, 105, 30, 16, liste_phoneme[8], 2) - glColor3d(0,0,0) - glRasterPos2i(40, 108) - Text("=") - let09selectkey = Menu(key_menu, 58, 50, 105, 70, 16,let09selectkey.val) - - # - if (nbr_phoneme > 9): - let10 = String(" ", 4, 150, 105, 30, 16, liste_phoneme[9], 2) - glColor3d(0,0,0) - glRasterPos2i(185, 108) - Text("=") - let10selectkey = Menu(key_menu, 59, 195, 105, 70, 16, let10selectkey.val) - - # - if (nbr_phoneme > 10): - let11 = String(" ", 4, 5, 85, 30, 16, liste_phoneme[10], 2) - glColor3d(0,0,0) - glRasterPos2i(40, 88) - Text("=") - let11selectkey = Menu(key_menu, 60, 50, 85, 70, 16, let11selectkey.val) - - # - if (nbr_phoneme > 11): - let12 = String(" ", 4, 150, 85, 30, 16, liste_phoneme[11], 2) - glColor3d(0,0,0) - Text("=") - let12selectkey = Menu(key_menu, 61, 195, 85, 70, 16, let12selectkey.val) - - # - if (nbr_phoneme > 12): - let13 = String(" ", 4, 5, 65, 30, 16, liste_phoneme[12], 2) - glColor3d(0,0,0) - glRasterPos2i(40, 68) - Text("=") - let13selectkey = Menu(key_menu, 62, 50, 65, 70, 16, let13selectkey.val) - - # - if (nbr_phoneme > 13): - let14 = String(" ", 4, 150, 65, 30, 16, liste_phoneme[13], 2) - glColor3d(0,0,0) - glRasterPos2i(185, 68) - Text("=") - let14selectkey = Menu(key_menu, 63, 195, 65, 70, 16, let14selectkey.val) - - # - if (nbr_phoneme > 14): - let15 = String(" ", 4, 5, 45, 30, 16, liste_phoneme[14], 2) - glColor3d(0,0,0) - glRasterPos2i(40, 48) - Text("=") - let15selectkey = Menu(key_menu, 64, 50, 45, 70, 16, let15selectkey.val) - - # - if (nbr_phoneme > 15): - let16 = String(" ", 4, 150, 45, 30, 16, liste_phoneme[15], 2) - glColor3d(0,0,0) - glRasterPos2i(185, 48) - Text("=") - let16selectkey = Menu(key_menu, 65, 195, 45, 70, 16, let16selectkey.val) - - # - if (nbr_phoneme > 16): - let17 = String(" ", 4, 295, 185, 30, 16, liste_phoneme[16], 2) - glColor3d(0,0,0) - glRasterPos2i(330, 188) - Text("=") - let17selectkey = Menu(key_menu, 66, 340, 185, 70, 16, let17selectkey.val) - - # - if (nbr_phoneme > 17): - let18 = String(" ", 4, 440, 185, 70, 16, liste_phoneme[17], 8) - glColor3d(0,0,0) - glRasterPos2i(515, 188) - Text("=") - let18selectkey = Menu(key_menu, 67, 525, 185, 70, 16, let18selectkey.val) - - # - if (nbr_phoneme > 18): - let19 = String(" ", 4, 295, 165, 30, 16, liste_phoneme[18], 2) - glColor3d(0,0,0) - glRasterPos2i(330, 168) - Text("=") - let19selectkey = Menu(key_menu, 68, 340, 165, 70, 16, let19selectkey.val) - - # - if (nbr_phoneme > 19): - let20 = String(" ", 4, 440, 165, 70, 16, liste_phoneme[19], 8) - glColor3d(0,0,0) - glRasterPos2i(515, 168) - Text("=") - let20selectkey = Menu(key_menu, 69, 525, 165, 70, 16, let20selectkey.val) - - # - if (nbr_phoneme > 20): - let21 = String(" ", 4, 295, 145, 30, 16, liste_phoneme[20], 2) - glColor3d(0,0,0) - glRasterPos2i(330, 148) - Text("=") - let21selectkey = Menu(key_menu, 70, 340, 145, 70, 16, let21selectkey.val) - - # - if (nbr_phoneme > 21): - let22 = String(" ", 4, 440, 145, 70, 16, liste_phoneme[21], 8) - glColor3d(0,0,0) - glRasterPos2i(515, 148) - Text("=") - let22selectkey = Menu(key_menu, 71, 525, 145, 70, 16, let22selectkey.val) - - # - if (nbr_phoneme > 22): - let23 = String(" ", 4, 295, 125, 30, 16, liste_phoneme[22], 2) - glColor3d(0,0,0) - glRasterPos2i(330, 128) - Text("=") - let23selectkey = Menu(key_menu, 72, 340, 125, 70, 16,let23selectkey.val) - - # - if (nbr_phoneme > 23): - let24 = String(" ", 4, 440, 125, 70, 16, liste_phoneme[23], 8) - glColor3d(0,0,0) - glRasterPos2i(515, 128) - Text("=") - let24selectkey = Menu(key_menu, 73, 525, 125, 70, 16, let24selectkey.val) - - # - if (nbr_phoneme > 24): - let25 = String(" ", 4, 295, 105, 30, 16, liste_phoneme[24], 2) - glColor3d(0,0,0) - glRasterPos2i(330, 108) - Text("=") - let25selectkey = Menu(key_menu, 74, 340, 105, 70, 16, let25selectkey.val) - - # - if (nbr_phoneme > 25): - let26 = String(" ", 4, 440, 105, 70, 16, liste_phoneme[25], 8) - glColor3d(0,0,0) - glRasterPos2i(515, 108) - Text("=") - let26selectkey = Menu(key_menu, 75, 525, 105, 70, 16,let26selectkey.val) - - # - if (nbr_phoneme > 26): - let27 = String(" ", 4, 295, 85, 30, 16, liste_phoneme[26], 2) - glColor3d(0,0,0) - glRasterPos2i(330, 88) - Text("=") - let27selectkey = Menu(key_menu, 76, 340, 85, 70, 16, let27selectkey.val) - - # - if (nbr_phoneme > 27): - let28 = String(" ", 4, 440, 85, 70, 16, liste_phoneme[27], 8) - glColor3d(0,0,0) - glRasterPos2i(515, 88) - Text("=") - let28selectkey = Menu(key_menu, 77, 525, 85, 70, 16,let28selectkey.val) - - # - if (nbr_phoneme > 28): - let29 = String(" ", 4, 295, 65, 30, 16, liste_phoneme[28], 2) - glColor3d(0,0,0) - glRasterPos2i(330, 68) - Text("=") - let29selectkey = Menu(key_menu, 78, 340, 65, 70, 16, let29selectkey.val) - - # - if (nbr_phoneme > 29): - let30 = String(" ", 4, 440, 65, 70, 16, liste_phoneme[29], 8) - glColor3d(0,0,0) - glRasterPos2i(515, 68) - Text("=") - let30selectkey = Menu(key_menu, 79, 525, 65, 70, 16, let30selectkey.val) - - # - if (nbr_phoneme > 30): - let31 = String(" ", 4, 295, 45, 30, 16, liste_phoneme[30], 2) - glColor3d(0,0,0) - glRasterPos2i(330, 48) - Text("=") - let31selectkey = Menu(key_menu, 80, 340, 45, 70, 16, let31selectkey.val) - - # - if (nbr_phoneme > 31): - let32 = String(" ", 4, 440, 45, 70, 16, liste_phoneme[31], 8) - glColor3d(0,0,0) - glRasterPos2i(515, 48) - Text("=") - let32selectkey = Menu(key_menu, 81, 525, 45, 70, 16, let32selectkey.val) - - Button("Go", 3, 155, 5, 145, 22) - - if (etape==2): - glColor3d(1,1,1) - glRasterPos2i(125, 200) - Text("Operation Completed") - - if (etape==0): - glColor3d(1,1,1) - glRasterPos2i(125, 200) - Text("Please select a Mesh'Object and Create all the IPO Curves for your Shapes") - - if (etape==3): - #this stage permits to load a custom dictionnary - load_file_text = "Load File" - if mon_fichier_dico: - Button("Import Loaded File", 2, 5, 5, 145, 22) - glColor3d(1,1,1) - glRasterPos2i(6, 50) - Text("loaded file: %s" % basename(mon_fichier_dico)) - load_file_text = "Choose Another File" - Button(load_file_text, 8, 125, 180, 145, 22) - - glRasterPos2i(6, 40) - Text("_______________________________________________________") - glColor3d(0,0,0) - glRasterPos2i(6, 38) - Text("_______________________________________________________") - - Button("Exit", 1, 305, 5, 80, 22) - - - -#cette fonction sur evenement quite en cas d'ESC -#this functions catch the ESC event and quit -def event(evt,val): - if (evt == ESCKEY and not val): Exit() - -#cette fonction gere les evenements -#the event functions -def bevent(evt): - global etape,soft_type,liste_phoneme,dico_phoneme_export - - if (evt == 1): - Exit() - - elif (evt == 2): - #c'est l'import du dictionnaire - #we create and import the dictionnary - lecture_chaine(mon_fichier_dico,dico_phoneme_export) - construction_dictionnaire_phoneme() - #we change the stage - etape=1 - - elif (evt == 3): - #c'est l'import - #we import - lecture_chaine(mon_fichier_export,dico_phoneme_export) - construction_dico_correspondance() - construction_lipsynchro() - #on change d'etape - #we change the stage - etape=2 - - elif (evt == 8): - #we choose the file - Blender.Window.FileSelector(selectionner_fichier,"Select File") - - Blender.Redraw() - -#cette fonction recupere le nom et le chemin du fichier dictionnaire -#we catch the name and the path of the dictionnary -def selectionner_fichier(filename): - global mon_fichier_dico,mon_fichier_export - mon_fichier_dico=filename - mon_fichier_export=filename - -#fonction de lecture de la liste frame phoneme -#we read the frame and phonems -def lecture_chaine(fichier,liste): - mon_fichier=open(fichier) - #je lis la premiere ligne qui contiens la version de moho - #first, we read the moho version - mon_fichier.readline() - - #je lis jusqu'a la fin - #then we read until the end of the file - while 1: - ma_ligne=mon_fichier.readline() - if ma_ligne=='': - break - decoup=ma_ligne.split() - liste[decoup[0]]=decoup[1] - print liste - - - - -#fonction qui construit la liste dictionnaire simple -#we make the dictionnary -def construction_dictionnaire_phoneme(): - global liste_phoneme - index_liste=0 - #je transforme mon dictionnaire en list de tulpes - #we transform the list in tulpes - ma_liste=dico_phoneme_export.items() - #je parcours ma liste a la recherche d'elements non existant - #we read the list to find non existing elements - print dico_phoneme - for index in range(len(ma_liste)): - if ma_liste[index][1] not in liste_phoneme: - liste_phoneme[index_liste:index_liste]=[ma_liste[index][1]] - index_liste=index_liste+1 - print liste_phoneme - - -#cette fonction recupere les courbes cible -#this functon catch the IPO curve -def recuperation_courbe(): - global key_menu,dico_key - - #on recupere le nom des shapes - #we catch the shapes - key=Blender.Object.GetSelected()[0].getData().getKey().getBlocks() - for n in range(len(key)): - #on vire la première cle (en effet basic n'est pas une cle en tant que telle) - #we threw away the basic shapes - if (n>0): - key_menu=key_menu+key[n].name + " %x" + str(n-1) + "|" - dico_key[str(n-1)]=Blender.Object.GetSelected()[0].getData().getKey().getIpo().getCurves()[n-1] - - - print "dico_key" - print dico_key - print 'end dico_key' - -#cette fonction construit un dictionnaire de correspondance entre les phonemes prononces et les cles a utiliser -#we make the dictionnary for the mapping between shapes and phonems -def construction_dico_correspondance(): - global dico_correspondance - #je parcours les phonemes - #we read the phonems - if (nbr_phoneme>0): - dico_correspondance[liste_phoneme[0]]=dico_key[str(let01selectkey.val)] - if (nbr_phoneme>1): - dico_correspondance[liste_phoneme[1]]=dico_key[str(let02selectkey.val)] - if (nbr_phoneme>2): - dico_correspondance[liste_phoneme[2]]=dico_key[str(let03selectkey.val)] - if (nbr_phoneme>3): - dico_correspondance[liste_phoneme[3]]=dico_key[str(let04selectkey.val)] - if (nbr_phoneme>4): - dico_correspondance[liste_phoneme[4]]=dico_key[str(let05selectkey.val)] - if (nbr_phoneme>5): - dico_correspondance[liste_phoneme[5]]=dico_key[str(let06selectkey.val)] - if (nbr_phoneme>6): - dico_correspondance[liste_phoneme[6]]=dico_key[str(let07selectkey.val)] - if (nbr_phoneme>7): - dico_correspondance[liste_phoneme[7]]=dico_key[str(let08selectkey.val)] - if (nbr_phoneme>8): - dico_correspondance[liste_phoneme[8]]=dico_key[str(let09selectkey.val)] - if (nbr_phoneme>9): - dico_correspondance[liste_phoneme[9]]=dico_key[str(let10selectkey.val)] - if (nbr_phoneme>10): - dico_correspondance[liste_phoneme[10]]=dico_key[str(let11selectkey.val)] - if (nbr_phoneme>11): - dico_correspondance[liste_phoneme[11]]=dico_key[str(let12selectkey.val)] - if (nbr_phoneme>12): - dico_correspondance[liste_phoneme[12]]=dico_key[str(let13selectkey.val)] - if (nbr_phoneme>13): - dico_correspondance[liste_phoneme[13]]=dico_key[str(let14selectkey.val)] - if (nbr_phoneme>14): - dico_correspondance[liste_phoneme[14]]=dico_key[str(let15selectkey.val)] - if (nbr_phoneme>15): - dico_correspondance[liste_phoneme[15]]=dico_key[str(let16selectkey.val)] - if (nbr_phoneme>16): - dico_correspondance[liste_phoneme[16]]=dico_key[str(let17selectkey.val)] - if (nbr_phoneme>17): - dico_correspondance[liste_phoneme[17]]=dico_key[str(let18selectkey.val)] - if (nbr_phoneme>18): - dico_correspondance[liste_phoneme[18]]=dico_key[str(let19selectkey.val)] - if (nbr_phoneme>19): - dico_correspondance[liste_phoneme[19]]=dico_key[str(let20selectkey.val)] - if (nbr_phoneme>20): - dico_correspondance[liste_phoneme[20]]=dico_key[str(let21selectkey.val)] - if (nbr_phoneme>21): - dico_correspondance[liste_phoneme[21]]=dico_key[str(let22selectkey.val)] - if (nbr_phoneme>22): - dico_correspondance[liste_phoneme[22]]=dico_key[str(let23selectkey.val)] - if (nbr_phoneme>23): - dico_correspondance[liste_phoneme[23]]=dico_key[str(let24selectkey.val)] - if (nbr_phoneme>24): - dico_correspondance[liste_phoneme[24]]=dico_key[str(let25selectkey.val)] - if (nbr_phoneme>25): - dico_correspondance[liste_phoneme[25]]=dico_key[str(let26selectkey.val)] - if (nbr_phoneme>26): - dico_correspondance[liste_phoneme[26]]=dico_key[str(let27selectkey.val)] - if (nbr_phoneme>27): - dico_correspondance[liste_phoneme[27]]=dico_key[str(let28selectkey.val)] - if (nbr_phoneme>28): - dico_correspondance[liste_phoneme[28]]=dico_key[str(let29selectkey.val)] - if (nbr_phoneme>29): - dico_correspondance[liste_phoneme[29]]=dico_key[str(let30selectkey.val)] - if (nbr_phoneme>30): - dico_correspondance[liste_phoneme[30]]=dico_key[str(let31selectkey.val)] - if (nbr_phoneme>31): - dico_correspondance[liste_phoneme[31]]=dico_key[str(let32selectkey.val)] - - print dico_correspondance - - -#cette fonction ajoute un points a la cle donnee a la frame donnee -#we add a point to the IPO curve Target -def ajoute_point(cle,frame,valeur): - cle.setInterpolation('Linear') - cle.append((frame,valeur)) - cle.Recalc() - -#cette fonction parcours le dictionnaire des frame à ajouter et construit les points -#we add all the point to the IPO Curve -def construction_lipsynchro(): - print "je construit" - doublet_old="" - #construction de la liste des frame - cpt=0 - liste_frame=[] - for frame in dico_phoneme_export: - liste_frame.append(int(frame)) - cpt=cpt+1 - liste_frame.sort() - print "listeframe" - print liste_frame - print "fini" - - for doublet in liste_frame: - ajoute_point(dico_correspondance[dico_phoneme_export[str(doublet)]],doublet,1) - if (doublet_old==""): - ajoute_point(dico_correspondance[dico_phoneme_export[str(doublet)]],(doublet-2),0) - if (doublet_old!=''): - if (dico_correspondance[dico_phoneme_export[str(doublet)]]!=dico_correspondance[dico_phoneme_export[doublet_old]]): - print "doublet:"+str(doublet) - print "doublet old:"+doublet_old - ajoute_point(dico_correspondance[dico_phoneme_export[doublet_old]],(int(doublet_old)+2),0) - ajoute_point(dico_correspondance[dico_phoneme_export[str(doublet)]],(doublet-2),0) - doublet_old=str(doublet) - - -#end of my functions we begin the execution -#je commence l execution----------------------------------------------------------------------------------------------- -#voici mes variables - -#declaration et instanciation -#decleration and instanciation - - -#voici mon objet de travail -objet_travail=Create(0) - -#my soft type -soft_type=1 - -#voici la liste des phoneme effectivement utilise -#the phonems'list -#liste_phoneme_papagayo=['AI','E','O','U','FV','L','WQ','MBP','etc','rest'] -#liste_phoneme_jlipsinch=['A','B','C','Closed','D','E','F','G','I','K','L','M','N','O','P','Q','R','S','SH','T','TH','U','V','W'] - -liste_phoneme=[] -#voici mon dictionnaire des frames o -dico_phoneme_export = Create(0) -dico_phoneme_export={} -dico_phoneme={} - - -#voici mes cle -key_menu="" -dico_key={} - -#voici mes ipo -dico_bloc={} -iponame = Create(0) - -#voici mon dictionnaire de correspondance -dico_correspondance={} - -try: - #on verifie est bien une mesh et qu'il a des courbes - if ((Blender.Object.GetSelected()[0].getType()=='Mesh')): - #on verifie que l'objet a bien toute ses Courbes - if (len(Blender.Object.GetSelected()[0].getData().getKey().getBlocks())-1==Blender.Object.GetSelected()[0].getData().getKey().getIpo().getNcurves()): - etape=3 - #on lance la creation du dictionnaire - recuperation_courbe() - else: - print "not the good number of IPO Curve" - etape = 0 - else: - print "error: bad object Type:" - print Blender.Object.GetSelected()[0].getType() - etape = 0 -except: - print 'error: exception' - etape = 0 - - -#voici le fichier dictionnaire -mon_fichier_dico="" - -#voici le fichier export pamela -mon_fichier_export="" - - -let01selectkey = Create(0) -let02selectkey = Create(0) -let03selectkey = Create(0) -let04selectkey = Create(0) -let05selectkey = Create(0) -let06selectkey = Create(0) -let07selectkey = Create(0) -let08selectkey = Create(0) -let09selectkey = Create(0) -let10selectkey = Create(0) -let11selectkey = Create(0) -let12selectkey = Create(0) -let13selectkey = Create(0) -let14selectkey = Create(0) -let15selectkey = Create(0) -let16selectkey = Create(0) -let17selectkey = Create(0) -let18selectkey = Create(0) -let19selectkey = Create(0) -let20selectkey = Create(0) -let21selectkey = Create(0) -let22selectkey = Create(0) -let23selectkey = Create(0) -let24selectkey = Create(0) - - -Register (trace,event,bevent) diff --git a/release/scripts/bpydata/KUlang.txt b/release/scripts/bpydata/KUlang.txt deleted file mode 100644 index 38605d69c9f..00000000000 --- a/release/scripts/bpydata/KUlang.txt +++ /dev/null @@ -1,121 +0,0 @@ -Version 3.233-2004 -****************** -Espanol -Sale del programa -Utilidades de...%t|Alinea objetos%x1|Creacion%x2|Edita mallas%x3|Edita objetos%x4 -11 -Mov -Esc -Encaja -Abarca -Separa -Alinea -Rota -Incr. -Crea nuevos objetos -Es+ -Es* -Separar entre:%t|Origenes%x1|Centros geometricos%x2|Minimos%x3|Maximos%x4|Baricentro%x5|Objetos%x6 -Crear%t|Arco (3 ptos.)%x1|Arco (interactivo)%x2|Circunferencia (3 ptos.)%x3 -12 -Puntos -Centro -Orden -Objeto -AngIni: -AngFin: -Angulo: -Radio: -Puntos: -Centro -Nombre: -Puntos -Modifica vertices%t|Subdivide%x1|Envia a un plano%x2|Aplica LocRotSize%x3 -Partes -Proyectar en el plano:%t|Coordenado global...%x1|Coordenado local...%x2 -Actuar sobre el plano%t|Yz%x1|Zx%x2|Xy%x3 -En la dirección%t|X%x1|Y%x2|Z%x3|Ortogonal al plano%x4 -Captura -Buffer%t|Copia vector diferencia%x1|Copia distancia%x2|Copia diferencia de rotacion%x3|Copia media LocRotSiz%x4|Ver buffer en consola%x5 -Transformar LocRotSize%t|Hacia el obj. activo%x1|Aleatoriamente%x2 -Poner a distancia fija%x1|Sumar (desp. absoluto)%x2|Multiplicar (desp. relativo)%x3 -******************** -English -Exit program -Utils about:%t|Align Objects%x1|Create%x2|Edit Meshes%x3|Edit Objects%x4 -11 -Mov -Sca -Fit -Embrace -Separate -Align -Rota -Incr. -Create new objects -Sc+ -Sc* -Separate between:%t|Origins%x1|Geometric centers%x2|Minimum%x3|Maximum%x4|Baricenter%x5|Objects%x6 -Create what%t|Arc (3 pts.)%x1|Arc (interactive)%x2|Circunference (3 pts.)%x3 -12 -Points -Centre -Sort -Object -AngIni: -AngEnd: -Angle: -Radius: -Points: -Centre -ObjName: -Points -Modify vertices%t|Subdivide edges%x1|Send to a plane%x2|Set LocRotSize%x3 -Parts -Project onto the plane:%t|Global coordinated...%x1|Local coordinated...%x2 -Act on plane%t|Yz%x1|Zx%x2|Xy%x3 -In direction%t|X%x1|Y%x2|Z%x3|Ortogonal to plane%x4 -Get -Buffer%t|Copy diference vector%x1|Copy distance%x2|Copy rot diference%x3|Copy LocRotSiz average%x4|Show Buffer in Console%x5 -Transform LocRotSize%t|Close to active%x1|Randomly%x2 -Set at fixed distance%x1|Add (absolute displ.)%x2|Multiply (relative displ.)%x3 -******************** -Catala -Surt del programa -Utilitats de...%t|Alinea objectes%x1|Creacio%x2|Edita malles%x3|Edita objetes%x4 -11 -Mov -Esc -Encaixa -Abarca -Separa -Alinea -Rotacio -Incr. -Crea objectes nous -Es+ -Es* -Separa entra:%t|Origens%x1|Centres geometrics%x2|Minims%x3|Maxims%x4|Baricentre%x5|Objectes%x6 -Crear%t|Arc (3 pts.)%x1|Arc (interactiu)%x2|Circumferencia (3 pts.)%x3 -12 -Punts -Centre -Ordre -Objecte -AngIni: -AngFi: -Angle: -Radi: -Punts: -Centre -Nom: -Punts -Modifica vertex%t|Subdivideix%x1|Envia a un pla%x2|Aplica LocRotSize%x3 -Parts -Projectar en el pla:%t|Coordenacio global...%x1|Coordenacio local...%x2 -Actuar sobre el pla%t|Yz%x1|Zx%x2|Xy%x3 -En la direccio%t|X%x1|Y%x2|Z%x3|Ortogonal al pla%x4 -Captura -Buffer%t|Copia vector diferencia%x1|Copia distancia%x2|Copia diferencia de rotacio%x3|Copia mitjana LocRotSiz%x4|Veure buffer en consola%x5 -Transformar LocRotSize%t|Cap al obj. actiu%x1|Aleatoriamente%x2 -Posar a distancia fixa%x1|Sumar (desp. absolut)%x2|Multiplicar (desp. relatiu)%x3 diff --git a/release/scripts/bpydata/config/readme.txt b/release/scripts/bpydata/config/readme.txt deleted file mode 100644 index 4b5cb61b063..00000000000 --- a/release/scripts/bpydata/config/readme.txt +++ /dev/null @@ -1,6 +0,0 @@ -This folder is for automatically saved scripts configuration data. - -To use this feature scripts just need to set a proper Blender.Registry key. - -To know more, check the API Reference doc (specifically the API_related and -Registry parts) and the documentation for the "Scripts Config Editor" script. diff --git a/release/scripts/bpydata/readme.txt b/release/scripts/bpydata/readme.txt deleted file mode 100644 index 3e640e27c4b..00000000000 --- a/release/scripts/bpydata/readme.txt +++ /dev/null @@ -1,9 +0,0 @@ -This directory is the default place for scripts to put their data, -like internal files needed by the script and its saved configuration. - -Scripts can find the path to this dir using Blender.Get("datadir"). -Ex: - -import Blender -print Blender.Get("datadir") - diff --git a/release/scripts/bpymodules/BPyAddMesh.py b/release/scripts/bpymodules/BPyAddMesh.py deleted file mode 100644 index 901e68866cc..00000000000 --- a/release/scripts/bpymodules/BPyAddMesh.py +++ /dev/null @@ -1,159 +0,0 @@ -import Blender -from Blender.Window import EditMode, GetCursorPos, GetViewQuat -import bpy -import BPyMessages - -def add_mesh_simple(name, verts, edges, faces): - ''' - Adds a mesh from verts, edges and faces - - name - new object/mesh name - verts - list of 3d vectors - edges - list of int pairs - faces - list of int triplets/quads - ''' - - scn = bpy.data.scenes.active - if scn.lib: return - ob_act = scn.objects.active - - is_editmode = EditMode() - - cursor = GetCursorPos() - quat = None - if is_editmode or Blender.Get('add_view_align'): # Aligning seems odd for editmode, but blender does it, oh well - try: quat = Blender.Mathutils.Quaternion(GetViewQuat()) - except: pass - - # Exist editmode for non mesh types - if ob_act and ob_act.type != 'Mesh' and is_editmode: - EditMode(0) - - # We are in mesh editmode - if EditMode(): - me = ob_act.getData(mesh=1) - - if me.multires: - BPyMessages.Error_NoMeshMultiresEdit() - return - - # Add to existing mesh - # must exit editmode to modify mesh - EditMode(0) - - me.sel = False - - vert_offset = len(me.verts) - edge_offset = len(me.edges) - face_offset = len(me.faces) - - # transform the verts - txmat = Blender.Mathutils.TranslationMatrix(Blender.Mathutils.Vector(cursor)) - if quat: - mat = quat.toMatrix() - mat.invert() - mat.resize4x4() - txmat = mat * txmat - - txmat = txmat * ob_act.matrixWorld.copy().invert() - - - me.verts.extend(verts) - # Transform the verts by the cursor and view rotation - me.transform(txmat, selected_only=True) - - if vert_offset: - me.edges.extend([[i+vert_offset for i in e] for e in edges]) - me.faces.extend([[i+vert_offset for i in f] for f in faces]) - else: - # Mesh with no data, unlikely - me.edges.extend(edges) - me.faces.extend(faces) - else: - - # Object mode add new - - me = bpy.data.meshes.new(name) - me.verts.extend(verts) - me.edges.extend(edges) - me.faces.extend(faces) - me.sel = True - - # Object creation and location - scn.objects.selected = [] - ob_act = scn.objects.new(me, name) - scn.objects.active = ob_act - - if quat: - mat = quat.toMatrix() - mat.invert() - mat.resize4x4() - ob_act.setMatrix(mat) - - ob_act.loc = cursor - - me.calcNormals() - - if is_editmode or Blender.Get('add_editmode'): - EditMode(1) - - - - - -def write_mesh_script(filepath, me): - ''' - filepath - path to py file - me - mesh to write - ''' - - name = me.name - file = open(filepath, 'w') - - file.write('#!BPY\n') - file.write('"""\n') - file.write('Name: \'%s\'\n' % name) - file.write('Blender: 245\n') - file.write('Group: \'AddMesh\'\n') - file.write('"""\n\n') - file.write('import BPyAddMesh\n') - file.write('from Blender.Mathutils import Vector\n\n') - - file.write('verts = [\\\n') - for v in me.verts: - file.write('Vector(%f,%f,%f),\\\n' % tuple(v.co)) - file.write(']\n') - - file.write('edges = []\n') # TODO, write loose edges - - file.write('faces = [\\\n') - for f in me.faces: - file.write('%s,\\\n' % str(tuple([v.index for v in f]))) - file.write(']\n') - - file.write('BPyAddMesh.add_mesh_simple("%s", verts, edges, faces)\n' % name) - -# The script below can make a file from a mesh with teh above function... -''' -#!BPY -""" -Name: 'Mesh as AddMesh Script' -Blender: 242 -Group: 'Mesh' -Tip: '' -""" -import BPyAddMesh -reload(BPyAddMesh) - -import bpy - -def main(): - # Add error checking - scn = bpy.data.scenes.active - ob = scn.objects.active - me = ob.getData(mesh=1) - - BPyAddMesh.write_mesh_script('/test.py', me) - -main() -''' diff --git a/release/scripts/bpymodules/BPyArmature.py b/release/scripts/bpymodules/BPyArmature.py deleted file mode 100644 index 63df02d080c..00000000000 --- a/release/scripts/bpymodules/BPyArmature.py +++ /dev/null @@ -1,152 +0,0 @@ -# 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 -# Version History: -# 1.0 original release bakes an armature into a matrix -# 1.1 optional params (ACTION_BAKE, ACTION_BAKE_FIRST_FRAME, direct function to key and return the Action - -import Blender -from Blender import sys -import bpy -def getBakedPoseData(ob_arm, start_frame, end_frame, ACTION_BAKE = False, ACTION_BAKE_FIRST_FRAME = True): - ''' - If you are currently getting IPO's this function can be used to - ACTION_BAKE==False: return a list of frame aligned bone dictionary's - ACTION_BAKE==True: return an action with keys aligned to bone constrained movement - if ACTION_BAKE_FIRST_FRAME is not supplied or is true: keys begin at frame 1 - - The data in these can be swaped in for the IPO loc and quat - - If you want to bake an action, this is not as hard and the ipo hack can be removed. - ''' - - # --------------------------------- Dummy Action! Only for this functon - backup_action = ob_arm.action - backup_frame = Blender.Get('curframe') - - DUMMY_ACTION_NAME = '~DONT_USE~' - # Get the dummy action if it has no users - try: - new_action = bpy.data.actions[DUMMY_ACTION_NAME] - if new_action.users: - new_action = None - except: - new_action = None - - if not new_action: - new_action = bpy.data.actions.new(DUMMY_ACTION_NAME) - new_action.fakeUser = False - # ---------------------------------- Done - - Matrix = Blender.Mathutils.Matrix - Quaternion = Blender.Mathutils.Quaternion - Vector = Blender.Mathutils.Vector - POSE_XFORM= [Blender.Object.Pose.LOC, Blender.Object.Pose.ROT] - - # Each dict a frame - bake_data = [{} for i in xrange(1+end_frame-start_frame)] - - pose= ob_arm.getPose() - armature_data= ob_arm.getData(); - pose_bones= pose.bones - - # --------------------------------- Build a list of arma data for reuse - armature_bone_data = [] - bones_index = {} - for bone_name, rest_bone in armature_data.bones.items(): - pose_bone = pose_bones[bone_name] - rest_matrix = rest_bone.matrix['ARMATURESPACE'] - rest_matrix_inv = rest_matrix.copy().invert() - armature_bone_data.append( [len(bones_index), -1, bone_name, rest_bone, rest_matrix, rest_matrix_inv, pose_bone, None ]) - bones_index[bone_name] = len(bones_index) - - # Set the parent ID's - for bone_name, pose_bone in pose_bones.items(): - parent = pose_bone.parent - if parent: - bone_index= bones_index[bone_name] - parent_index= bones_index[parent.name] - armature_bone_data[ bone_index ][1]= parent_index - # ---------------------------------- Done - - - - # --------------------------------- Main loop to collect IPO data - frame_index = 0 - NvideoFrames= end_frame-start_frame - for current_frame in xrange(start_frame, end_frame+1): - if frame_index==0: start=sys.time() - elif frame_index==15: print NvideoFrames*(sys.time()-start),"seconds estimated..." #slows as it grows *3 - elif frame_index >15: - percom= frame_index*100/NvideoFrames - print "Frame %i Overall %i percent complete\r" % (current_frame, percom), - ob_arm.action = backup_action - #pose.update() # not needed - Blender.Set('curframe', current_frame) - #Blender.Window.RedrawAll() - #frame_data = bake_data[frame_index] - ob_arm.action = new_action - ###for i,pose_bone in enumerate(pose_bones): - - for index, parent_index, bone_name, rest_bone, rest_matrix, rest_matrix_inv, pose_bone, ipo in armature_bone_data: - matrix= pose_bone.poseMatrix - parent_bone= rest_bone.parent - if parent_index != -1: - parent_pose_matrix = armature_bone_data[parent_index][6].poseMatrix - parent_bone_matrix_inv = armature_bone_data[parent_index][5] - matrix= matrix * parent_pose_matrix.copy().invert() - rest_matrix= rest_matrix * parent_bone_matrix_inv - - matrix=matrix * rest_matrix.copy().invert() - pose_bone.quat= matrix.toQuat() - pose_bone.loc= matrix.translationPart() - if ACTION_BAKE==False: - pose_bone.insertKey(ob_arm, 1, POSE_XFORM) # always frame 1 - - # THIS IS A BAD HACK! IT SUCKS BIGTIME BUT THE RESULT ARE NICE - # - use a temp action and bake into that, always at the same frame - # so as not to make big IPO's, then collect the result from the IPOs - - # Now get the data from the IPOs - if not ipo: ipo = armature_bone_data[index][7] = new_action.getChannelIpo(bone_name) - - loc = Vector() - quat = Quaternion() - - for curve in ipo: - val = curve.evaluate(1) - curve_name= curve.name - if curve_name == 'LocX': loc[0] = val - elif curve_name == 'LocY': loc[1] = val - elif curve_name == 'LocZ': loc[2] = val - elif curve_name == 'QuatW': quat[3] = val - elif curve_name == 'QuatX': quat[0] = val - elif curve_name == 'QuatY': quat[1] = val - elif curve_name == 'QuatZ': quat[2] = val - - bake_data[frame_index][bone_name] = loc, quat - else: - if ACTION_BAKE_FIRST_FRAME: pose_bone.insertKey(ob_arm, frame_index+1, POSE_XFORM) - else: pose_bone.insertKey(ob_arm, current_frame , POSE_XFORM) - frame_index+=1 - print "\nBaking Complete." - ob_arm.action = backup_action - if ACTION_BAKE==False: - Blender.Set('curframe', backup_frame) - return bake_data - elif ACTION_BAKE==True: - return new_action - else: print "ERROR: Invalid ACTION_BAKE %i sent to BPyArmature" % ACTION_BAKE - - - diff --git a/release/scripts/bpymodules/BPyBlender.py b/release/scripts/bpymodules/BPyBlender.py deleted file mode 100644 index 681dff63cf8..00000000000 --- a/release/scripts/bpymodules/BPyBlender.py +++ /dev/null @@ -1,36 +0,0 @@ -# $Id$ -# -# -------------------------------------------------------------------------- -# BPyBlender.py version 0.3 Mar 20, 2005 -# -------------------------------------------------------------------------- -# helper functions to be used by other scripts -# -------------------------------------------------------------------------- -# ***** 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 ***** -# -------------------------------------------------------------------------- - -# Basic set of modules Blender should have in all supported platforms. -# The second and third lines are the contents of the Python23.zip file -# included with Windows Blender binaries along with zlib.pyd. -# Other platforms are assumed to have Python installed. -basic_modules = [ -'Blender', -'chunk','colorsys','copy','copy_reg','gzip','os','random','repr','stat', -'string','StringIO','types','UserDict','webbrowser', 'zlib', 'math', -'BPyBlender', 'BPyRegistry' -] diff --git a/release/scripts/bpymodules/BPyCurve.py b/release/scripts/bpymodules/BPyCurve.py deleted file mode 100644 index 3dd5f1784f2..00000000000 --- a/release/scripts/bpymodules/BPyCurve.py +++ /dev/null @@ -1,79 +0,0 @@ -# -------------------------------------------------------------------------- -# BPyImage.py version 0.15 -# -------------------------------------------------------------------------- -# helper functions to be used by other scripts -# -------------------------------------------------------------------------- -# ***** 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 ***** -# -------------------------------------------------------------------------- - -from Blender import * - -def curve2vecs(ob, WORLDSPACE= True): - ''' - Takes a curve object and retuirns a list of vec lists (polylines) - one list per curve - - This is usefull as a way to get a polyline per curve - so as not to have to deal with the spline types directly - ''' - if ob.type != 'Curve': - raise 'must be a curve object' - - me_dummy = Mesh.New() - me_dummy.getFromObject(ob) - - if WORLDSPACE: - me_dummy.transform(ob.matrixWorld) - - # build an edge dict - edges = {} # should be a set - - def sort_pair(i1, i2): - if i1 > i2: return i2, i1 - else: return i1, i2 - - for ed in me_dummy.edges: - edges[sort_pair(ed.v1.index,ed.v2.index)] = None # dummy value - - # now set the curves - first_time = True - - current_vecs = [] - vec_list = [current_vecs] - - for v in me_dummy.verts: - if first_time: - first_time = False - current_vecs.append(v.co.copy()) - last_index = v.index - else: - index = v.index - if edges.has_key(sort_pair(index, last_index)): - current_vecs.append( v.co.copy() ) - else: - current_vecs = [] - vec_list.append(current_vecs) - - last_index = index - - me_dummy.verts = None - - return vec_list - - diff --git a/release/scripts/bpymodules/BPyImage.py b/release/scripts/bpymodules/BPyImage.py deleted file mode 100644 index 504e4ee29ba..00000000000 --- a/release/scripts/bpymodules/BPyImage.py +++ /dev/null @@ -1,318 +0,0 @@ -# -------------------------------------------------------------------------- -# BPyImage.py version 0.15 -# -------------------------------------------------------------------------- -# helper functions to be used by other scripts -# -------------------------------------------------------------------------- -# ***** 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 ***** -# -------------------------------------------------------------------------- - -#===========================================================================# -# Comprehensive image loader, will search and find the image # -# Will return a blender image or a new image if the image is missing # -#===========================================================================# -import bpy -from Blender import sys -try: - import os -except: - os=None - -#==============================================# -# Return directory, where the file is # -#==============================================# -def stripFile(path): - lastSlash = max(path.rfind('\\'), path.rfind('/')) - if lastSlash != -1: - path = path[:lastSlash] - newpath= '%s%s' % (path, sys.sep) - else: - newpath= path - return newpath - -#==============================================# -# Strips the slashes from the back of a string # -#==============================================# -def stripPath(path): - return path.split('/')[-1].split('\\')[-1] - -#====================================================# -# Strips the prefix off the name before writing # -#====================================================# -def stripExt(name): # name is a string - index = name.rfind('.') - if index != -1: - return name[ : index ] - else: - return name - -def getExt(name): - index = name.rfind('.') - if index != -1: - return name[index+1:] - return name - -#====================================================# -# Adds a slash to the end of a path if its not there # -#====================================================# -def addSlash(path): - if not path: - return '' - - elif path.endswith('\\') or path.endswith('/'): - return path - return path + sys.sep - - -def comprehensiveImageLoad(imagePath, filePath, PLACE_HOLDER= True, RECURSIVE=True, VERBOSE=False, CONVERT_CALLBACK=None): - ''' - imagePath: The image filename - If a path precedes it, this will be searched as well. - - filePath: is the directory where the image may be located - any file at teh end will be ignored. - - PLACE_HOLDER: if True a new place holder image will be created. - this is usefull so later you can relink the image to its original data. - - VERBOSE: If True debug info will be printed. - - RECURSIVE: If True, directories will be recursivly searched. - Be carefull with this if you have files in your root directory because it may take a long time. - - CASE_INSENSITIVE: for non win32 systems, find the correct case for the file. - - CONVERT_CALLBACK: a function that takes an existing path and returns a new one. - Use this when loading image formats blender may not support, the CONVERT_CALLBACK - can take the path for a GIF (for example), convert it to a PNG and return the PNG's path. - For formats blender can read, simply return the path that is given. - ''' - - # VERBOSE = True - - if VERBOSE: print 'img:', imagePath, 'file:', filePath - - if os == None and CASE_INSENSITIVE: - CASE_INSENSITIVE = True - - # When we have the file load it with this. try/except niceness. - def imageLoad(path): - #if path.endswith('\\') or path.endswith('/'): - # raise 'INVALID PATH' - - if CONVERT_CALLBACK: - path = CONVERT_CALLBACK(path) - - try: - img = bpy.data.images.new(filename=path) - if VERBOSE: print '\t\tImage loaded "%s"' % path - return img - except: - if VERBOSE: - if sys.exists(path): print '\t\tImage failed loading "%s", mabe its not a format blender can read.' % (path) - else: print '\t\tImage not found, making a place holder "%s"' % (path) - if PLACE_HOLDER: - img= bpy.data.images.new(stripPath(path),4,4) - img.filename= path - return img #blank image - else: - return None - - # Image formats blender can read - IMAGE_EXT = ['jpg', 'jpeg', 'png', 'tga', 'bmp', 'rgb', 'sgi', 'bw', 'iff', 'lbm', # Blender Internal - 'gif', 'psd', 'tif', 'tiff', 'pct', 'pict', 'pntg', 'qtif'] # Quacktime, worth a try. - - imageFileName = stripPath(imagePath) # image path only - imageFileName_lower = imageFileName.lower() # image path only - - if VERBOSE: print '\tSearchingExisting Images for "%s"' % imagePath - for i in bpy.data.images: - if stripPath(i.filename.lower()) == imageFileName_lower: - if VERBOSE: print '\t\tUsing existing image.' - return i - - - if VERBOSE: print '\tAttempting to load "%s"' % imagePath - if sys.exists(imagePath): - if VERBOSE: print '\t\tFile found where expected "%s".' % imagePath - return imageLoad(imagePath) - - - - imageFileName_noext = stripExt(imageFileName) # With no extension. - imageFileName_noext_lower = stripExt(imageFileName_lower) # With no extension. - imageFilePath = stripFile(imagePath) - - # Remove relative path from image path - if imageFilePath.startswith('./') or imageFilePath.startswith('.\\'): - imageFilePath = imageFilePath[2:] - - - # Attempt to load from obj path. - tmpPath = stripFile(filePath) + stripPath(imageFileName) - if sys.exists(tmpPath): - if VERBOSE: print '\t\tFile found in path (1)"%s".' % tmpPath - return imageLoad(tmpPath) - - - # os needed if we go any further. - if not os: - if VERBOSE: print '\t\tCreating a placeholder with a face path: "%s".' % imagePath - return imageLoad(imagePath) # Will jus treturn a placeholder. - - - # We have os. - # GATHER PATHS. - paths = {} # Store possible paths we may use, dict for no doubles. - tmpPath = addSlash(sys.expandpath('//')) # Blenders path - if sys.exists(tmpPath): - if VERBOSE: print '\t\tSearching in %s' % tmpPath - paths[tmpPath] = [os.listdir(tmpPath)] # Orig name for loading - paths[tmpPath].append([f.lower() for f in paths[tmpPath][0]]) # Lower case list. - paths[tmpPath].append([stripExt(f) for f in paths[tmpPath][1]]) # Lower case no ext - else: - if VERBOSE: print '\tNo Path: "%s"' % tmpPath - - tmpPath = imageFilePath - if sys.exists(tmpPath): - if VERBOSE: print '\t\tSearching in %s' % tmpPath - paths[tmpPath] = [os.listdir(tmpPath)] # Orig name for loading - paths[tmpPath].append([f.lower() for f in paths[tmpPath][0]]) # Lower case list. - paths[tmpPath].append([stripExt(f) for f in paths[tmpPath][1]]) # Lower case no ext - else: - if VERBOSE: print '\tNo Path: "%s"' % tmpPath - - tmpPath = stripFile(filePath) - if sys.exists(tmpPath): - if VERBOSE: print '\t\tSearching in %s' % tmpPath - paths[tmpPath] = [os.listdir(tmpPath)] # Orig name for loading - paths[tmpPath].append([f.lower() for f in paths[tmpPath][0]]) # Lower case list. - paths[tmpPath].append([stripExt(f) for f in paths[tmpPath][1]]) # Lower case no ext - else: - if VERBOSE: print '\tNo Path: "%s"' % tmpPath - - tmpPath = addSlash(bpy.config.textureDir) - if tmpPath and sys.exists(tmpPath): - if VERBOSE: print '\t\tSearching in %s' % tmpPath - paths[tmpPath] = [os.listdir(tmpPath)] # Orig name for loading - paths[tmpPath].append([f.lower() for f in paths[tmpPath][0]]) # Lower case list. - paths[tmpPath].append([stripExt(f) for f in paths[tmpPath][1]]) # Lower case no ext - else: - if VERBOSE: print '\tNo Path: "%s"' % tmpPath - - # Add path if relative image patrh was given. - tmp_paths= paths.keys() - for k in tmp_paths: - tmpPath = k + imageFilePath - if sys.exists(tmpPath): - paths[tmpPath] = [os.listdir(tmpPath)] # Orig name for loading - paths[tmpPath].append([f.lower() for f in paths[tmpPath][0]]) # Lower case list. - paths[tmpPath].append([stripExt(f) for f in paths[tmpPath][1]]) # Lower case no ext - else: - if VERBOSE: print '\tNo Path: "%s"' % tmpPath - # DONE - # - for path, files in paths.iteritems(): - if sys.exists(path + imageFileName): - if VERBOSE: print '\tFound image at path: "%s" file" "%s"' % (path, imageFileName) - return imageLoad(path + imageFileName) - - # If the files not there then well do a case insensitive seek. - filesOrigCase = files[0] - filesLower = files[1] - filesLowerNoExt = files[2] - - # We are going to try in index the file directly, if its not there just keep on - - index = None - try: - # Is it just a case mismatch? - index = filesLower.index(imageFileName_lower) - except: - try: - # Have the extensions changed? - index = filesLowerNoExt.index(imageFileName_noext_lower) - - ext = getExt( filesLower[index] ) # Get the extension of the file that matches all but ext. - - # Check that the ext is useable eg- not a 3ds file :) - if ext.lower() not in IMAGE_EXT: - index = None - - except: - index = None - - if index != None: - tmpPath = path + filesOrigCase[index] - img = imageLoad( tmpPath ) - if img != None: - if VERBOSE: print '\t\tImage Found "%s"' % tmpPath - return img - - if RECURSIVE: - # IMAGE NOT FOUND IN ANY OF THE DIRS!, DO A RECURSIVE SEARCH. - if VERBOSE: print '\t\tImage Not Found in any of the dirs, doing a recusrive search' - for path in paths.iterkeys(): - # Were not going to use files - if path == '/' or len(path) == 3 and path[1:] == ':\\': - continue - - # print path , 'ASS' - - #------------------ - # finds the file starting at the root. - # def findImage(findRoot, imagePath): - #W--------------- - - # ROOT, DIRS, FILES - pathWalk = os.walk(path) - pathList = [True] - - matchList = [] # Store a list of (match, size), choose the biggest. - while True: - try: - pathList = pathWalk.next() - except: - break - - for file in pathList[2]: - file_lower = file.lower() - # FOUND A MATCH - if (file_lower == imageFileName_lower) or\ - (stripExt(file_lower) == imageFileName_noext_lower and getExt(file_lower) in IMAGE_EXT): - name = pathList[0] + sys.sep + file - size = os.path.getsize(name) - if VERBOSE: print '\t\t\tfound:', name - matchList.append( (name, size) ) - - if matchList: - # Sort by file size - matchList.sort(lambda A, B: cmp(B[1], A[1]) ) - - if VERBOSE: print '\t\tFound "%s"' % matchList[0][0] - - # Loop through all we have found - img = None - for match in matchList: - img = imageLoad(match[0]) # 0 - first, 0 - pathname - if img != None: - break - return img - - # No go. - if VERBOSE: print '\t\tImage Not Found after looking everywhere! "%s"' % imagePath - return imageLoad(imagePath) # Will jus treturn a placeholder. diff --git a/release/scripts/bpymodules/BPyMathutils.py b/release/scripts/bpymodules/BPyMathutils.py deleted file mode 100644 index 4882e9aaf21..00000000000 --- a/release/scripts/bpymodules/BPyMathutils.py +++ /dev/null @@ -1,228 +0,0 @@ -# $Id$ -# -# -------------------------------------------------------------------------- -# helper functions to be used by other scripts -# -------------------------------------------------------------------------- -# ***** 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 ***** -# -------------------------------------------------------------------------- - -import Blender -from Blender.Mathutils import * - -# ------ Mersenne Twister - start - -# Copyright (C) 1997 Makoto Matsumoto and Takuji Nishimura. -# Any feedback is very welcome. For any question, comments, -# see http://www.math.keio.ac.jp/matumoto/emt.html or email -# matumoto@math.keio.ac.jp - -# The link above is dead, this is the new one: -# http://www.math.sci.hiroshima-u.ac.jp/m-mat/MT/emt.html -# And here the license info, from Mr. Matsumoto's site: -# Until 2001/4/6, MT had been distributed under GNU Public License, -# but after 2001/4/6, we decided to let MT be used for any purpose, including -# commercial use. 2002-versions mt19937ar.c, mt19937ar-cok.c are considered -# to be usable freely. -# -# So from the year above (1997), this code is under GPL. - -# Period parameters -N = 624 -M = 397 -MATRIX_A = 0x9908b0dfL # constant vector a -UPPER_MASK = 0x80000000L # most significant w-r bits -LOWER_MASK = 0x7fffffffL # least significant r bits - -# Tempering parameters -TEMPERING_MASK_B = 0x9d2c5680L -TEMPERING_MASK_C = 0xefc60000L - -def TEMPERING_SHIFT_U(y): - return (y >> 11) - -def TEMPERING_SHIFT_S(y): - return (y << 7) - -def TEMPERING_SHIFT_T(y): - return (y << 15) - -def TEMPERING_SHIFT_L(y): - return (y >> 18) - -mt = [] # the array for the state vector -mti = N+1 # mti==N+1 means mt[N] is not initialized - -# initializing the array with a NONZERO seed -def sgenrand(seed): - # setting initial seeds to mt[N] using - # the generator Line 25 of Table 1 in - # [KNUTH 1981, The Art of Computer Programming - # Vol. 2 (2nd Ed.), pp102] - - global mt, mti - - mt = [] - - mt.append(seed & 0xffffffffL) - for i in xrange(1, N + 1): - mt.append((69069 * mt[i-1]) & 0xffffffffL) - - mti = i -# end sgenrand - - -def genrand(): - global mt, mti - - mag01 = [0x0L, MATRIX_A] - # mag01[x] = x * MATRIX_A for x=0,1 - y = 0 - - if mti >= N: # generate N words at one time - if mti == N+1: # if sgenrand() has not been called, - sgenrand(4357) # a default initial seed is used - - for kk in xrange((N-M) + 1): - y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK) - mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1] - - for kk in xrange(kk, N): - y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK) - mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1] - - y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK) - mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1] - - mti = 0 - - y = mt[mti] - mti += 1 - y ^= TEMPERING_SHIFT_U(y) - y ^= TEMPERING_SHIFT_S(y) & TEMPERING_MASK_B - y ^= TEMPERING_SHIFT_T(y) & TEMPERING_MASK_C - y ^= TEMPERING_SHIFT_L(y) - - return ( float(y) / 0xffffffffL ) # reals - -#------ Mersenne Twister -- end - - - - -""" 2d convexhull -Based from Dinu C. Gherman's work, -modified for Blender/Mathutils by Campell Barton -""" -###################################################################### -# Public interface -###################################################################### -def convexHull(point_list_2d): - """Calculate the convex hull of a set of vectors - The vectors can be 3 or 4d but only the Xand Y are used. - returns a list of convex hull indicies to the given point list - """ - - ###################################################################### - # Helpers - ###################################################################### - - def _myDet(p, q, r): - """Calc. determinant of a special matrix with three 2D points. - - The sign, "-" or "+", determines the side, right or left, - respectivly, on which the point r lies, when measured against - a directed vector from p to q. - """ - return (q.x*r.y + p.x*q.y + r.x*p.y) - (q.x*p.y + r.x*q.y + p.x*r.y) - - def _isRightTurn((p, q, r)): - "Do the vectors pq:qr form a right turn, or not?" - #assert p[0] != q[0] and q[0] != r[0] and p[0] != r[0] - if _myDet(p[0], q[0], r[0]) < 0: - return 1 - else: - return 0 - - # Get a local list copy of the points and sort them lexically. - points = [(p, i) for i, p in enumerate(point_list_2d)] - - try: points.sort(key = lambda a: (a[0].x, a[0].y)) - except: points.sort(lambda a,b: cmp((a[0].x, a[0].y), (b[0].x, b[0].y))) - - # Build upper half of the hull. - upper = [points[0], points[1]] # cant remove these. - for i in xrange(len(points)-2): - upper.append(points[i+2]) - while len(upper) > 2 and not _isRightTurn(upper[-3:]): - del upper[-2] - - # Build lower half of the hull. - points.reverse() - lower = [points.pop(0), points.pop(1)] - for p in points: - lower.append(p) - while len(lower) > 2 and not _isRightTurn(lower[-3:]): - del lower[-2] - - # Concatenate both halfs and return. - return [p[1] for ls in (upper, lower) for p in ls] - - -def plane2mat(plane, normalize= False): - ''' - Takes a plane and converts to a matrix - points between 0 and 1 are up - 1 and 2 are right - assumes the plane has 90d corners - ''' - cent= (plane[0]+plane[1]+plane[2]+plane[3] ) /4.0 - - - up= cent - ((plane[0]+plane[1])/2.0) - right= cent - ((plane[1]+plane[2])/2.0) - z= up.cross(right) - - if normalize: - up.normalize() - right.normalize() - z.normalize() - - mat= Matrix(up, right, z) - - # translate - mat.resize4x4() - tmat= Blender.Mathutils.TranslationMatrix(cent) - return mat * tmat - - -# Used for mesh_solidify.py and mesh_wire.py - -# returns a length from an angle -# Imaging a 2d space. -# there is a hoz line at Y1 going to inf on both X ends, never moves (LINEA) -# down at Y0 is a unit length line point up at (angle) from X0,Y0 (LINEB) -# This function returns the length of LINEB at the point it would intersect LINEA -# - Use this for working out how long to make the vector - differencing it from surrounding faces, -# import math -from math import pi, sin, cos, sqrt - -def angleToLength(angle): - # Alredy accounted for - if angle < 0.000001: return 1.0 - else: return abs(1.0 / cos(pi*angle/180)); diff --git a/release/scripts/bpymodules/BPyMesh.py b/release/scripts/bpymodules/BPyMesh.py deleted file mode 100644 index 292f7a4b91e..00000000000 --- a/release/scripts/bpymodules/BPyMesh.py +++ /dev/null @@ -1,1326 +0,0 @@ -# ***** 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 ***** -# -------------------------------------------------------------------------- - - -import Blender -import bpy -import BPyMesh_redux # seperated because of its size. -# reload(BPyMesh_redux) -redux= BPyMesh_redux.redux - -# python 2.3 has no reversed() iterator. this will only work on lists and tuples -try: - reversed -except: - def reversed(l): return l[::-1] - - -# If python version is less than 2.4, try to get set stuff from module -try: - set -except: - try: - from sets import Set as set - except: - set= None - - - - - -def meshWeight2List(me): - ''' Takes a mesh and return its group names and a list of lists, one list per vertex. - aligning the each vert list with the group names, each list contains float value for the weight. - These 2 lists can be modified and then used with list2MeshWeight to apply the changes. - ''' - - # Clear the vert group. - groupNames= me.getVertGroupNames() - len_groupNames= len(groupNames) - - if not len_groupNames: - # no verts? return a vert aligned empty list - return [[] for i in xrange(len(me.verts))], [] - - else: - vWeightList= [[0.0]*len_groupNames for i in xrange(len(me.verts))] - - for group_index, group in enumerate(groupNames): - for vert_index, weight in me.getVertsFromGroup(group, 1): # (i,w) tuples. - vWeightList[vert_index][group_index]= weight - - # removed this because me may be copying teh vertex groups. - #for group in groupNames: - # me.removeVertGroup(group) - - return groupNames, vWeightList - - -def list2MeshWeight(me, groupNames, vWeightList): - ''' Takes a list of groups and a list of vertex Weight lists as created by meshWeight2List - and applys it to the mesh.''' - - if len(vWeightList) != len(me.verts): - raise 'Error, Lists Differ in size, do not modify your mesh.verts before updating the weights' - - act_group = me.activeGroup - - # Clear the vert group. - currentGroupNames= me.getVertGroupNames() - for group in currentGroupNames: - me.removeVertGroup(group) # messes up the active group. - - # Add clean unused vert groupNames back - currentGroupNames= me.getVertGroupNames() - for group in groupNames: - me.addVertGroup(group) - - add_ = Blender.Mesh.AssignModes.ADD - - vertList= [None] - for i, v in enumerate(me.verts): - vertList[0]= i - for group_index, weight in enumerate(vWeightList[i]): - if weight: - try: - me.assignVertsToGroup(groupNames[group_index], vertList, min(1, max(0, weight)), add_) - except: - pass # vert group is not used anymore. - - try: me.activeGroup = act_group - except: pass - - me.update() - - - - -def meshWeight2Dict(me): - ''' Takes a mesh and return its group names and a list of dicts, one dict per vertex. - using the group as a key and a float value for the weight. - These 2 lists can be modified and then used with dict2MeshWeight to apply the changes. - ''' - - vWeightDict= [dict() for i in xrange(len(me.verts))] # Sync with vertlist. - - # Clear the vert group. - groupNames= me.getVertGroupNames() - - for group in groupNames: - for vert_index, weight in me.getVertsFromGroup(group, 1): # (i,w) tuples. - vWeightDict[vert_index][group]= weight - - # removed this because me may be copying teh vertex groups. - #for group in groupNames: - # me.removeVertGroup(group) - - return groupNames, vWeightDict - - -def dict2MeshWeight(me, groupNames, vWeightDict): - ''' Takes a list of groups and a list of vertex Weight dicts as created by meshWeight2Dict - and applys it to the mesh.''' - - if len(vWeightDict) != len(me.verts): - raise 'Error, Lists Differ in size, do not modify your mesh.verts before updating the weights' - - act_group = me.activeGroup - - # Clear the vert group. - currentGroupNames= me.getVertGroupNames() - for group in currentGroupNames: - if group not in groupNames: - me.removeVertGroup(group) # messes up the active group. - else: - me.removeVertsFromGroup(group) - - # Add clean unused vert groupNames back - currentGroupNames= me.getVertGroupNames() - for group in groupNames: - if group not in currentGroupNames: - me.addVertGroup(group) - - add_ = Blender.Mesh.AssignModes.ADD - - vertList= [None] - for i, v in enumerate(me.verts): - vertList[0]= i - for group, weight in vWeightDict[i].iteritems(): - try: - me.assignVertsToGroup(group, vertList, min(1, max(0, weight)), add_) - except: - pass # vert group is not used anymore. - - try: me.activeGroup = act_group - except: pass - - me.update() - -def dictWeightMerge(dict_weights): - ''' - Takes dict weight list and merges into 1 weight dict item and returns it - ''' - - if not dict_weights: - return {} - - keys= [] - for weight in dict_weights: - keys.extend([ (k, 0.0) for k in weight.iterkeys() ]) - - new_wdict = dict(keys) - - len_dict_weights= len(dict_weights) - - for weight in dict_weights: - for group, value in weight.iteritems(): - new_wdict[group] += value/len_dict_weights - - return new_wdict - - -FLIPNAMES=[\ -('Left','Right'),\ -('_L','_R'),\ -('-L','-R'),\ -('.L','.R'),\ -] - -def dictWeightFlipGroups(dict_weight, groupNames, createNewGroups): - ''' - Returns a weight with flip names - dict_weight - 1 vert weight. - groupNames - because we may need to add new group names. - dict_weight - Weather to make new groups where needed. - ''' - - def flipName(name): - for n1,n2 in FLIPNAMES: - for nA, nB in ( (n1,n2), (n1.lower(),n2.lower()), (n1.upper(),n2.upper()) ): - if createNewGroups: - newName= name.replace(nA,nB) - if newName!=name: - if newName not in groupNames: - groupNames.append(newName) - return newName - - newName= name.replace(nB,nA) - if newName!=name: - if newName not in groupNames: - groupNames.append(newName) - return newName - - else: - newName= name.replace(nA,nB) - if newName!=name and newName in groupNames: - return newName - - newName= name.replace(nB,nA) - if newName!=name and newName in groupNames: - return newName - - return name - - if not dict_weight: - return dict_weight, groupNames - - - new_wdict = {} - for group, weight in dict_weight.iteritems(): - flipname= flipName(group) - new_wdict[flipname]= weight - - return new_wdict, groupNames - - -def mesh2linkedFaces(me): - ''' - Splits the mesh into connected parts, - these parts are returned as lists of faces. - used for seperating cubes from other mesh elements in the 1 mesh - ''' - - # Build vert face connectivity - vert_faces= [[] for i in xrange(len(me.verts))] - for f in me.faces: - for v in f: - vert_faces[v.index].append(f) - - # sort faces into connectivity groups - face_groups= [[f] for f in me.faces] - face_mapping = range(len(me.faces)) # map old, new face location - - # Now clump faces iterativly - ok= True - while ok: - ok= False - - for i, f in enumerate(me.faces): - mapped_index= face_mapping[f.index] - mapped_group= face_groups[mapped_index] - - for v in f: - for nxt_f in vert_faces[v.index]: - if nxt_f != f: - nxt_mapped_index= face_mapping[nxt_f.index] - - # We are not a part of the same group - if mapped_index != nxt_mapped_index: - - ok= True - - # Assign mapping to this group so they all map to this group - for grp_f in face_groups[nxt_mapped_index]: - face_mapping[grp_f.index] = mapped_index - - # Move faces into this group - mapped_group.extend(face_groups[nxt_mapped_index]) - - # remove reference to the list - face_groups[nxt_mapped_index]= None - - - # return all face groups that are not null - # this is all the faces that are connected in their own lists. - return [fg for fg in face_groups if fg] - - -def getFaceLoopEdges(faces, seams=[]): - ''' - Takes me.faces or a list of faces and returns the edge loops - These edge loops are the edges that sit between quads, so they dont touch - 1 quad, not not connected will make 2 edge loops, both only containing 2 edges. - - return a list of edge key lists - [ [(0,1), (4, 8), (3,8)], ...] - - optionaly, seams are edge keys that will be removed - ''' - - OTHER_INDEX = 2,3,0,1 # opposite face index - - edges = {} - - for f in faces: - if len(f) == 4: - edge_keys = f.edge_keys - for i, edkey in enumerate(f.edge_keys): - edges.setdefault(edkey, []).append(edge_keys[OTHER_INDEX[i]]) - - for edkey in seams: - edges[edkey] = [] - - # Collect edge loops here - edge_loops = [] - - for edkey, ed_adj in edges.iteritems(): - if 0 <len(ed_adj) < 3: # 1 or 2 - # Seek the first edge - context_loop = [edkey, ed_adj[0]] - edge_loops.append(context_loop) - if len(ed_adj) == 2: - other_dir = ed_adj[1] - else: - other_dir = None - - ed_adj[:] = [] - - flipped = False - - while 1: - # from knowing the last 2, look for th next. - ed_adj = edges[context_loop[-1]] - if len(ed_adj) != 2: - - if other_dir and flipped==False: # the original edge had 2 other edges - flipped = True # only flip the list once - context_loop.reverse() - ed_adj[:] = [] - context_loop.append(other_dir) # save 1 lookiup - - ed_adj = edges[context_loop[-1]] - if len(ed_adj) != 2: - ed_adj[:] = [] - break - else: - ed_adj[:] = [] - break - - i = ed_adj.index(context_loop[-2]) - context_loop.append( ed_adj[ not i] ) - - # Dont look at this again - ed_adj[:] = [] - - - return edge_loops - - - -def getMeshFromObject(ob, container_mesh=None, apply_modifiers=True, vgroups=True, scn=None): - ''' - ob - the object that you want to get the mesh from - container_mesh - a Blender.Mesh type mesh that is reused to avoid a new datablock per call to getMeshFromObject - apply_modifiers - if enabled, subsurf bones etc. will be applied to the returned mesh. disable to get a copy of the mesh. - vgroup - For mesh objects only, apply the vgroup to the the copied mesh. (slower) - scn - Scene type. avoids getting the current scene each time getMeshFromObject is called. - - Returns Mesh or None - ''' - - if not scn: - scn= bpy.data.scenes.active - if not container_mesh: - mesh = bpy.data.meshes.new(ob.name) - else: - mesh= container_mesh - mesh.verts= None - - ob_type = ob.type - dataname = ob.getData(1) - tempob= None - if apply_modifiers or ob_type != 'Mesh': - try: - mesh.getFromObject(ob) - except: - return None - - else: - ''' - Dont apply modifiers, copy the mesh. - So we can transform the data. its easiest just to get a copy of the mesh. - ''' - tempob= scn.objects.new(ob.getData(mesh=1)) - mesh.getFromObject(tempob) - scn.objects.unlink(tempob) - - if ob_type == 'Mesh': - if vgroups: - if tempob==None: - tempob= Blender.Object.New('Mesh') - - tempob.link(mesh) - try: - # Copy the influences if possible. - groupNames, vWeightDict= meshWeight2Dict(ob.getData(mesh=1)) - dict2MeshWeight(mesh, groupNames, vWeightDict) - except: - # if the modifier changes the vert count then it messes it up for us. - pass - - return mesh - - -def faceRayIntersect(f, orig, rdir): - ''' - Returns face, side - Side is the side of a quad we intersect. - side 0 == 0,1,2 - side 1 == 0,2,3 - ''' - f_v= f.v - isect= Blender.Mathutils.Intersect(f_v[0].co, f_v[1].co, f_v[2].co, rdir, orig, 1) # 1==clip - - if isect: - return isect, 0 - - if len(f_v)==4: - isect= Blender.Mathutils.Intersect(f_v[0].co, f_v[2].co, f_v[3].co, rdir, orig, 1) # 1==clip - if isect: - return isect, 1 - return False, 0 - - -def pickMeshRayFace(me, orig, rdir): - best_dist= 1000000 - best_isect= best_side= best_face= None - for f in me.faces: - isect, side= faceRayIntersect(f, orig, rdir) - if isect: - dist= (isect-orig).length - if dist<best_dist: - best_dist= dist - best_face= f - best_side= side - best_isect= isect - - return best_face, best_isect, best_side - - -def pickMeshRayFaceWeight(me, orig, rdir): - f, isect, side = pickMeshRayFace(me, orig, rdir) - - if f==None: - return None, None, None, None, None - - f_v= [v.co for v in f] - if side==1: # we can leave side 0 without changes. - f_v = f_v[0], f_v[2], f_v[3] - - l0= (f_v[0]-isect).length - l1= (f_v[1]-isect).length - l2= (f_v[2]-isect).length - - w0 = (l1+l2) - w1 = (l0+l2) - w2 = (l1+l0) - - totw= w0 + w1 + w2 - w0=w0/totw - w1=w1/totw - w2=w2/totw - - return f, side, w0, w1, w2 - - - -def pickMeshGroupWeight(me, act_group, orig, rdir): - f, side, w0, w1, w2= pickMeshRayFaceWeight(me, orig, rdir) - - if f==None: - return None - - f_v= f.v - if side==0: - f_vi= (f_v[0].index, f_v[1].index, f_v[2].index) - else: - f_vi= (f_v[0].index, f_v[2].index, f_v[3].index) - - vws= [0.0,0.0,0.0] - for i in xrange(3): - try: vws[i]= me.getVertsFromGroup(act_group, 1, [f_vi[i],])[0][1] - except: pass - - return w0*vws[0] + w1*vws[1] + w2*vws[2] - -def pickMeshGroupVCol(me, orig, rdir): - Vector= Blender.Mathutils.Vector - f, side, w0, w1, w2= pickMeshRayFaceWeight(me, orig, rdir) - - if f==None: - return None - - def col2vec(c): - return Vector(c.r, c.g, c.b) - - if side==0: - idxs= 0,1,2 - else: - idxs= 0,2,3 - f_c= f.col - f_colvecs= [col2vec(f_c[i]) for i in idxs] - return f_colvecs[0]*w0 + f_colvecs[1]*w1 + f_colvecs[2]*w2 - -def edge_face_users(me): - ''' - Takes a mesh and returns a list aligned with the meshes edges. - Each item is a list of the faces that use the edge - would be the equiv for having ed.face_users as a property - ''' - - face_edges_dict= dict([(ed.key, (ed.index, [])) for ed in me.edges]) - for f in me.faces: - fvi= [v.index for v in f]# face vert idx's - for edkey in f.edge_keys: - face_edges_dict[edkey][1].append(f) - - face_edges= [None] * len(me.edges) - for ed_index, ed_faces in face_edges_dict.itervalues(): - face_edges[ed_index]= ed_faces - - return face_edges - - -def face_edges(me): - ''' - Returns a list alligned to the meshes faces. - each item is a list of lists: that is - face_edges -> face indicies - face_edges[i] -> list referencs local faces v indicies 1,2,3 &| 4 - face_edges[i][j] -> list of faces that this edge uses. - crap this is tricky to explain :/ - ''' - face_edges= [ [-1] * len(f) for f in me.faces ] - - face_edges_dict= dict([(ed.key, []) for ed in me.edges]) - for fidx, f in enumerate(me.faces): - for i, edkey in enumerate(f.edge_keys): - edge_face_users= face_edges_dict[edkey] - edge_face_users.append(f) - face_edges[fidx][i]= edge_face_users - - return face_edges - - -def facesPlanerIslands(me): - - def roundvec(v): - return round(v[0], 4), round(v[1], 4), round(v[2], 4) - - face_props= [(cent, no, roundvec(no), cent.dot(no)) for f in me.faces for no, cent in ((f.no, f.cent),)] - - face_edge_users= face_edges(me) - islands= [] - - used_faces= [0] * len(me.faces) - while True: - new_island= False - for i, used_val in enumerate(used_faces): - if used_val==0: - island= [i] - new_island= True - used_faces[i]= 1 - break - - if not new_island: - break - - island_growing= True - while island_growing: - island_growing= False - for fidx1 in island[:]: - if used_faces[fidx1]==1: - used_faces[fidx1]= 2 - face_prop1= face_props[fidx1] - for ed in face_edge_users[fidx1]: - for f2 in ed: - fidx2= f2.index - if fidx1 != fidx2 and used_faces[fidx2]==0: - island_growing= True - face_prop2= face_props[fidx2] - # normals are the same? - if face_prop1[2]==face_prop2[2]: - if abs(face_prop1[3] - face_prop1[1].dot(face_prop2[0])) < 0.000001: - used_faces[fidx2]= 1 - island.append(fidx2) - islands.append([me.faces[i] for i in island]) - return islands - - - -def facesUvIslands(me, PREF_IMAGE_DELIMIT=True): - def roundvec(v): - return round(v[0], 4), round(v[1], 4) - - if not me.faceUV: - return [ list(me.faces), ] - - # make a list of uv dicts - face_uvs= [ [roundvec(uv) for uv in f.uv] for f in me.faces] - - # key - face uv || value - list of face idxs - uv_connect_dict= dict([ (uv, [] ) for f_uvs in face_uvs for uv in f_uvs]) - - for i, f_uvs in enumerate(face_uvs): - for uv in f_uvs: # loops through rounded uv values - uv_connect_dict[uv].append(i) - islands= [] - - used_faces= [0] * len(me.faces) - while True: - new_island= False - for i, used_val in enumerate(used_faces): - if used_val==0: - island= [i] - new_island= True - used_faces[i]= 1 - break - - if not new_island: - break - - island_growing= True - while island_growing: - island_growing= False - for fidx1 in island[:]: - if used_faces[fidx1]==1: - used_faces[fidx1]= 2 - for uv in face_uvs[fidx1]: - for fidx2 in uv_connect_dict[uv]: - if fidx1 != fidx2 and used_faces[fidx2]==0: - if not PREF_IMAGE_DELIMIT or me.faces[fidx1].image==me.faces[fidx2].image: - island_growing= True - used_faces[fidx2]= 1 - island.append(fidx2) - - islands.append([me.faces[i] for i in island]) - return islands - -#def faceUvBounds(me, faces= None): - - -def facesUvRotate(me, deg, faces= None, pivot= (0,0)): - ''' - Faces can be None an all faces will be used - pivot is just the x/y well rotated about - - positive deg value for clockwise rotation - ''' - if faces==None: faces= me.faces - pivot= Blender.Mathutils.Vector(pivot) - - rotmat= Blender.Mathutils.RotationMatrix(-deg, 2) - - for f in faces: - f.uv= [((uv-pivot)*rotmat)+pivot for uv in f.uv] - -def facesUvScale(me, sca, faces= None, pivot= (0,0)): - ''' - Faces can be None an all faces will be used - pivot is just the x/y well rotated about - sca can be wither an int/float or a vector if you want to - scale x/y seperately. - a sca or (1.0, 1.0) will do nothing. - ''' - def vecmulti(v1,v2): - '''V2 is unchanged''' - v1[:]= (v1.x*v2.x, v1.y*v2.y) - return v1 - - sca= Blender.Mathutils.Vector(sca) - if faces==None: faces= me.faces - pivot= Blender.Mathutils.Vector(pivot) - - for f in faces: - f.uv= [vecmulti(uv-pivot, sca)+pivot for uv in f.uv] - - -def facesUvTranslate(me, tra, faces= None, pivot= (0,0)): - ''' - Faces can be None an all faces will be used - pivot is just the x/y well rotated about - ''' - if faces==None: faces= me.faces - tra= Blender.Mathutils.Vector(tra) - - for f in faces: - f.uv= [uv+tra for uv in f.uv] - - - -def edgeFaceUserCount(me, faces= None): - ''' - Return an edge aligned list with the count for all the faces that use that edge. - - can spesify a subset of the faces, so only those will be counted. - ''' - if faces==None: - faces= me.faces - max_vert= len(me.verts) - else: - # find the lighest vert index - pass - - edge_users= [0] * len(me.edges) - - edges_idx_dict= dict([(ed.key, ed.index) for ed in me.edges]) - - for f in faces: - for edkey in f.edge_keys: - edge_users[edges_idx_dict[edkey]] += 1 - - return edge_users - - -#============================================================================# -# Takes a face, and a pixel x/y on the image and returns a worldspace x/y/z # -# will return none if the pixel is not inside the faces UV # -#============================================================================# -def getUvPixelLoc(face, pxLoc, img_size = None, uvArea = None): - TriangleArea= Blender.Mathutils.TriangleArea - Vector= Blender.Mathutils.Vector - - if not img_size: - w,h = face.image.size - else: - w,h= img_size - - scaled_uvs= [Vector(uv.x*w, uv.y*h) for uv in f.uv] - - if len(scaled_uvs)==3: - indicies= ((0,1,2),) - else: - indicies= ((0,1,2), (0,2,3)) - - for fidxs in indicies: - for i1,i2,i3 in fidxs: - # IS a point inside our triangle? - # UVArea could be cached? - uv_area = TriangleArea(scaled_uvs[i1], scaled_uvs[i2], scaled_uvs[i3]) - area0 = TriangleArea(pxLoc, scaled_uvs[i2], scaled_uvs[i3]) - area1 = TriangleArea(pxLoc, scaled_uvs[i1], scaled_uvs[i3]) - area2 = TriangleArea(pxLoc, scaled_uvs[i1], scaled_uvs[i2]) - if area0 + area1 + area2 > uv_area + 1: # 1 px bleed/error margin. - pass # if were a quad the other side may contain the pixel so keep looking. - else: - # We know the point is in the tri - area0 /= uv_area - area1 /= uv_area - area2 /= uv_area - - # New location - return Vector(\ - face.v[i1].co[0]*area0 + face.v[i2].co[0]*area1 + face.v[i3].co[0]*area2,\ - face.v[i1].co[1]*area0 + face.v[i2].co[1]*area1 + face.v[i3].co[1]*area2,\ - face.v[i1].co[2]*area0 + face.v[i2].co[2]*area1 + face.v[i3].co[2]*area2\ - ) - - return None - - -# Used for debugging ngon -""" -def draw_loops(loops): - - me= Blender.Mesh.New() - for l in loops: - #~ me= Blender.Mesh.New() - - - i= len(me.verts) - me.verts.extend([v[0] for v in l]) - try: - me.verts[0].sel= 1 - except: - pass - me.edges.extend([ (j-1, j) for j in xrange(i+1, len(me.verts)) ]) - # Close the edge? - me.edges.extend((i, len(me.verts)-1)) - - - #~ ob= Blender.Object.New('Mesh') - #~ ob.link(me) - #~ scn= Blender.Scene.GetCurrent() - #~ scn.link(ob) - #~ ob.Layers= scn.Layers - #~ ob.sel= 1 - - - - # Fill - #fill= Blender.Mathutils.PolyFill(loops) - #me.faces.extend(fill) - - - ob= Blender.Object.New('Mesh') - ob.link(me) - scn= Blender.Scene.GetCurrent() - scn.link(ob) - ob.Layers= scn.Layers - ob.sel= 1 - Blender.Window.RedrawAll() -""" - -def ngon(from_data, indices, PREF_FIX_LOOPS= True): - ''' - Takes a polyline of indices (fgon) - and returns a list of face indicie lists. - Designed to be used for importers that need indices for an fgon to create from existing verts. - - from_data: either a mesh, or a list/tuple of vectors. - indices: a list of indicies to use this list is the ordered closed polyline to fill, and can be a subset of the data given. - PREF_FIX_LOOPS: If this is enabled polylines that use loops to make multiple polylines are delt with correctly. - ''' - - if not set: # Need sets for this, otherwise do a normal fill. - PREF_FIX_LOOPS= False - - Vector= Blender.Mathutils.Vector - if not indices: - return [] - - # return [] - def rvec(co): return round(co.x, 6), round(co.y, 6), round(co.z, 6) - def mlen(co): return abs(co[0])+abs(co[1])+abs(co[2]) # manhatten length of a vector, faster then length - - def vert_treplet(v, i): - return v, rvec(v), i, mlen(v) - - def ed_key_mlen(v1, v2): - if v1[3] > v2[3]: - return v2[1], v1[1] - else: - return v1[1], v2[1] - - - if not PREF_FIX_LOOPS: - ''' - Normal single concave loop filling - ''' - if type(from_data) in (tuple, list): - verts= [Vector(from_data[i]) for ii, i in enumerate(indices)] - else: - verts= [from_data.verts[i].co for ii, i in enumerate(indices)] - - for i in xrange(len(verts)-1, 0, -1): # same as reversed(xrange(1, len(verts))): - if verts[i][1]==verts[i-1][0]: - verts.pop(i-1) - - fill= Blender.Geometry.PolyFill([verts]) - - else: - ''' - Seperate this loop into multiple loops be finding edges that are used twice - This is used by lightwave LWO files a lot - ''' - - if type(from_data) in (tuple, list): - verts= [vert_treplet(Vector(from_data[i]), ii) for ii, i in enumerate(indices)] - else: - verts= [vert_treplet(from_data.verts[i].co, ii) for ii, i in enumerate(indices)] - - edges= [(i, i-1) for i in xrange(len(verts))] - if edges: - edges[0]= (0,len(verts)-1) - - if not verts: - return [] - - - edges_used= set() - edges_doubles= set() - # We need to check if any edges are used twice location based. - for ed in edges: - edkey= ed_key_mlen(verts[ed[0]], verts[ed[1]]) - if edkey in edges_used: - edges_doubles.add(edkey) - else: - edges_used.add(edkey) - - # Store a list of unconnected loop segments split by double edges. - # will join later - loop_segments= [] - - v_prev= verts[0] - context_loop= [v_prev] - loop_segments= [context_loop] - - for v in verts: - if v!=v_prev: - # Are we crossing an edge we removed? - if ed_key_mlen(v, v_prev) in edges_doubles: - context_loop= [v] - loop_segments.append(context_loop) - else: - if context_loop and context_loop[-1][1]==v[1]: - #raise "as" - pass - else: - context_loop.append(v) - - v_prev= v - # Now join loop segments - - def join_seg(s1,s2): - if s2[-1][1]==s1[0][1]: # - s1,s2= s2,s1 - elif s1[-1][1]==s2[0][1]: - pass - else: - return False - - # If were stuill here s1 and s2 are 2 segments in the same polyline - s1.pop() # remove the last vert from s1 - s1.extend(s2) # add segment 2 to segment 1 - - if s1[0][1]==s1[-1][1]: # remove endpoints double - s1.pop() - - s2[:]= [] # Empty this segment s2 so we dont use it again. - return True - - joining_segments= True - while joining_segments: - joining_segments= False - segcount= len(loop_segments) - - for j in xrange(segcount-1, -1, -1): #reversed(xrange(segcount)): - seg_j= loop_segments[j] - if seg_j: - for k in xrange(j-1, -1, -1): # reversed(xrange(j)): - if not seg_j: - break - seg_k= loop_segments[k] - - if seg_k and join_seg(seg_j, seg_k): - joining_segments= True - - loop_list= loop_segments - - for verts in loop_list: - while verts and verts[0][1]==verts[-1][1]: - verts.pop() - - loop_list= [verts for verts in loop_list if len(verts)>2] - # DONE DEALING WITH LOOP FIXING - - - # vert mapping - vert_map= [None]*len(indices) - ii=0 - for verts in loop_list: - if len(verts)>2: - for i, vert in enumerate(verts): - vert_map[i+ii]= vert[2] - ii+=len(verts) - - fill= Blender.Geometry.PolyFill([ [v[0] for v in loop] for loop in loop_list ]) - #draw_loops(loop_list) - #raise 'done loop' - # map to original indicies - fill= [[vert_map[i] for i in reversed(f)] for f in fill] - - - if not fill: - print 'Warning Cannot scanfill, fallback on a triangle fan.' - fill= [ [0, i-1, i] for i in xrange(2, len(indices)) ] - else: - # Use real scanfill. - # See if its flipped the wrong way. - flip= None - for fi in fill: - if flip != None: - break - for i, vi in enumerate(fi): - if vi==0 and fi[i-1]==1: - flip= False - break - elif vi==1 and fi[i-1]==0: - flip= True - break - - if not flip: - for i, fi in enumerate(fill): - fill[i]= tuple([ii for ii in reversed(fi)]) - - - - - return fill - - - -# EG -''' -scn= Scene.GetCurrent() -me = scn.getActiveObject().getData(mesh=1) -ind= [v.index for v in me.verts if v.sel] # Get indices - -indices = ngon(me, ind) # fill the ngon. - -# Extand the faces to show what the scanfill looked like. -print len(indices) -me.faces.extend([[me.verts[ii] for ii in i] for i in indices]) -''' - -def meshCalcNormals(me, vertNormals=None): - ''' - takes a mesh and returns very high quality normals 1 normal per vertex. - The normals should be correct, indipendant of topology - - vertNormals - a list of vectors at least as long as the number of verts in the mesh - ''' - Ang= Blender.Mathutils.AngleBetweenVecs - Vector= Blender.Mathutils.Vector - SMALL_NUM=0.000001 - # Weight the edge normals by total angle difference - # EDGE METHOD - - if not vertNormals: - vertNormals= [ Vector() for v in xrange(len(me.verts)) ] - else: - for v in vertNormals: - v.zero() - - edges={} - for f in me.faces: - f_v = f.v - for edkey in f.edge_keys: - edges.setdefault(edkey, []).append(f.no) - - # Weight the edge normals by total angle difference - for fnos in edges.itervalues(): - - len_fnos= len(fnos) - if len_fnos>1: - totAngDiff=0 - for j in xrange(len_fnos-1, -1, -1): # same as reversed(xrange(...)) - for k in xrange(j-1, -1, -1): # same as reversed(xrange(...)) - #print j,k - try: - totAngDiff+= (Ang(fnos[j], fnos[k])) # /180 isnt needed, just to keeop the vert small. - except: - pass # Zero length face - - # print totAngDiff - if totAngDiff > SMALL_NUM: - ''' - average_no= Vector() - for no in fnos: - average_no+=no - ''' - average_no= reduce(lambda a,b: a+b, fnos, Vector()) - fnos.append(average_no*totAngDiff) # average no * total angle diff - #else: - # fnos[0] - else: - fnos.append(fnos[0]) - - for ed, v in edges.iteritems(): - vertNormals[ed[0]]+= v[-1] - vertNormals[ed[1]]+= v[-1] - for i, v in enumerate(me.verts): - v.no= vertNormals[i] - - - - -def pointInsideMesh(ob, pt): - Intersect = Blender.Mathutils.Intersect # 2 less dict lookups. - Vector = Blender.Mathutils.Vector - - def ptInFaceXYBounds(f, pt): - f_v = f.v - co= f_v[0].co - xmax= xmin= co.x - ymax= ymin= co.y - - co= f_v[1].co - xmax= max(xmax, co.x) - xmin= min(xmin, co.x) - ymax= max(ymax, co.y) - ymin= min(ymin, co.y) - - co= f_v[2].co - xmax= max(xmax, co.x) - xmin= min(xmin, co.x) - ymax= max(ymax, co.y) - ymin= min(ymin, co.y) - - if len(f_v)==4: - co= f_v[3].co - xmax= max(xmax, co.x) - xmin= min(xmin, co.x) - ymax= max(ymax, co.y) - ymin= min(ymin, co.y) - - # Now we have the bounds, see if the point is in it. - if\ - pt.x < xmin or\ - pt.y < ymin or\ - pt.x > xmax or\ - pt.y > ymax: - return False # point is outside face bounds - else: - return True # point inside. - #return xmax, ymax, xmin, ymin - - def faceIntersect(f): - f_v = f.v - isect = Intersect(f_v[0].co, f_v[1].co, f_v[2].co, ray, obSpacePt, 1) # Clipped. - if not isect and len(f) == 4: - isect = Intersect(f_v[0].co, f_v[2].co, f_v[3].co, ray, obSpacePt, 1) # Clipped. - - if isect and isect.z > obSpacePt.z: # This is so the ray only counts if its above the point. - return True - else: - return False - - obSpacePt = pt*ob.matrixWorld.copy().invert() - ray = Vector(0,0,-1) - me= ob.getData(mesh=1) - - # Here we find the number on intersecting faces, return true if an odd number (inside), false (outside) if its true. - return len([None for f in me.faces if ptInFaceXYBounds(f, obSpacePt) if faceIntersect(f)]) % 2 - - -def faceAngles(f): - ''' - Returns the angle between all corners in a tri or a quad - - ''' - AngleBetweenVecs = Blender.Mathutils.AngleBetweenVecs - def Ang(a1,a2): - try: return AngleBetweenVecs(a1,a2) - except: return 180 - - if len(f) == 3: - if type(f) in (tuple, list): v1,v2,v3 = f - else: v1,v2,v3 = [v.co for v in f] - a1= Ang(v2-v1,v3-v1) - a2= Ang(v1-v2,v3-v2) - a3 = 180 - (a1+a2) # a3= Mathutils.AngleBetweenVecs(v2-v3,v1-v3) - return a1,a2,a3 - - else: - if type(f) in (tuple, list): v1,v2,v3,v4 = f - else: v1,v2,v3,v4 = [v.co for v in f] - a1= Ang(v2-v1,v4-v1) - a2= Ang(v1-v2,v3-v2) - a3= Ang(v2-v3,v4-v3) - a4= Ang(v3-v4,v1-v4) - return a1,a2,a3,a4 - -# NMesh wrapper -Vector= Blender.Mathutils.Vector -class NMesh(object): - __slots__= 'verts', 'faces', 'edges', 'faceUV', 'materials', 'realmesh' - def __init__(self, mesh): - ''' - This is an NMesh wrapper that - mesh is an Mesh as returned by Blender.Mesh.New() - This class wraps NMesh like access into Mesh - - Running NMesh.update() - with this wrapper, - Will update the realmesh. - ''' - self.verts= [] - self.faces= [] - self.edges= [] - self.faceUV= False - self.materials= [] - self.realmesh= mesh - - def addFace(self, nmf): - self.faces.append(nmf) - - def Face(self, v=[]): - return NMFace(v) - def Vert(self, x,y,z): - return NMVert(x,y,z) - - def hasFaceUV(self, flag): - if flag: - self.faceUV= True - else: - self.faceUV= False - - def addMaterial(self, mat): - self.materials.append(mat) - - def update(self, recalc_normals=False): # recalc_normals is dummy - mesh= self.realmesh - mesh.verts= None # Clears the - - # Add in any verts from faces we may have not added. - for nmf in self.faces: - for nmv in nmf.v: - if nmv.index==-1: - nmv.index= len(self.verts) - self.verts.append(nmv) - - - mesh.verts.extend([nmv.co for nmv in self.verts]) - for i, nmv in enumerate(self.verts): - nmv.index= i - mv= mesh.verts[i] - mv.sel= nmv.sel - - good_faces= [nmf for nmf in self.faces if len(nmf.v) in (3,4)] - #print len(good_faces), 'AAA' - - - #mesh.faces.extend([nmf.v for nmf in self.faces]) - mesh.faces.extend([[mesh.verts[nmv.index] for nmv in nmf.v] for nmf in good_faces]) - if len(mesh.faces): - if self.faceUV: - mesh.faceUV= 1 - - #for i, nmf in enumerate(self.faces): - for i, nmf in enumerate(good_faces): - mf= mesh.faces[i] - if self.faceUV: - if len(nmf.uv) == len(mf.v): - mf.uv= [Vector(uv[0], uv[1]) for uv in nmf.uv] - if len(nmf.col) == len(mf.v): - for c, i in enumerate(mf.col): - c.r, c.g, c.b= nmf.col[i].r, nmf.col[i].g, nmf.col[i].b - if nmf.image: - mf.image= nmf.image - - mesh.materials= self.materials[:16] - -class NMVert(object): - __slots__= 'co', 'index', 'no', 'sel', 'uvco' - def __init__(self, x,y,z): - self.co= Vector(x,y,z) - self.index= None # set on appending. - self.no= Vector(0,0,1) # dummy - self.sel= 0 - self.uvco= None -class NMFace(object): - __slots__= 'col', 'flag', 'hide', 'image', 'mat', 'materialIndex', 'mode', 'normal',\ - 'sel', 'smooth', 'transp', 'uv', 'v' - - def __init__(self, v=[]): - self.col= [] - self.flag= 0 - self.hide= 0 - self.image= None - self.mat= 0 # materialIndex needs support too. - self.mode= 0 - self.normal= Vector(0,0,1) - self.uv= [] - self.sel= 0 - self.smooth= 0 - self.transp= 0 - self.uv= [] - self.v= [] # a list of nmverts. - -class NMCol(object): - __slots__ = 'r', 'g', 'b', 'a' - def __init__(self): - self.r= 255 - self.g= 255 - self.b= 255 - self.a= 255 - - -''' -# -verts_split= [dict() for i in xrange(len(me.verts))] - -tot_verts= 0 -for f in me.faces: - f_uv= f.uv - for i, v in enumerate(f.v): - vert_index= v.index # mesh index - vert_dict= verts_split[vert_index] # get the dict for this vert - - uv= f_uv[i] - # now we have the vert and the face uv well make a unique dict. - - vert_key= v.x, v.y, v.x, uv.x, uv.y # ADD IMAGE NAME HETR IF YOU WANT TO SPLIT BY THAT TOO - value= vert_index, tot_verts # ADD WEIGHT HERE IF YOU NEED. - try: - vert_dict[vert_key] # if this is missing it will fail. - except: - # this stores a mapping between the split and orig vert indicies - vert_dict[vert_key]= value - tot_verts+= 1 - -# a flat list of split verts - can add custom weight data here too if you need -split_verts= [None]*tot_verts - -for vert_split_dict in verts_split: - for key, value in vert_split_dict.iteritems(): - local_index, split_index= value - split_verts[split_index]= key - -# split_verts - Now you have a list of verts split by their UV. -''' diff --git a/release/scripts/bpymodules/BPyMesh_redux.py b/release/scripts/bpymodules/BPyMesh_redux.py deleted file mode 100644 index 5955d696fbd..00000000000 --- a/release/scripts/bpymodules/BPyMesh_redux.py +++ /dev/null @@ -1,652 +0,0 @@ -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# (C) Copyright 2006 MetaVR, Inc. -# http://www.metavr.com -# Written by Campbell Barton -# -# 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 ***** -# -------------------------------------------------------------------------- - -import Blender -import bpy -Vector= Blender.Mathutils.Vector -Ang= Blender.Mathutils.AngleBetweenVecs -MidpointVecs= Blender.Mathutils.MidpointVecs -import BPyMesh - -# If python version is less than 2.4, try to get set stuff from module - -try: - set -except: - try: - from sets import Set as set - except: - set= None - -def uv_key(uv): - return round(uv.x, 5), round(uv.y, 5) - -def uv_key_mix(uv1, uv2, w1, w2): - # Weighted mix. w1+w2==1.0 - return w1*uv1[0]+w2*uv2[0], w1*uv1[1]+w2*uv2[1] - -def col_key(col): - return col.r, col.g, col.b - -def col_key_mix(col1, col2, w1, w2): - # Weighted mix. w1+w2==1.0 - return int(w1*col1[0] + w2*col2[0]), int(w1*col1[1] + w2*col2[1]), int(w1*col1[2]+col2[2]*w2) - - -def redux(ob, REDUX=0.5, BOUNDRY_WEIGHT=2.0, REMOVE_DOUBLES=False, FACE_AREA_WEIGHT=1.0, FACE_TRIANGULATE=True, DO_UV=True, DO_VCOL=True, DO_WEIGHTS=True, VGROUP_INF_REDUX= None, VGROUP_INF_WEIGHT=0.5): - """ - BOUNDRY_WEIGHT - 0 is no boundry weighting. 2.0 will make them twice as unlikely to collapse. - FACE_AREA_WEIGHT - 0 is no weight. 1 is normal, 2.0 is higher. - """ - - if REDUX<0 or REDUX>1.0: - raise 'Error, factor must be between 0 and 1.0' - elif not set: - raise 'Error, this function requires Python 2.4 or a full install of Python 2.3' - - BOUNDRY_WEIGHT= 1+BOUNDRY_WEIGHT - - """ # DEBUG! - if Blender.Get('rt') == 1000: - DEBUG=True - else: - DEBUG= False - """ - - me= ob.getData(mesh=1) - me.hide= False # unhide all data,. - if len(me.faces)<5: - return - - - - if FACE_TRIANGULATE or REMOVE_DOUBLES: - me.sel= True - - if FACE_TRIANGULATE: - me.quadToTriangle() - - if REMOVE_DOUBLES: - me.remDoubles(0.0001) - - vgroups= me.getVertGroupNames() - - if not me.getVertGroupNames(): - DO_WEIGHTS= False - - if (VGROUP_INF_REDUX!= None and VGROUP_INF_REDUX not in vgroups) or\ - VGROUP_INF_WEIGHT==0.0: - VGROUP_INF_REDUX= None - - try: - VGROUP_INF_REDUX_INDEX= vgroups.index(VGROUP_INF_REDUX) - except: - VGROUP_INF_REDUX_INDEX= -1 - - # del vgroups - len_vgroups= len(vgroups) - - - - OLD_MESH_MODE= Blender.Mesh.Mode() - Blender.Mesh.Mode(Blender.Mesh.SelectModes.VERTEX) - - if DO_UV and not me.faceUV: - DO_UV= False - - if DO_VCOL and not me.vertexColors: - DO_VCOL = False - - current_face_count= len(me.faces) - target_face_count= int(current_face_count * REDUX) - # % of the collapseable faces to collapse per pass. - #collapse_per_pass= 0.333 # between 0.1 - lots of small nibbles, slow but high q. and 0.9 - big passes and faster. - collapse_per_pass= 0.333 # between 0.1 - lots of small nibbles, slow but high q. and 0.9 - big passes and faster. - - """# DEBUG! - if DEBUG: - COUNT= [0] - def rd(): - if COUNT[0]< 330: - COUNT[0]+=1 - return - me.update() - Blender.Window.RedrawAll() - print 'Press key for next, count "%s"' % COUNT[0] - try: input() - except KeyboardInterrupt: - raise "Error" - except: - pass - - COUNT[0]+=1 - """ - - class collapseEdge(object): - __slots__ = 'length', 'key', 'faces', 'collapse_loc', 'v1', 'v2','uv1', 'uv2', 'col1', 'col2', 'collapse_weight' - def __init__(self, ed): - self.init_from_edge(ed) # So we can re-use the classes without using more memory. - - def init_from_edge(self, ed): - self.key= ed.key - self.length= ed.length - self.faces= [] - self.v1= ed.v1 - self.v2= ed.v2 - if DO_UV or DO_VCOL: - self.uv1= [] - self.uv2= [] - self.col1= [] - self.col2= [] - - # self.collapse_loc= None # new collapse location. - # Basic weighting. - #self.collapse_weight= self.length * (1+ ((ed.v1.no-ed.v2.no).length**2)) - self.collapse_weight= 1.0 - - def collapse_locations(self, w1, w2): - ''' - Generate a smart location for this edge to collapse to - w1 and w2 are vertex location bias - ''' - - v1co= self.v1.co - v2co= self.v2.co - v1no= self.v1.no - v2no= self.v2.no - - # Basic operation, works fine but not as good as predicting the best place. - #between= ((v1co*w1) + (v2co*w2)) - #self.collapse_loc= between - - # normalize the weights of each vert - se we can use them as scalers. - wscale= w1+w2 - if not wscale: # no scale? - w1=w2= 0.5 - else: - w1/=wscale - w2/=wscale - - length= self.length - between= MidpointVecs(v1co, v2co) - - # Collapse - # new_location = between # Replace tricky code below. this code predicts the best collapse location. - - # Make lines at right angles to the normals- these 2 lines will intersect and be - # the point of collapsing. - - # Enlarge so we know they intersect: self.length*2 - cv1= v1no.cross(v1no.cross(v1co-v2co)) - cv2= v2no.cross(v2no.cross(v2co-v1co)) - - # Scale to be less then the edge lengths. - cv2.length = cv1.length = 1 - - cv1 = cv1 * (length* 0.4) - cv2 = cv2 * (length* 0.4) - - smart_offset_loc= between + (cv1 + cv2) - - # Now we need to blend between smart_offset_loc and w1/w2 - # you see were blending between a vert and the edges midpoint, so we cant use a normal weighted blend. - if w1 > 0.5: # between v1 and smart_offset_loc - #self.collapse_loc= v1co*(w2+0.5) + smart_offset_loc*(w1-0.5) - w2*=2 - w1= 1-w2 - new_loc_smart= v1co*w1 + smart_offset_loc*w2 - else: # w between v2 and smart_offset_loc - w1*=2 - w2= 1-w1 - new_loc_smart= v2co*w2 + smart_offset_loc*w1 - - if new_loc_smart.x != new_loc_smart.x: # NAN LOCATION, revert to between - new_loc_smart= None - - return new_loc_smart, between, v1co*0.99999 + v2co*0.00001, v1co*0.00001 + v2co*0.99999 - - - class collapseFace(object): - __slots__ = 'verts', 'normal', 'area', 'index', 'orig_uv', 'orig_col', 'uv', 'col' # , 'collapse_edge_count' - def __init__(self, f): - self.init_from_face(f) - - def init_from_face(self, f): - self.verts= f.v - self.normal= f.no - self.area= f.area - self.index= f.index - if DO_UV: - self.orig_uv= [uv_key(uv) for uv in f.uv] - self.uv= f.uv - if DO_VCOL: - self.orig_col= [col_key(col) for col in f.col] - self.col= f.col - - collapse_edges= collapse_faces= None - - # So meshCalcNormals can avoid making a new list all the time. - reuse_vertNormals= [ Vector() for v in xrange(len(me.verts)) ] - - while target_face_count <= len(me.faces): - BPyMesh.meshCalcNormals(me, reuse_vertNormals) - - if DO_WEIGHTS: - #groupNames, vWeightDict= BPyMesh.meshWeight2Dict(me) - groupNames, vWeightList= BPyMesh.meshWeight2List(me) - - # THIS CRASHES? Not anymore. - verts= list(me.verts) - edges= list(me.edges) - faces= list(me.faces) - - # THIS WORKS - #verts= me.verts - #edges= me.edges - #faces= me.faces - - # if DEBUG: DOUBLE_CHECK= [0]*len(verts) - me.sel= False - - if not collapse_faces: # Initialize the list. - collapse_faces= [collapseFace(f) for f in faces] - collapse_edges= [collapseEdge(ed) for ed in edges] - else: - for i, ed in enumerate(edges): - collapse_edges[i].init_from_edge(ed) - - # Strip the unneeded end off the list - collapse_edges[i+1:]= [] - - for i, f in enumerate(faces): - collapse_faces[i].init_from_face(f) - - # Strip the unneeded end off the list - collapse_faces[i+1:]= [] - - - collapse_edges_dict= dict( [(ced.key, ced) for ced in collapse_edges] ) - - # Store verts edges. - vert_ed_users= [[] for i in xrange(len(verts))] - for ced in collapse_edges: - vert_ed_users[ced.key[0]].append(ced) - vert_ed_users[ced.key[1]].append(ced) - - # Store face users - vert_face_users= [[] for i in xrange(len(verts))] - - # Have decieded not to use this. area is better. - #face_perim= [0.0]* len(me.faces) - - for ii, cfa in enumerate(collapse_faces): - for i, v1 in enumerate(cfa.verts): - vert_face_users[v1.index].append( (i,cfa) ) - - # add the uv coord to the vert - v2 = cfa.verts[i-1] - i1= v1.index - i2= v2.index - - if i1>i2: ced= collapse_edges_dict[i2,i1] - else: ced= collapse_edges_dict[i1,i2] - - ced.faces.append(cfa) - if DO_UV or DO_VCOL: - # if the edge is flipped from its order in the face then we need to flip the order indicies. - if cfa.verts[i]==ced.v1: i1,i2 = i, i-1 - else: i1,i2 = i-1, i - - if DO_UV: - ced.uv1.append( cfa.orig_uv[i1] ) - ced.uv2.append( cfa.orig_uv[i2] ) - - if DO_VCOL: - ced.col1.append( cfa.orig_col[i1] ) - ced.col2.append( cfa.orig_col[i2] ) - - - # PERIMITER - #face_perim[ii]+= ced.length - - - - # How weight the verts by the area of their faces * the normal difference. - # when the edge collapses, to vert weights are taken into account - - vert_weights= [0.5] * len(verts) - - for ii, vert_faces in enumerate(vert_face_users): - for f in vert_faces: - try: - no_ang= (Ang(verts[ii].no, f[1].normal)/180) * f[1].area - except: - no_ang= 1.0 - - vert_weights[ii] += no_ang - - # Use a vertex group as a weighting. - if VGROUP_INF_REDUX!=None: - - # Get Weights from a vgroup. - """ - vert_weights_map= [1.0] * len(verts) - for i, wd in enumerate(vWeightDict): - try: vert_weights_map[i]= 1+(wd[VGROUP_INF_REDUX] * VGROUP_INF_WEIGHT) - except: pass - """ - vert_weights_map= [1+(wl[VGROUP_INF_REDUX_INDEX]*VGROUP_INF_WEIGHT) for wl in vWeightList ] - - - # BOUNDRY CHECKING AND WEIGHT EDGES. CAN REMOVE - # Now we know how many faces link to an edge. lets get all the boundry verts - if BOUNDRY_WEIGHT > 0: - verts_boundry= [1] * len(verts) - #for ed_idxs, faces_and_uvs in edge_faces_and_uvs.iteritems(): - for ced in collapse_edges: - if len(ced.faces) < 2: - for key in ced.key: # only ever 2 key indicies. - verts_boundry[key]= 2 - - for ced in collapse_edges: - b1= verts_boundry[ced.key[0]] - b2= verts_boundry[ced.key[1]] - if b1 != b2: - # Edge has 1 boundry and 1 non boundry vert. weight higher - ced.collapse_weight= BOUNDRY_WEIGHT - #elif b1==b2==2: # if both are on a seam then weigh half as bad. - # ced.collapse_weight= ((BOUNDRY_WEIGHT-1)/2) +1 - # weight the verts by their boundry status - del b1 - del b2 - - for ii, boundry in enumerate(verts_boundry): - if boundry==2: - vert_weights[ii] *= BOUNDRY_WEIGHT - - vert_collapsed= verts_boundry - del verts_boundry - else: - vert_collapsed= [1] * len(verts) - - - - - # Best method, no quick hacks here, Correction. Should be the best but needs tweaks. - def ed_set_collapse_error(ced): - # Use the vertex weights to bias the new location. - new_locs= ced.collapse_locations(vert_weights[ced.key[0]], vert_weights[ced.key[1]]) - - - # Find the connecting faces of the 2 verts. - i1, i2= ced.key - test_faces= set() - for i in (i1,i2): # faster then LC's - for f in vert_face_users[i]: - test_faces.add(f[1].index) - for f in ced.faces: - test_faces.remove(f.index) - - - v1_orig= Vector(ced.v1.co) - v2_orig= Vector(ced.v2.co) - - def test_loc(new_loc): - ''' - Takes a location and tests the error without changing anything - ''' - new_weight= ced.collapse_weight - ced.v1.co= ced.v2.co= new_loc - - new_nos= [faces[i].no for i in test_faces] - - # So we can compare the befire and after normals - ced.v1.co= v1_orig - ced.v2.co= v2_orig - - # now see how bad the normals are effected - angle_diff= 1.0 - - for ii, i in enumerate(test_faces): # local face index, global face index - cfa= collapse_faces[i] # this collapse face - try: - # can use perim, but area looks better. - if FACE_AREA_WEIGHT: - # Psudo code for wrighting - # angle_diff= The before and after angle difference between the collapsed and un-collapsed face. - # ... devide by 180 so the value will be between 0 and 1.0 - # ... add 1 so we can use it as a multiplyer and not make the area have no eefect (below) - # area_weight= The faces original area * the area weight - # ... add 1.0 so a small area face dosent make the angle_diff have no effect. - # - # Now multiply - (angle_diff * area_weight) - # ... The weight will be a minimum of 1.0 - we need to subtract this so more faces done give the collapse an uneven weighting. - - angle_diff+= ((1+(Ang(cfa.normal, new_nos[ii])/180)) * (1+(cfa.area * FACE_AREA_WEIGHT))) -1 # 4 is how much to influence area - else: - angle_diff+= (Ang(cfa.normal), new_nos[ii])/180 - - except: - pass - - - # This is very arbirary, feel free to modify - try: no_ang= (Ang(ced.v1.no, ced.v2.no)/180) + 1 - except: no_ang= 2.0 - - # do *= because we face the boundry weight to initialize the weight. 1.0 default. - new_weight *= ((no_ang * ced.length) * (1-(1/angle_diff)))# / max(len(test_faces), 1) - return new_weight - # End testloc - - - # Test the collapse locatons - collapse_loc_best= None - collapse_weight_best= 1000000000 - ii= 0 - for collapse_loc in new_locs: - if collapse_loc: # will only ever fail if smart loc is NAN - test_weight= test_loc(collapse_loc) - if test_weight < collapse_weight_best: - iii= ii - collapse_weight_best = test_weight - collapse_loc_best= collapse_loc - ii+=1 - - ced.collapse_loc= collapse_loc_best - ced.collapse_weight= collapse_weight_best - - - # are we using a weight map - if VGROUP_INF_REDUX: - v= vert_weights_map[i1]+vert_weights_map[i2] - ced.collapse_weight*= v - # End collapse Error - - # We can calculate the weights on __init__ but this is higher qualuity. - for ced in collapse_edges: - if ced.faces: # dont collapse faceless edges. - ed_set_collapse_error(ced) - - # Wont use the function again. - del ed_set_collapse_error - # END BOUNDRY. Can remove - - # sort by collapse weight - try: collapse_edges.sort(key = lambda ced: ced.collapse_weight) # edges will be used for sorting - except: collapse_edges.sort(lambda ced1, ced2: cmp(ced1.collapse_weight, ced2.collapse_weight)) # edges will be used for sorting - - - vert_collapsed= [0]*len(verts) - - collapse_edges_to_collapse= [] - - # Make a list of the first half edges we can collapse, - # these will better edges to remove. - collapse_count=0 - for ced in collapse_edges: - if ced.faces: - i1, i2= ced.key - # Use vert selections - if vert_collapsed[i1] or vert_collapsed[i2]: - pass - else: - # Now we know the verts havnyt been collapsed. - vert_collapsed[i2]= vert_collapsed[i1]= 1 # Dont collapse again. - collapse_count+=1 - collapse_edges_to_collapse.append(ced) - - # Get a subset of the entire list- the first "collapse_per_pass", that are best to collapse. - if collapse_count > 4: - collapse_count = int(collapse_count*collapse_per_pass) - else: - collapse_count = len(collapse_edges) - # We know edge_container_list_collapse can be removed. - for ced in collapse_edges_to_collapse: - """# DEBUG! - if DEBUG: - if DOUBLE_CHECK[ced.v1.index] or\ - DOUBLE_CHECK[ced.v2.index]: - raise 'Error' - else: - DOUBLE_CHECK[ced.v1.index]=1 - DOUBLE_CHECK[ced.v2.index]=1 - - tmp= (ced.v1.co+ced.v2.co)*0.5 - Blender.Window.SetCursorPos(tmp.x, tmp.y, tmp.z) - Blender.Window.RedrawAll() - """ - - # Chech if we have collapsed our quota. - collapse_count-=1 - if not collapse_count: - break - - current_face_count -= len(ced.faces) - - # Find and assign the real weights based on collapse loc. - - # Find the weights from the collapse error - if DO_WEIGHTS or DO_UV or DO_VCOL: - i1, i2= ced.key - # Dont use these weights since they may not have been used to make the collapse loc. - #w1= vert_weights[i1] - #w2= vert_weights[i2] - w1= (ced.v2.co-ced.collapse_loc).length - w2= (ced.v1.co-ced.collapse_loc).length - - # Normalize weights - wscale= w1+w2 - if not wscale: # no scale? - w1=w2= 0.5 - else: - w1/= wscale - w2/= wscale - - - # Interpolate the bone weights. - if DO_WEIGHTS: - - # add verts vgroups to eachother - wl1= vWeightList[i1] # v1 weight dict - wl2= vWeightList[i2] # v2 weight dict - for group_index in xrange(len_vgroups): - wl1[group_index]= wl2[group_index]= (wl1[group_index]*w1) + (wl2[group_index]*w2) - # Done finding weights. - - - - if DO_UV or DO_VCOL: - # Handel UV's and vert Colors! - for v, my_weight, other_weight, edge_my_uvs, edge_other_uvs, edge_my_cols, edge_other_cols in (\ - (ced.v1, w1, w2, ced.uv1, ced.uv2, ced.col1, ced.col2),\ - (ced.v2, w2, w1, ced.uv2, ced.uv1, ced.col2, ced.col1)\ - ): - uvs_mixed= [ uv_key_mix(edge_my_uvs[iii], edge_other_uvs[iii], my_weight, other_weight) for iii in xrange(len(edge_my_uvs)) ] - cols_mixed= [ col_key_mix(edge_my_cols[iii], edge_other_cols[iii], my_weight, other_weight) for iii in xrange(len(edge_my_cols)) ] - - for face_vert_index, cfa in vert_face_users[v.index]: - if len(cfa.verts)==3 and cfa not in ced.faces: # if the face is apart of this edge then dont bother finding the uvs since the face will be removed anyway. - - if DO_UV: - # UV COORDS - uvk= cfa.orig_uv[face_vert_index] - try: - tex_index= edge_my_uvs.index(uvk) - except: - tex_index= None - """ # DEBUG! - if DEBUG: - print 'not found', uvk, 'in', edge_my_uvs, 'ed index', ii, '\nwhat about', edge_other_uvs - """ - if tex_index != None: # This face uses a uv in the collapsing face. - do a merge - other_uv= edge_other_uvs[tex_index] - uv_vec= cfa.uv[face_vert_index] - uv_vec.x, uv_vec.y= uvs_mixed[tex_index] - - # TEXFACE COLORS - if DO_VCOL: - colk= cfa.orig_col[face_vert_index] - try: tex_index= edge_my_cols.index(colk) - except: pass - if tex_index != None: - other_col= edge_other_cols[tex_index] - col_ob= cfa.col[face_vert_index] - col_ob.r, col_ob.g, col_ob.b= cols_mixed[tex_index] - - # DEBUG! if DEBUG: rd() - - # Execute the collapse - ced.v1.sel= ced.v2.sel= True # Select so remove doubles removed the edges and faces that use it - ced.v1.co= ced.v2.co= ced.collapse_loc - - # DEBUG! if DEBUG: rd() - if current_face_count <= target_face_count: - break - - # Copy weights back to the mesh before we remove doubles. - if DO_WEIGHTS: - #BPyMesh.dict2MeshWeight(me, groupNames, vWeightDict) - BPyMesh.list2MeshWeight(me, groupNames, vWeightList) - - doubles= me.remDoubles(0.0001) - current_face_count= len(me.faces) - - if current_face_count <= target_face_count or not doubles: # not doubles shoule never happen. - break - - me.update() - Blender.Mesh.Mode(OLD_MESH_MODE) - - -# Example usage -def main(): - Blender.Window.EditMode(0) - scn= bpy.data.scenes.active - active_ob= scn.objects.active - t= Blender.sys.time() - redux(active_ob, 0.5) - print '%.4f' % (Blender.sys.time()-t) - -if __name__=='__main__': - main() diff --git a/release/scripts/bpymodules/BPyMessages.py b/release/scripts/bpymodules/BPyMessages.py deleted file mode 100644 index 8ee1aa6c707..00000000000 --- a/release/scripts/bpymodules/BPyMessages.py +++ /dev/null @@ -1,61 +0,0 @@ -from Blender import Draw, sys -def Error_NoMeshSelected(): - Draw.PupMenu('Error%t|No mesh objects selected') -def Error_NoActive(): - Draw.PupMenu('Error%t|No active object') -def Error_NoMeshActive(): - Draw.PupMenu('Error%t|Active object is not a mesh') -def Error_NoMeshUvSelected(): - Draw.PupMenu('Error%t|No mesh objects with texface selected') -def Error_NoMeshUvActive(): - Draw.PupMenu('Error%t|Active object is not a mesh with texface') -def Error_NoMeshMultiresEdit(): - Draw.PupMenu('Error%t|Unable to complete action with multires enabled') -def Error_NoMeshFaces(): - Draw.PupMenu('Error%t|Mesh has no faces') - -# File I/O messages -def Error_NoFile(path): - '''True if file missing, False if files there - - Use simply by doing... - if Error_NoFile(path): return - ''' - if not sys.exists(sys.expandpath(path)): - Draw.PupMenu("Error%t|Can't open file: " + path) - return True - return False - -def Error_NoDir(path): - '''True if dirs missing, False if dirs there - - Use simply by doing... - if Error_NoDir(path): return - ''' - if not sys.exists(sys.expandpath(path)): - Draw.PupMenu("Error%t|Path does not exist: " + path) - return True - return False - - -def Warning_MeshDistroyLayers(mesh): - '''Returns true if we can continue to edit the mesh, warn when using NMesh''' - if len(mesh.getUVLayerNames()) >1 and len(mesh.getColorLayerNames()) >1: - return True - - ret = Draw.PupMenu('Warning%t|This script will distroy inactive UV and Color layers, OK?') - if ret == -1: - return False - - return True - -def Warning_SaveOver(path): - '''Returns - True to save, False dont save''' - if sys.exists(sys.expandpath(path)): - ret= Draw.PupMenu('Save over%t|' + path) - if ret == -1: - return False - - return True - - diff --git a/release/scripts/bpymodules/BPyNMesh.py b/release/scripts/bpymodules/BPyNMesh.py deleted file mode 100644 index 043d8514db9..00000000000 --- a/release/scripts/bpymodules/BPyNMesh.py +++ /dev/null @@ -1,48 +0,0 @@ -# $Id$ -# -# -------------------------------------------------------------------------- -# BPyNMesh.py version 0.1 -# -------------------------------------------------------------------------- -# helper functions to be used by other scripts -# -------------------------------------------------------------------------- -# ***** 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 ***** -# -------------------------------------------------------------------------- - - -# -------------------------------------------------------------------------- -# "Apply size and rotation" function by Jonas Petersen -# -------------------------------------------------------------------------- -# This function does (hopefully) exactly what the -# "Apply size and rotation" command does (CTRL-A in Object Mode). -def ApplySizeAndRotation(obj): - if obj.getType() != "Mesh": return - if obj.SizeX==1.0 and obj.SizeY==1.0 and obj.SizeZ==1.0 and obj.RotX == 0.0 and obj.RotY == 0.0 and obj.RotZ == 0.0: return - mesh = obj.getData() - matrix = obj.matrix - v = [0,0,0] - for vert in mesh.verts: - co = vert.co - v[0] = co[0]*matrix[0][0] + co[1]*matrix[1][0] + co[2]*matrix[2][0] - v[1] = co[0]*matrix[0][1] + co[1]*matrix[1][1] + co[2]*matrix[2][1] - v[2] = co[0]*matrix[0][2] + co[1]*matrix[1][2] + co[2]*matrix[2][2] - co[0], co[1], co[2] = v - obj.SizeX = obj.SizeY = obj.SizeZ = 1.0 - obj.RotX = obj.RotY = obj.RotZ = 0.0 - mesh.update() - diff --git a/release/scripts/bpymodules/BPyObject.py b/release/scripts/bpymodules/BPyObject.py deleted file mode 100644 index 54ff949218d..00000000000 --- a/release/scripts/bpymodules/BPyObject.py +++ /dev/null @@ -1,108 +0,0 @@ -import Blender - -def getObjectArmature(ob): - ''' - This returns the first armature the mesh uses. - remember there can be more then 1 armature but most people dont do that. - ''' - if ob.type != 'Mesh': - return None - - arm = ob.parent - if arm and arm.type == 'Armature' and ob.parentType == Blender.Object.ParentTypes.ARMATURE: - return arm - - for m in ob.modifiers: - if m.type== Blender.Modifier.Types.ARMATURE: - arm = m[Blender.Modifier.Settings.OBJECT] - if arm: - return arm - - return None - - -def getDerivedObjects(ob, PARTICLES= True): - ''' - Takes an objects and returnes a list of (ob, maxrix4x4) pairs - that are derived from this object - - This will include the object its self if it would be rendered. - all dupli's for eg are not rendered themselves. - - currently supports - * dupligroups - * dupliverts - * dupliframes - * static particles as a mesh - - it is possible this function will return an empty list. - ''' - - ob_mtx_pairs = ob.DupObjects - effects= ob.effects - - # Ignore self if were a dupli* or our parent is a duplivert. - if ob.enableDupFrames or ob.enableDupGroup or ob.enableDupVerts: - pass - else: - parent= ob.parent - if parent and parent.enableDupVerts: - pass - else: - if effects and (not effects[0].flag & Blender.Effect.Flags.EMESH): - # Particles mesh wont render - pass - else: - ob_mtx_pairs.append((ob, ob.matrixWorld)) - - - if PARTICLES: - type_vec= type(Blender.Mathutils.Vector()) - type_tp= type((0,0)) - type_ls= type([]) - - # TODO, particles per child object. - # TODO Support materials - me= Blender.Mesh.New() - for eff in effects: - par= eff.getParticlesLoc() - - if par: - type_par= type(par[0]) - - if type_par == type_vec: - # point particles - me.verts.extend(par) - - elif type_par == type_tp: - # edge pairs - start_index= len(me.verts) - me.verts.extend([v for p in par for v in p]) - me.edges.extend( [(i, i+1) for i in xrange(start_index, start_index + len(par) - 1 )] ) - - elif type_par == type_ls: - # lines of edges - start_index= len(me.verts) - me.verts.extend([v for line in par for v in line]) - - edges= [] - for line in par: - edges.extend( [(i,i+1) for i in xrange(start_index, start_index+len(line)-1) ] ) - start_index+= len(line) - - me.edges.extend(edges) - - if me.verts: - # If we have verts, then add the mesh - ob_par = Blender.Object.New('Mesh') - ob_par.link( me ) - - LOOSE= Blender.Mesh.EdgeFlags.LOOSE - for ed in me.edges: - ed.flag |= LOOSE - - # Particle's are in worldspace so an identity matrix is fine. - ob_mtx_pairs.append( (ob_par, Blender.Mathutils.Matrix()) ) - - return ob_mtx_pairs - - diff --git a/release/scripts/bpymodules/BPyRegistry.py b/release/scripts/bpymodules/BPyRegistry.py deleted file mode 100644 index 4d681e15937..00000000000 --- a/release/scripts/bpymodules/BPyRegistry.py +++ /dev/null @@ -1,267 +0,0 @@ -# -------------------------------------------------------------------------- -# Module BPyRegistry version 0.1 -# Helper functions to store / restore configuration data. -# -------------------------------------------------------------------------- -# $Id$ -# -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Copyright (C) 2004: Willian P. Germano, wgermano _at_ ig.com.br -# -# 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, -# -------------------------------------------------------------------------- - -# The Registry is a Python dictionary that is kept in Blender for as long as -# the program is running, where scripts can store / restore persistent data -# (data that is not lost when the script exits). This module provides -# functions to save and restore Registry entries as config data in the -# bpydata/config folder. Scripts just need to give an extra parameter to -# the Blender.Registry.Get/Set() functions to have their data automatically -# saved and restored when needed. -# -# Note: entries starting with an underscore are not saved, so script authors -# can use that fact to define data that is not meant to be stored in a -# config file. Example: data to be passed to another script and references to -# invalid data, like Blender objects and any function or method. -# -# Check the Blender.Registry documentation for more information. - -import Blender -from Blender import Registry, sys as bsys - -_EXT = '.cfg' # file extension for saved config data - -# limits: -#MAX_ITEMS_NUM = 60 # max number of keys per dict and itens per list and tuple -#MAX_STR_LEN = 300 # max string length (remember this is just for config data) - -_CFG_DIR = '' -if Blender.Get('udatadir'): - _CFG_DIR = Blender.sys.join(Blender.Get('udatadir'), 'config') -if not _CFG_DIR or not bsys.exists(_CFG_DIR): - _CFG_DIR = Blender.sys.join(Blender.Get('datadir'), 'config') -if not bsys.exists(_CFG_DIR): - _CFG_DIR = '' - -# to compare against, so we don't write to a cvs tree: -_CVS_SUBPATH = 'release/scripts/bpydata/config/' -if bsys.dirsep == '\\': - _CVS_SUBPATH = _CVS_SUBPATH.replace('/', '\\') - -_KEYS = [k for k in Registry.Keys() if k[0] != '_'] - -# _ITEMS_NUM = 0 - -def _sanitize(o): - "Check recursively that all objects are valid, set invalid ones to None" - - # global MAX_ITEMS_NUM, MAX_STR_LEN, _ITEMS_NUM - - valid_types = [int, float, bool, long, type] - valid_checked_types = [str, unicode] - # Only very simple types are considered valid for configuration data, - # functions, methods and Blender objects (use their names instead) aren't. - - t = type(o) - - if t == dict: - ''' - _ITEMS_NUM += len(o) - if _ITEMS_NUM > MAX_ITEMS_NUM: - return None - ''' - for k, v in o.iteritems(): - o[k] = _sanitize(v) - elif t in [list, tuple]: - ''' - _ITEMS_NUM += len(o) - if _ITEMS_NUM > MAX_ITEMS_NUM: - return None - ''' - return [_sanitize(i) for i in o] - elif t in valid_types: - return o - elif t in valid_checked_types: - ''' - if len(o) > MAX_STR_LEN: - o = o[:MAX_STR_LEN] - ''' - return o - else: return None - - return o - - -def _dict_to_str(name, d): - "Return a pretty-print version of the passed dictionary" - if not d: return 'None' # d can be None if there was no config to pass - - if name: l = ['%s = {' % name] - else: l = ['{'] - #keys = d.keys() - for k,v in d.iteritems(): # .keys() - if type(v) == dict: - l.append("'%s': %s" % (k, _dict_to_str(None, v))) - else: - l.append("'%s': %s," % (k, repr(v))) - if name: l.append('}') - else: l.append('},') - return "\n".join(l) - -_HELP_MSG = """ -Please create a valid scripts config dir tree either by -copying release/scripts/ tree to your <blenderhome> dir -or by copying release/scripts/bpydata/ tree to a user -defined scripts dir that you can set in the -User Preferences -> Paths tab -> Python path input box. -""" - -def _check_dir(): - global _CFG_DIR, _CVS_SUBPATH, _HELP_MSG - - if not _CFG_DIR: - errmsg = "scripts config dir not found!\n%s" % _HELP_MSG - raise IOError, errmsg - elif _CFG_DIR.find(_CVS_SUBPATH) > 0: - errmsg = """ -Your scripts config dir:\n%s -seems to reside in your local Blender's cvs tree.\n%s""" % (_CFG_DIR, _HELP_MSG) - raise SystemError, errmsg - else: return - - -# API: - -BPY_KEY_MISSING = 0 -BPY_KEY_IN_REGISTRY = 1 -BPY_KEY_IN_FILE = 2 - -def HasConfigData (key): - """ - Check if the given key exists, either already loaded in the Registry dict or - as a file in the script data config dir. - @type key: string - @param key: a given key name. - @returns: - - 0: key does not exist; - - 1: key exists in the Registry dict only; - - 2: key exists as a file only; - - 3: key exists in the Registry dict and also as a file. - @note: for readability it's better to check against the constant bitmasks - BPY_KEY_MISSING = 0, BPY_KEY_IN_REGISTRY = 1 and BPY_KEY_IN_FILE = 2. - """ - - fname = bsys.join(_CFG_DIR, "%s%s" % (key, _EXT)) - - result = BPY_KEY_MISSING - if key in Registry.Keys(): result |= BPY_KEY_IN_REGISTRY - if bsys.exists(fname): result |= BPY_KEY_IN_FILE - - return result - - -def LoadConfigData (key = None): - """ - Load config data from file(s) to the Registry dictionary. - @type key: string - @param key: a given key name. If None (default), all available keys are - loaded. - @returns: None - """ - - _check_dir() - - import os - - if not key: - files = \ - [bsys.join(_CFG_DIR, f) for f in os.listdir(_CFG_DIR) if f.endswith(_EXT)] - else: - files = [] - fname = bsys.join(_CFG_DIR, "%s%s" % (key, _EXT)) - if bsys.exists(fname): files.append(fname) - - for p in files: - try: - f = file(p, 'r') - lines = f.readlines() - f.close() - if lines: # Lines may be blank - mainkey = lines[0].split('=')[0].strip() - pysrc = "\n".join(lines) - exec(pysrc) - exec("Registry.SetKey('%s', %s)" % (str(mainkey), mainkey)) - except Exception, e: - raise Warning(e) # Resend exception as warning - - -def RemoveConfigData (key = None): - """ - Remove this key's config file from the <(u)datadir>/config/ folder. - @type key: string - @param key: the name of the key to be removed. If None (default) all - available config files are deleted. - """ - - _check_dir() - - if not key: - files = \ - [bsys.join(_CFG_DIR, f) for f in os.listdir(_CFG_DIR) if f.endswith(_EXT)] - else: - files = [] - fname = bsys.join(_CFG_DIR, "%s%s" % (key, _EXT)) - if bsys.exists(fname): files.append(fname) - - import os - - try: - for p in files: - os.remove(p) # remove the file(s) - except Exception, e: - raise Warning(e) # Resend exception as warning - - -def SaveConfigData (key = None): - """ - Save Registry key(s) as file(s) in the <(u)datadir>/config/ folder. - @type key: string - @param key: the name of the key to be saved. If None (default) all - available keys are saved. - """ - - global _KEYS, _CFG_DIR - - _check_dir() - - if key: keys = [key] - else: keys = _KEYS - - for mainkey in keys: - cfgdict = Registry.GetKey(mainkey).copy() - for k in cfgdict: # .keys() - if not k or k[0] == '_': - del cfgdict[k] - - if not cfgdict: continue - - try: - filename = bsys.join(_CFG_DIR, "%s%s" % (mainkey, _EXT)) - f = file(filename, 'w') - output = _dict_to_str(mainkey, _sanitize(cfgdict)) - if output!='None': - f.write(output) - f.close() - except Exception, e: - raise Warning(e) # Resend exception as warning diff --git a/release/scripts/bpymodules/BPyRender.py b/release/scripts/bpymodules/BPyRender.py deleted file mode 100644 index 951e1ae6300..00000000000 --- a/release/scripts/bpymodules/BPyRender.py +++ /dev/null @@ -1,633 +0,0 @@ -import Blender -from Blender import Scene, sys, Camera, Object, Image -from Blender.Scene import Render -Vector= Blender.Mathutils.Vector - - -def extFromFormat(format): - if format == Render.TARGA: return 'tga' - if format == Render.RAWTGA: return 'tga' - if format == Render.HDR: return 'hdr' - if format == Render.PNG: return 'png' - if format == Render.BMP: return 'bmp' - if format == Render.JPEG: return 'jpg' - if format == Render.HAMX: return 'ham' - if format == Render.TIFF: return 'tif' - if format == Render.CINEON: return 'cine' - if format == Render.DPX: return 'tif' - if format == Render.OPENEXR: return 'exr' - if format == Render.IRIS: return 'rgb' - return '' - - - -def imageFromObjectsOrtho(objects, path, width, height, smooth, alpha= True, camera_matrix= None, format=Render.PNG): - ''' - Takes any number of objects and renders them on the z axis, between x:y-0 and x:y-1 - Usefull for making images from a mesh without per pixel operations - - objects must be alredy placed - - smooth, anti alias True/False - - path renders to a PNG image - - alpha weather to render background as alpha - - returns the blender image - ''' - ext = '.' + extFromFormat(format) - print ext - # remove an extension if its alredy there - if path.lower().endswith(ext): - path= path[:-4] - - path_expand= sys.expandpath(path) + ext - - print path_expand, 'path' - - # Touch the path - try: - f= open(path_expand, 'w') - f.close() - except: - raise 'Error, could not write to path:' + path_expand - - - # RENDER THE FACES. - scn= Scene.GetCurrent() - render_scn= Scene.New() - render_scn.makeCurrent() - render_scn.Layers |= (1<<20)-1 # all layers enabled - - # Add objects into the current scene - for ob in objects: - render_scn.link(ob) - - render_context= render_scn.getRenderingContext() - render_context.setRenderPath('') # so we can ignore any existing path and save to the abs path. - - - render_context.imageSizeX(width) - render_context.imageSizeY(height) - - if smooth: - render_context.enableOversampling(True) - render_context.setOversamplingLevel(16) - else: - render_context.enableOversampling(False) - - render_context.setRenderWinSize(100) - render_context.setImageType(format) - render_context.enableExtensions(True) - #render_context.enableSky() # No alpha needed. - if alpha: - render_context.alphaMode= 1 - render_context.enableRGBAColor() - else: - render_context.alphaMode= 0 - render_context.enableRGBColor() - - render_context.displayMode= 0 # fullscreen - - # New camera and object - render_cam_data= Camera.New('ortho') - render_cam_ob= Object.New('Camera') - render_cam_ob.link(render_cam_data) - render_scn.link(render_cam_ob) - render_scn.objects.camera = render_cam_ob - - render_cam_data.type= 'ortho' - - - - # Position the camera - if camera_matrix: - render_cam_ob.setMatrix(camera_matrix) - # We need to take into account the matrix scaling when setting the size - # so we get the image bounds defined by the matrix - # first get the x and y factors from the matrix. - # To render the correct dimensions we must use the aspy and aspy to force the matrix scale to - # override the aspect enforced by the width and weight. - cent= Vector() * camera_matrix - xvec= Vector(1,0,0) * camera_matrix - yvec= Vector(0,1,0) * camera_matrix - # zvec= Vector(0,0,1) * camera_matrix - xlen = (cent-xvec).length # half height of the image - ylen = (cent-yvec).length # half width of the image - # zlen = (cent-zvec).length # dist to place the camera? - just use the loc for now. - - - # less then 1.0 portrate, 1.0 or more is portrate - asp_cam_mat= xlen/ylen # divide by zero? - possible but scripters fault. - asp_image_res= float(width)/height - #print 'asp quad', asp_cam_mat, 'asp_image', asp_image_res - #print 'xylen', xlen, ylen, 'w/h', width, height - # Setup the aspect - - if asp_cam_mat > asp_image_res: - # camera is wider then image res. - # to make the image wider, reduce the aspy - asp_diff= asp_image_res/asp_cam_mat - min_asp= asp_diff * 200 - #print 'X', min_asp - - elif asp_cam_mat < asp_image_res: # asp_cam_mat < asp_image_res - # camera is narrower then image res - # to make the image narrower, reduce the aspx - asp_diff= asp_cam_mat/asp_image_res - min_asp= asp_diff * 200 - #print 'Y', min_asp - else: - min_asp= 200 - - # set the camera size - if xlen > ylen: - if asp_cam_mat > asp_image_res: - render_context.aspectX= 200 # get the greatest range possible - render_context.aspectY= min_asp # get the greatest range possible - else: - render_context.aspectY= 200 # get the greatest range possible - render_context.aspectX= min_asp # get the greatest range possible - #print "xlen bigger" - render_cam_data.scale= xlen * 2 - elif xlen < ylen:# ylen is bigger - if asp_cam_mat > asp_image_res: - render_context.aspectX= 200 # get the greatest range possible - render_context.aspectY= min_asp # get the greatest range possible - else: - render_context.aspectY= 200 # get the greatest range possible - render_context.aspectX= min_asp # get the greatest range possible - #print "ylen bigger" - render_cam_data.scale= ylen *2 - else: - # asppect 1:1 - #print 'NOLEN Bigger' - render_cam_data.scale= xlen * 2 - - #print xlen, ylen, 'xlen, ylen' - - else: - if width > height: - min_asp = int((float(height) / width) * 200) - render_context.aspectX= min_asp - render_context.aspectY= 200 - else: - min_asp = int((float(width) / height) * 200) - render_context.aspectX= 200 - render_context.aspectY= min_asp - - - render_cam_data.scale= 1.0 - render_cam_ob.LocZ= 1.0 - render_cam_ob.LocX= 0.5 - render_cam_ob.LocY= 0.5 - - Blender.Window.RedrawAll() - - render_context.render() - render_context.saveRenderedImage(path) - Render.CloseRenderWindow() - #if not B.sys.exists(PREF_IMAGE_PATH_EXPAND): - # raise 'Error!!!' - - scn.makeCurrent() - Scene.Unlink(render_scn) - - # NOW APPLY THE SAVED IMAGE TO THE FACES! - #print PREF_IMAGE_PATH_EXPAND - try: - target_image= Image.Load(path_expand) - return target_image - except: - raise 'Error: Could not render or load the image at path "%s"' % path_expand - return - - - -#-----------------------------------------------------------------------------# -# UV Baking functions, make a picture from mesh(es) uvs # -#-----------------------------------------------------------------------------# - -def mesh2uv(me_s, PREF_SEL_FACES_ONLY=False): - ''' - Converts a uv mapped mesh into a 2D Mesh from UV coords. - returns a triple - - (mesh2d, face_list, col_list) - "mesh" is the new mesh and... - "face_list" is the faces that were used to make the mesh, - "material_list" is a list of materials used by each face - These are in alligned with the meshes faces, so you can easerly copy data between them - - ''' - render_me= Blender.Mesh.New() - render_me.verts.extend( [Vector(0,0,0),] ) # 0 vert uv bugm dummy vert - face_list= [] - material_list= [] - for me in me_s: - me_materials= me.materials - if PREF_SEL_FACES_ONLY: - me_faces= [f for f in me.faces if f.sel] - else: - me_faces= me.faces - - face_list.extend(me_faces) - - # Dittro - if me_materials: - material_list.extend([me_materials[f.mat] for f in me_faces]) - else: - material_list.extend([None]*len(me_faces)) - - # Now add the verts - render_me.verts.extend( [ Vector(uv.x, uv.y, 0) for f in face_list for uv in f.uv ] ) - - # Now add the faces - tmp_faces= [] - vert_offset= 1 - for f in face_list: - tmp_faces.append( [ii+vert_offset for ii in xrange(len(f))] ) - vert_offset+= len(f) - - render_me.faces.extend(tmp_faces) - render_me.faceUV=1 - return render_me, face_list, material_list - - -def uvmesh_apply_normals(render_me, face_list): - '''Worldspace normals to vertex colors''' - for i, f in enumerate(render_me.faces): - face_orig= face_list[i] - f_col= f.col - for j, v in enumerate(face_orig): - c= f_col[j] - nx, ny, nz= v.no - c.r= int((nx+1)*128)-1 - c.g= int((ny+1)*128)-1 - c.b= int((nz+1)*128)-1 - -def uvmesh_apply_image(render_me, face_list): - '''Copy the image and uvs from the original faces''' - for i, f in enumerate(render_me.faces): - f.uv= face_list[i].uv - f.image= face_list[i].image - - -def uvmesh_apply_vcol(render_me, face_list): - '''Copy the vertex colors from the original faces''' - for i, f in enumerate(render_me.faces): - face_orig= face_list[i] - f_col= f.col - for j, c_orig in enumerate(face_orig.col): - c= f_col[j] - c.r= c_orig.r - c.g= c_orig.g - c.b= c_orig.b - -def uvmesh_apply_matcol(render_me, material_list): - '''Get the vertex colors from the original materials''' - for i, f in enumerate(render_me.faces): - mat_orig= material_list[i] - f_col= f.col - if mat_orig: - for c in f_col: - c.r= int(mat_orig.R*255) - c.g= int(mat_orig.G*255) - c.b= int(mat_orig.B*255) - else: - for c in f_col: - c.r= 255 - c.g= 255 - c.b= 255 - -def uvmesh_apply_col(render_me, color): - '''Get the vertex colors from the original materials''' - r,g,b= color - for i, f in enumerate(render_me.faces): - f_col= f.col - for c in f_col: - c.r= r - c.g= g - c.b= b - - -def vcol2image(me_s,\ - PREF_IMAGE_PATH,\ - PREF_IMAGE_SIZE,\ - PREF_IMAGE_BLEED,\ - PREF_IMAGE_SMOOTH,\ - PREF_IMAGE_WIRE,\ - PREF_IMAGE_WIRE_INVERT,\ - PREF_IMAGE_WIRE_UNDERLAY,\ - PREF_USE_IMAGE,\ - PREF_USE_VCOL,\ - PREF_USE_MATCOL,\ - PREF_USE_NORMAL,\ - PREF_USE_TEXTURE,\ - PREF_SEL_FACES_ONLY): - - - def rnd_mat(): - render_mat= Blender.Material.New() - mode= render_mat.mode - - # Dont use lights ever - mode |= Blender.Material.Modes.SHADELESS - - if PREF_IMAGE_WIRE: - # Set the wire color - if PREF_IMAGE_WIRE_INVERT: - render_mat.rgbCol= (1,1,1) - else: - render_mat.rgbCol= (0,0,0) - - mode |= Blender.Material.Modes.WIRE - if PREF_USE_VCOL or PREF_USE_MATCOL or PREF_USE_NORMAL: # both vcol and material color use vertex cols to avoid the 16 max limit in materials - mode |= Blender.Material.Modes.VCOL_PAINT - if PREF_USE_IMAGE: - mode |= Blender.Material.Modes.TEXFACE - - # Copy back the mode - render_mat.mode |= mode - return render_mat - - - render_me, face_list, material_list= mesh2uv(me_s, PREF_SEL_FACES_ONLY) - - # Normals exclude all others - if PREF_USE_NORMAL: - uvmesh_apply_normals(render_me, face_list) - else: - if PREF_USE_IMAGE: - uvmesh_apply_image(render_me, face_list) - uvmesh_apply_vcol(render_me, face_list) - - elif PREF_USE_VCOL: - uvmesh_apply_vcol(render_me, face_list) - - elif PREF_USE_MATCOL: - uvmesh_apply_matcol(render_me, material_list) - - elif PREF_USE_TEXTURE: - # if we have more then 16 materials across all the mesh objects were stuffed :/ - # get unique materials - tex_unique_materials= dict([(mat.name, mat) for mat in material_list]).values()[:16] # just incase we have more then 16 - tex_me= Blender.Mesh.New() - - # Backup the original shadless setting - tex_unique_materials_shadeless= [ mat.mode & Blender.Material.Modes.SHADELESS for mat in tex_unique_materials ] - - # Turn shadeless on - for mat in tex_unique_materials: - mat.mode |= Blender.Material.Modes.SHADELESS - - # Assign materials - render_me.materials= tex_unique_materials - - - - tex_material_indicies= dict([(mat.name, i) for i, mat in enumerate(tex_unique_materials)]) - - tex_me.verts.extend([Vector(0,0,0),]) # dummy - tex_me.verts.extend( [ Vector(v.co) for f in face_list for v in f ] ) - - # Now add the faces - tmp_faces= [] - vert_offset= 1 - for f in face_list: - tmp_faces.append( [ii+vert_offset for ii in xrange(len(f))] ) - vert_offset+= len(f) - - tex_me.faces.extend(tmp_faces) - - # Now we have the faces, put materials and normal, uvs into the mesh - if len(tex_me.faces) != len(face_list): - # Should never happen - raise "Error face length mismatch" - - # Copy data to the mesh that could be used as texture coords - for i, tex_face in enumerate(tex_me.faces): - orig_face= face_list[i] - - # Set the material index - try: - render_face.mat= tex_material_indicies[ material_list[i].name ] - except: - # more then 16 materials - pass - - - # set the uvs on the texmesh mesh - tex_face.uv= orig_face.uv - - orig_face_v= orig_face.v - # Set the normals - for j, v in enumerate(tex_face): - v.no= orig_face_v[j].no - - # Set the texmesh - render_me.texMesh= tex_me - # END TEXMESH - - - # Handel adding objects - render_ob= Blender.Object.New('Mesh') - render_ob.link(render_me) - - if not PREF_USE_TEXTURE: # textures use the original materials - render_me.materials= [rnd_mat()] - - - obs= [render_ob] - - - if PREF_IMAGE_WIRE_UNDERLAY: - # Make another mesh with the material colors - render_me_under, face_list, material_list= mesh2uv(me_s, PREF_SEL_FACES_ONLY) - - uvmesh_apply_matcol(render_me_under, material_list) - - # Handel adding objects - render_ob= Blender.Object.New('Mesh') - render_ob.link(render_me_under) - render_ob.LocZ= -0.01 - - # Add material and disable wire - mat= rnd_mat() - mat.rgbCol= 1,1,1 - mat.alpha= 0.5 - mat.mode &= ~Blender.Material.Modes.WIRE - mat.mode |= Blender.Material.Modes.VCOL_PAINT - - render_me_under.materials= [mat] - - obs.append(render_ob) - - elif PREF_IMAGE_BLEED and not PREF_IMAGE_WIRE: - # EVIL BLEEDING CODE!! - Just do copys of the mesh and place behind. Crufty but better then many other methods I have seen. - Cam - BLEED_PIXEL= 1.0/PREF_IMAGE_SIZE - z_offset= 0.0 - for i in xrange(PREF_IMAGE_BLEED): - for diag1, diag2 in ((-1,-1),(-1,1),(1,-1),(1,1), (1,0), (0,1), (-1,0), (0, -1)): # This line extends the object in 8 different directions, top avoid bleeding. - - render_ob= Blender.Object.New('Mesh') - render_ob.link(render_me) - - render_ob.LocX= (i+1)*diag1*BLEED_PIXEL - render_ob.LocY= (i+1)*diag2*BLEED_PIXEL - render_ob.LocZ= -z_offset - - obs.append(render_ob) - z_offset += 0.01 - - - - image= imageFromObjectsOrtho(obs, PREF_IMAGE_PATH, PREF_IMAGE_SIZE, PREF_IMAGE_SIZE, PREF_IMAGE_SMOOTH) - - # Clear from memory as best as we can - render_me.verts= None - - if PREF_IMAGE_WIRE_UNDERLAY: - render_me_under.verts= None - - if PREF_USE_TEXTURE: - tex_me.verts= None - # Restire Shadeless setting - for i, mat in enumerate(tex_unique_materials): - # we know there all on so turn it off of its not set - if not tex_unique_materials_shadeless[i]: - mat.mode &= ~Blender.Material.Modes.SHADELESS - - return image - -def bakeToPlane(sce, ob_from, width, height, bakemodes, axis='z', margin=0, depth=32): - ''' - Bakes terrain onto a plane from one object - sce - scene to bake with - ob_from - mesh object - width/height - image size - bakemodes - list of baking modes to use, Blender.Scene.Render.BakeModes.NORMALS, Blender.Scene.Render.BakeModes.AO ... etc - axis - axis to allign the plane to. - margin - margin setting for baking. - depth - bit depth for the images to bake into, (32 or 128 for floating point images) - Example: - import Blender - from Blender import * - import BPyRender - sce = Scene.GetCurrent() - ob = Object.Get('Plane') - BPyRender.bakeToPlane(sce, ob, 512, 512, [Scene.Render.BakeModes.DISPLACEMENT, Scene.Render.BakeModes.NORMALS], 'z', 8 ) - ''' - - # Backup bake settings - rend = sce.render - BACKUP_bakeDist = rend.bakeDist - BACKUP_bakeBias = rend.bakeBias - BACKUP_bakeMode = rend.bakeMode - BACKUP_bakeClear = rend.bakeClear - BACKUP_bakeMargin = rend.bakeMargin - BACKUP_bakeToActive = rend.bakeToActive - BACKUP_bakeNormalize = rend.bakeNormalize - - # Backup object selection - BACKUP_obsel = list(sce.objects.selected) - BACKUP_obact = sce.objects.active - - # New bake settings - rend.bakeClear = True - rend.bakeMargin = margin - rend.bakeToActive = True - rend.bakeNormalize = True - - # Assume a mesh - me_from = ob_from.getData(mesh=1) - - xmin = ymin = zmin = 10000000000 - xmax = ymax = zmax =-10000000000 - - # Dont trust bounding boxes :/ - #bounds = ob_from.boundingBox - #for v in bounds: - # x,y,z = tuple(v) - mtx = ob_from.matrixWorld - for v in me_from.verts: - x,y,z = tuple(v.co*mtx) - - xmax = max(xmax, x) - ymax = max(ymax, y) - zmax = max(zmax, z) - - xmin = min(xmin, x) - ymin = min(ymin, y) - zmin = min(zmin, z) - - if axis=='x': - xmed = (xmin+xmax)/2.0 - co1 = (xmed, ymin, zmin) - co2 = (xmed, ymin, zmax) - co3 = (xmed, ymax, zmax) - co4 = (xmed, ymax, zmin) - rend.bakeDist = ((xmax-xmin)/2.0) + 0.000001 # we need a euler value for this since it - elif axis=='y': - ymed = (ymin+ymax)/2.0 - co1 = (xmin, ymed, zmin) - co2 = (xmin, ymed, zmax) - co3 = (xmax, ymed, zmax) - co4 = (xmax, ymed, zmin) - rend.bakeDist = ((ymax-ymin)/2.0) + 0.000001 - elif axis=='z': - zmed = (zmin+zmax)/2.0 - co1 = (xmin, ymin, zmed) - co2 = (xmin, ymax, zmed) - co3 = (xmax, ymax, zmed) - co4 = (xmax, ymin, zmed) - rend.bakeDist = ((zmax-zmin)/2.0) + 0.000001 - else: - raise "invalid axis" - me_plane = Blender.Mesh.New() - ob_plane = Blender.Object.New('Mesh') - ob_plane.link(me_plane) - sce.objects.link(ob_plane) - ob_plane.Layers = ob_from.Layers - - ob_from.sel = 1 # make active - sce.objects.active = ob_plane - ob_plane.sel = 1 - - me_plane.verts.extend([co4, co3, co2, co1]) - me_plane.faces.extend([(0,1,2,3)]) - me_plane.faceUV = True - me_plane_face = me_plane.faces[0] - uvs = me_plane_face.uv - uvs[0].x = 0.0; uvs[0].y = 0.0 - uvs[1].x = 0.0; uvs[1].y = 1.0 - uvs[2].x = 1.0; uvs[2].y = 1.0 - uvs[3].x = 1.0; uvs[3].y = 0.0 - - images_return = [] - - for mode in bakemodes: - img = Blender.Image.New('bake', width, height, depth) - - me_plane_face.image = img - rend.bakeMode = mode - rend.bake() - images_return.append( img ) - - # Restore bake settings - #''' - rend.bakeDist = BACKUP_bakeDist - rend.bakeBias = BACKUP_bakeBias - rend.bakeMode = BACKUP_bakeMode - rend.bakeClear = BACKUP_bakeClear - rend.bakeMargin = BACKUP_bakeMargin - rend.bakeToActive = BACKUP_bakeToActive - rend.bakeNormalize = BACKUP_bakeNormalize - - - # Restore obsel - sce.objects.selected = BACKUP_obsel - sce.objects.active = BACKUP_obact - - me_plane.verts = None - sce.objects.unlink(ob_plane) - #''' - - return images_return - diff --git a/release/scripts/bpymodules/BPySys.py b/release/scripts/bpymodules/BPySys.py deleted file mode 100644 index a2d2120ebff..00000000000 --- a/release/scripts/bpymodules/BPySys.py +++ /dev/null @@ -1,74 +0,0 @@ - -## This was used to make V, but faster not to do all that -##valid = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_' -##v = range(255) -##for c in valid: v.remove(ord(c)) -v = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,46,47,58,59,60,61,62,63,64,91,92,93,94,96,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254] -invalid = ''.join([chr(i) for i in v]) -## del v, c, i, valid -del v, i - -def cleanName(name): - for ch in invalid: name = name.replace(ch, '_') - return name - -def caseInsensitivePath(path, RET_FOUND=False): - ''' - Get a case insensitive path on a case sensitive system - - RET_FOUND is for internal use only, to avoid too many calls to os.path.exists - # Example usage - getCaseInsensitivePath('/hOmE/mE/sOmEpAtH.tXt') - ''' - import os # todo, what happens with no os? - - if os==None: - if RET_FOUND: ret = path, True - else: ret = path - return ret - - if path=='' or os.path.exists(path): - if RET_FOUND: ret = path, True - else: ret = path - return ret - - f = os.path.basename(path) # f may be a directory or a file - d = os.path.dirname(path) - - suffix = '' - if not f: # dir ends with a slash? - if len(d) < len(path): - suffix = path[:len(path)-len(d)] - - f = os.path.basename(d) - d = os.path.dirname(d) - - if not os.path.exists(d): - d, found = caseInsensitivePath(d, True) - - if not found: - if RET_FOUND: ret = path, False - else: ret = path - return ret - - # at this point, the directory exists but not the file - - try: # we are expecting 'd' to be a directory, but it could be a file - files = os.listdir(d) - except: - if RET_FOUND: ret = path, False - else: ret = path - - f_low = f.lower() - - try: f_nocase = [fl for fl in files if fl.lower() == f_low][0] - except: f_nocase = None - - if f_nocase: - if RET_FOUND: ret = os.path.join(d, f_nocase) + suffix, True - else: ret = os.path.join(d, f_nocase) + suffix - return ret - else: - if RET_FOUND: ret = path, False - else: ret = path - return ret # cant find the right one, just return the path as is.
\ No newline at end of file diff --git a/release/scripts/bpymodules/BPyTextPlugin.py b/release/scripts/bpymodules/BPyTextPlugin.py deleted file mode 100644 index cd5a085de37..00000000000 --- a/release/scripts/bpymodules/BPyTextPlugin.py +++ /dev/null @@ -1,814 +0,0 @@ -"""The BPyTextPlugin Module - -Use get_cached_descriptor(txt) to retrieve information about the script held in -the txt Text object. - -Use print_cache_for(txt) to print the information to the console. - -Use line, cursor = current_line(txt) to get the logical line and cursor position - -Use get_targets(line, cursor) to find out what precedes the cursor: - aaa.bbb.cc|c.ddd -> ['aaa', 'bbb', 'cc'] - -Use resolve_targets(txt, targets) to turn a target list into a usable object if -one is found to match. -""" - -import bpy, sys, os -import __builtin__, tokenize -from Blender.sys import time -from tokenize import generate_tokens, TokenError, \ - COMMENT, DEDENT, INDENT, NAME, NEWLINE, NL, STRING, NUMBER - -class Definition: - """Describes a definition or defined object through its name, line number - and docstring. This is the base class for definition based descriptors. - """ - - def __init__(self, name, lineno, doc=''): - self.name = name - self.lineno = lineno - self.doc = doc - -class ScriptDesc: - """Describes a script through lists of further descriptor objects (classes, - defs, vars) and dictionaries to built-in types (imports). If a script has - not been fully parsed, its incomplete flag will be set. The time of the last - parse is held by the time field and the name of the text object from which - it was parsed, the name field. - """ - - def __init__(self, name, imports, classes, defs, vars, incomplete=False): - self.name = name - self.imports = imports - self.classes = classes - self.defs = defs - self.vars = vars - self.incomplete = incomplete - self.parse_due = 0 - - def set_delay(self, delay): - self.parse_due = time() + delay - -class ClassDesc(Definition): - """Describes a class through lists of further descriptor objects (defs and - vars). The name of the class is held by the name field and the line on - which it is defined is held in lineno. - """ - - def __init__(self, name, parents, defs, vars, lineno, doc=''): - Definition.__init__(self, name, lineno, doc) - self.parents = parents - self.defs = defs - self.vars = vars - -class FunctionDesc(Definition): - """Describes a function through its name and list of parameters (name, - params) and the line on which it is defined (lineno). - """ - - def __init__(self, name, params, lineno, doc=''): - Definition.__init__(self, name, lineno, doc) - self.params = params - -class VarDesc(Definition): - """Describes a variable through its name and type (if ascertainable) and the - line on which it is defined (lineno). If no type can be determined, type - will equal None. - """ - - def __init__(self, name, type, lineno): - Definition.__init__(self, name, lineno) - self.type = type # None for unknown (supports: dict/list/str) - -# Context types -CTX_UNSET = -1 -CTX_NORMAL = 0 -CTX_SINGLE_QUOTE = 1 -CTX_DOUBLE_QUOTE = 2 -CTX_COMMENT = 3 - -# Python keywords -KEYWORDS = ['and', 'del', 'from', 'not', 'while', 'as', 'elif', 'global', - 'or', 'with', 'assert', 'else', 'if', 'pass', 'yield', - 'break', 'except', 'import', 'print', 'class', 'exec', 'in', - 'raise', 'continue', 'finally', 'is', 'return', 'def', 'for', - 'lambda', 'try' ] - -# Module file extensions -MODULE_EXTS = ['.py', '.pyc', '.pyo', '.pyw', '.pyd'] - -ModuleType = type(__builtin__) -NoneScriptDesc = ScriptDesc('', dict(), dict(), dict(), dict(), True) - -_modules = {} -_modules_updated = 0 -_parse_cache = dict() - -def _load_module_names(): - """Searches the sys.path for module files and lists them, along with - sys.builtin_module_names, in the global dict _modules. - """ - - global _modules - - for n in sys.builtin_module_names: - _modules[n] = None - for p in sys.path: - if p == '': p = os.curdir - if not os.path.isdir(p): continue - for f in os.listdir(p): - for ext in MODULE_EXTS: - if f.endswith(ext): - _modules[f[:-len(ext)]] = None - break - -_load_module_names() - -def _trim_doc(doc): - """Trims the quotes from a quoted STRING token (eg. "'''text'''" -> "text") - """ - - l = len(doc) - i = 0 - while i < l/2 and (doc[i] == "'" or doc[i] == '"'): - i += 1 - return doc[i:-i] - -def resolve_targets(txt, targets): - """Attempts to return a useful object for the locally or externally defined - entity described by targets. If the object is local (defined in txt), a - Definition instance is returned. If the object is external (imported or - built in), the object itself is returned. If no object can be found, None is - returned. - """ - - count = len(targets) - if count==0: return None - - obj = None - local = None - i = 1 - - desc = get_cached_descriptor(txt) - b = targets[0].find('(') - if b==-1: b = None # Trick to let us use [:b] and get the whole string - - if desc.classes.has_key(targets[0][:b]): - local = desc.classes[targets[0][:b]] - elif desc.defs.has_key(targets[0]): - local = desc.defs[targets[0]] - elif desc.vars.has_key(targets[0]): - obj = desc.vars[targets[0]].type - - if local: - while i < count: - b = targets[i].find('(') - if b==-1: b = None - if hasattr(local, 'classes') and local.classes.has_key(targets[i][:b]): - local = local.classes[targets[i][:b]] - elif hasattr(local, 'defs') and local.defs.has_key(targets[i]): - local = local.defs[targets[i]] - elif hasattr(local, 'vars') and local.vars.has_key(targets[i]): - obj = local.vars[targets[i]].type - local = None - i += 1 - break - else: - local = None - break - i += 1 - - if local: return local - - if not obj: - if desc.imports.has_key(targets[0]): - obj = desc.imports[targets[0]] - else: - builtins = get_builtins() - if builtins.has_key(targets[0]): - obj = builtins[targets[0]] - - while obj and i < count: - if hasattr(obj, targets[i]): - obj = getattr(obj, targets[i]) - else: - obj = None - break - i += 1 - - return obj - -def get_cached_descriptor(txt, force_parse=0): - """Returns the cached ScriptDesc for the specified Text object 'txt'. If the - script has not been parsed in the last 'period' seconds it will be reparsed - to obtain this descriptor. - - Specifying TP_AUTO for the period (default) will choose a period based on the - size of the Text object. Larger texts are parsed less often. - """ - - global _parse_cache - - parse = True - key = hash(txt) - if not force_parse and _parse_cache.has_key(key): - desc = _parse_cache[key] - if desc.parse_due > time(): - parse = desc.incomplete - - if parse: - desc = parse_text(txt) - - return desc - -def parse_text(txt): - """Parses an entire script's text and returns a ScriptDesc instance - containing information about the script. - - If the text is not a valid Python script (for example if brackets are left - open), parsing may fail to complete. However, if this occurs, no exception - is thrown. Instead the returned ScriptDesc instance will have its incomplete - flag set and information processed up to this point will still be accessible. - """ - - start_time = time() - txt.reset() - tokens = generate_tokens(txt.readline) # Throws TokenError - - curl, cursor = txt.getCursorPos() - linen = curl + 1 # Token line numbers are one-based - - imports = dict() - imp_step = 0 - - classes = dict() - cls_step = 0 - - defs = dict() - def_step = 0 - - vars = dict() - var1_step = 0 - var2_step = 0 - var3_step = 0 - var_accum = dict() - var_forflag = False - - indent = 0 - prev_type = -1 - prev_text = '' - incomplete = False - - while True: - try: - type, text, start, end, line = tokens.next() - except StopIteration: - break - except (TokenError, IndentationError): - incomplete = True - break - - # Skip all comments and line joining characters - if type == COMMENT or type == NL: - continue - - ################# - ## Indentation ## - ################# - - if type == INDENT: - indent += 1 - elif type == DEDENT: - indent -= 1 - - ######################### - ## Module importing... ## - ######################### - - imp_store = False - - # Default, look for 'from' or 'import' to start - if imp_step == 0: - if text == 'from': - imp_tmp = [] - imp_step = 1 - elif text == 'import': - imp_from = None - imp_tmp = [] - imp_step = 2 - - # Found a 'from', create imp_from in form '???.???...' - elif imp_step == 1: - if text == 'import': - imp_from = '.'.join(imp_tmp) - imp_tmp = [] - imp_step = 2 - elif type == NAME: - imp_tmp.append(text) - elif text != '.': - imp_step = 0 # Invalid syntax - - # Found 'import', imp_from is populated or None, create imp_name - elif imp_step == 2: - if text == 'as': - imp_name = '.'.join(imp_tmp) - imp_step = 3 - elif type == NAME or text == '*': - imp_tmp.append(text) - elif text != '.': - imp_name = '.'.join(imp_tmp) - imp_symb = imp_name - imp_store = True - - # Found 'as', change imp_symb to this value and go back to step 2 - elif imp_step == 3: - if type == NAME: - imp_symb = text - else: - imp_store = True - - # Both imp_name and imp_symb have now been populated so we can import - if imp_store: - - # Handle special case of 'import *' - if imp_name == '*': - parent = get_module(imp_from) - imports.update(parent.__dict__) - - else: - # Try importing the name as a module - try: - if imp_from: - module = get_module(imp_from +'.'+ imp_name) - else: - module = get_module(imp_name) - except (ImportError, ValueError, AttributeError, TypeError): - # Try importing name as an attribute of the parent - try: - module = __import__(imp_from, globals(), locals(), [imp_name]) - imports[imp_symb] = getattr(module, imp_name) - except (ImportError, ValueError, AttributeError, TypeError): - pass - else: - imports[imp_symb] = module - - # More to import from the same module? - if text == ',': - imp_tmp = [] - imp_step = 2 - else: - imp_step = 0 - - ################### - ## Class parsing ## - ################### - - # If we are inside a class then def and variable parsing should be done - # for the class. Otherwise the definitions are considered global - - # Look for 'class' - if cls_step == 0: - if text == 'class': - cls_name = None - cls_lineno = start[0] - cls_indent = indent - cls_step = 1 - - # Found 'class', look for cls_name followed by '(' parents ')' - elif cls_step == 1: - if not cls_name: - if type == NAME: - cls_name = text - cls_sline = False - cls_parents = dict() - cls_defs = dict() - cls_vars = dict() - elif type == NAME: - if classes.has_key(text): - parent = classes[text] - cls_parents[text] = parent - cls_defs.update(parent.defs) - cls_vars.update(parent.vars) - elif text == ':': - cls_step = 2 - - # Found 'class' name ... ':', now check if it's a single line statement - elif cls_step == 2: - if type == NEWLINE: - cls_sline = False - else: - cls_sline = True - cls_doc = '' - cls_step = 3 - - elif cls_step == 3: - if not cls_doc and type == STRING: - cls_doc = _trim_doc(text) - if cls_sline: - if type == NEWLINE: - classes[cls_name] = ClassDesc(cls_name, cls_parents, cls_defs, cls_vars, cls_lineno, cls_doc) - cls_step = 0 - else: - if type == DEDENT and indent <= cls_indent: - classes[cls_name] = ClassDesc(cls_name, cls_parents, cls_defs, cls_vars, cls_lineno, cls_doc) - cls_step = 0 - - ################# - ## Def parsing ## - ################# - - # Look for 'def' - if def_step == 0: - if text == 'def': - def_name = None - def_lineno = start[0] - def_step = 1 - - # Found 'def', look for def_name followed by '(' - elif def_step == 1: - if type == NAME: - def_name = text - def_params = [] - elif def_name and text == '(': - def_step = 2 - - # Found 'def' name '(', now identify the parameters upto ')' - # TODO: Handle ellipsis '...' - elif def_step == 2: - if type == NAME: - def_params.append(text) - elif text == ':': - def_step = 3 - - # Found 'def' ... ':', now check if it's a single line statement - elif def_step == 3: - if type == NEWLINE: - def_sline = False - else: - def_sline = True - def_doc = '' - def_step = 4 - - elif def_step == 4: - if type == STRING: - def_doc = _trim_doc(text) - newdef = None - if def_sline: - if type == NEWLINE: - newdef = FunctionDesc(def_name, def_params, def_lineno, def_doc) - else: - if type == NAME: - newdef = FunctionDesc(def_name, def_params, def_lineno, def_doc) - if newdef: - if cls_step > 0: # Parsing a class - cls_defs[def_name] = newdef - else: - defs[def_name] = newdef - def_step = 0 - - ########################## - ## Variable assignation ## - ########################## - - if cls_step > 0: # Parsing a class - # Look for 'self.???' - if var1_step == 0: - if text == 'self': - var1_step = 1 - elif var1_step == 1: - if text == '.': - var_name = None - var1_step = 2 - else: - var1_step = 0 - elif var1_step == 2: - if type == NAME: - var_name = text - if cls_vars.has_key(var_name): - var_step = 0 - else: - var1_step = 3 - elif var1_step == 3: - if text == '=': - var1_step = 4 - elif text != ',': - var1_step = 0 - elif var1_step == 4: - var_type = None - if type == NUMBER: - close = end[1] - if text.find('.') != -1: var_type = float - else: var_type = int - elif type == STRING: - close = end[1] - var_type = str - elif text == '[': - close = line.find(']', end[1]) - var_type = list - elif text == '(': - close = line.find(')', end[1]) - var_type = tuple - elif text == '{': - close = line.find('}', end[1]) - var_type = dict - elif text == 'dict': - close = line.find(')', end[1]) - var_type = dict - if var_type and close+1 < len(line): - if line[close+1] != ' ' and line[close+1] != '\t': - var_type = None - cls_vars[var_name] = VarDesc(var_name, var_type, start[0]) - var1_step = 0 - - elif def_step > 0: # Parsing a def - # Look for 'global ???[,???]' - if var2_step == 0: - if text == 'global': - var2_step = 1 - elif var2_step == 1: - if type == NAME: - if not vars.has_key(text): - vars[text] = VarDesc(text, None, start[0]) - elif text != ',' and type != NL: - var2_step == 0 - - else: # In global scope - if var3_step == 0: - # Look for names - if text == 'for': - var_accum = dict() - var_forflag = True - elif text == '=' or (var_forflag and text == 'in'): - var_forflag = False - var3_step = 1 - elif type == NAME: - if prev_text != '.' and not vars.has_key(text): - var_accum[text] = VarDesc(text, None, start[0]) - elif not text in [',', '(', ')', '[', ']']: - var_accum = dict() - var_forflag = False - elif var3_step == 1: - if len(var_accum) != 1: - var_type = None - vars.update(var_accum) - else: - var_name = var_accum.keys()[0] - var_type = None - if type == NUMBER: - if text.find('.') != -1: var_type = float - else: var_type = int - elif type == STRING: var_type = str - elif text == '[': var_type = list - elif text == '(': var_type = tuple - elif text == '{': var_type = dict - vars[var_name] = VarDesc(var_name, var_type, start[0]) - var3_step = 0 - - ####################### - ## General utilities ## - ####################### - - prev_type = type - prev_text = text - - desc = ScriptDesc(txt.name, imports, classes, defs, vars, incomplete) - desc.set_delay(10 * (time()-start_time) + 0.05) - - global _parse_cache - _parse_cache[hash(txt)] = desc - return desc - -def get_modules(since=1): - """Returns the set of built-in modules and any modules that have been - imported into the system upto 'since' seconds ago. - """ - - global _modules, _modules_updated - - t = time() - if _modules_updated < t - since: - _modules.update(sys.modules) - _modules_updated = t - return _modules.keys() - -def suggest_cmp(x, y): - """Use this method when sorting a list of suggestions. - """ - - return cmp(x[0].upper(), y[0].upper()) - -def get_module(name): - """Returns the module specified by its name. The module itself is imported - by this method and, as such, any initialization code will be executed. - """ - - mod = __import__(name) - components = name.split('.') - for comp in components[1:]: - mod = getattr(mod, comp) - return mod - -def type_char(v): - """Returns the character used to signify the type of a variable. Use this - method to identify the type character for an item in a suggestion list. - - The following values are returned: - 'm' if the parameter is a module - 'f' if the parameter is callable - 'v' if the parameter is variable or otherwise indeterminable - - """ - - if isinstance(v, ModuleType): - return 'm' - elif callable(v): - return 'f' - else: - return 'v' - -def get_context(txt): - """Establishes the context of the cursor in the given Blender Text object - - Returns one of: - CTX_NORMAL - Cursor is in a normal context - CTX_SINGLE_QUOTE - Cursor is inside a single quoted string - CTX_DOUBLE_QUOTE - Cursor is inside a double quoted string - CTX_COMMENT - Cursor is inside a comment - - """ - - l, cursor = txt.getCursorPos() - lines = txt.asLines(0, l+1) - - # FIXME: This method is too slow in large files for it to be called as often - # as it is. So for lines below the 1000th line we do this... (quorn) - if l > 1000: return CTX_NORMAL - - # Detect context (in string or comment) - in_str = CTX_NORMAL - for line in lines: - if l == 0: - end = cursor - else: - end = len(line) - l -= 1 - - # Comments end at new lines - if in_str == CTX_COMMENT: - in_str = CTX_NORMAL - - for i in range(end): - if in_str == 0: - if line[i] == "'": in_str = CTX_SINGLE_QUOTE - elif line[i] == '"': in_str = CTX_DOUBLE_QUOTE - elif line[i] == '#': in_str = CTX_COMMENT - else: - if in_str == CTX_SINGLE_QUOTE: - if line[i] == "'": - in_str = CTX_NORMAL - # In again if ' escaped, out again if \ escaped, and so on - for a in range(i-1, -1, -1): - if line[a] == '\\': in_str = 1-in_str - else: break - elif in_str == CTX_DOUBLE_QUOTE: - if line[i] == '"': - in_str = CTX_NORMAL - # In again if " escaped, out again if \ escaped, and so on - for a in range(i-1, -1, -1): - if line[i-a] == '\\': in_str = 2-in_str - else: break - - return in_str - -def current_line(txt): - """Extracts the Python script line at the cursor in the Blender Text object - provided and cursor position within this line as the tuple pair (line, - cursor). - """ - - lineindex, cursor = txt.getCursorPos() - lines = txt.asLines() - line = lines[lineindex] - - # Join previous lines to this line if spanning - i = lineindex - 1 - while i > 0: - earlier = lines[i].rstrip() - if earlier.endswith('\\'): - line = earlier[:-1] + ' ' + line - cursor += len(earlier) - i -= 1 - - # Join later lines while there is an explicit joining character - i = lineindex - while i < len(lines)-1 and lines[i].rstrip().endswith('\\'): - later = lines[i+1].strip() - line = line + ' ' + later[:-1] - i += 1 - - return line, cursor - -def get_targets(line, cursor): - """Parses a period separated string of valid names preceding the cursor and - returns them as a list in the same order. - """ - - brk = 0 - targets = [] - j = cursor - i = j-1 - while i >= 0: - if line[i] == ')': brk += 1 - elif brk: - if line[i] == '(': brk -= 1 - else: - if line[i] == '.': - targets.insert(0, line[i+1:j]); j=i - elif not (line[i].isalnum() or line[i] == '_' or line[i] == '.'): - break - i -= 1 - targets.insert(0, line[i+1:j]) - return targets - -def get_defs(txt): - """Returns a dictionary which maps definition names in the source code to - a list of their parameter names. - - The line 'def doit(one, two, three): print one' for example, results in the - mapping 'doit' : [ 'one', 'two', 'three' ] - """ - - return get_cached_descriptor(txt).defs - -def get_vars(txt): - """Returns a dictionary of variable names found in the specified Text - object. This method locates all names followed directly by an equal sign: - 'a = ???' or indirectly as part of a tuple/list assignment or inside a - 'for ??? in ???:' block. - """ - - return get_cached_descriptor(txt).vars - -def get_imports(txt): - """Returns a dictionary which maps symbol names in the source code to their - respective modules. - - The line 'from Blender import Text as BText' for example, results in the - mapping 'BText' : <module 'Blender.Text' (built-in)> - - Note that this method imports the modules to provide this mapping as as such - will execute any initilization code found within. - """ - - return get_cached_descriptor(txt).imports - -def get_builtins(): - """Returns a dictionary of built-in modules, functions and variables.""" - - return __builtin__.__dict__ - - -################################# -## Debugging utility functions ## -################################# - -def print_cache_for(txt, period=sys.maxint): - """Prints out the data cached for a given Text object. If no period is - given the text will not be reparsed and the cached version will be returned. - Otherwise if the period has expired the text will be reparsed. - """ - - desc = get_cached_descriptor(txt, period) - print '================================================' - print 'Name:', desc.name, '('+str(hash(txt))+')' - print '------------------------------------------------' - print 'Defs:' - for name, ddesc in desc.defs.items(): - print ' ', name, ddesc.params, ddesc.lineno - print ' ', ddesc.doc - print '------------------------------------------------' - print 'Vars:' - for name, vdesc in desc.vars.items(): - print ' ', name, vdesc.type, vdesc.lineno - print '------------------------------------------------' - print 'Imports:' - for name, item in desc.imports.items(): - print ' ', name.ljust(15), item - print '------------------------------------------------' - print 'Classes:' - for clsnme, clsdsc in desc.classes.items(): - print ' *********************************' - print ' Name:', clsnme - print ' ', clsdsc.doc - print ' ---------------------------------' - print ' Defs:' - for name, ddesc in clsdsc.defs.items(): - print ' ', name, ddesc.params, ddesc.lineno - print ' ', ddesc.doc - print ' ---------------------------------' - print ' Vars:' - for name, vdesc in clsdsc.vars.items(): - print ' ', name, vdesc.type, vdesc.lineno - print ' *********************************' - print '================================================' diff --git a/release/scripts/bpymodules/BPyWindow.py b/release/scripts/bpymodules/BPyWindow.py deleted file mode 100644 index d3fd4fa88b5..00000000000 --- a/release/scripts/bpymodules/BPyWindow.py +++ /dev/null @@ -1,206 +0,0 @@ -import Blender -from Blender import Mathutils, Window, Scene, Draw, Mesh -from Blender.Mathutils import Matrix, Vector, Intersect - -# DESCRIPTION: -# screen_x, screen_y the origin point of the pick ray -# it is either the mouse location -# localMatrix is used if you want to have the returned values in an objects localspace. -# this is usefull when dealing with an objects data such as verts. -# or if useMid is true, the midpoint of the current 3dview -# returns -# Origin - the origin point of the pick ray -# Direction - the direction vector of the pick ray -# in global coordinates -epsilon = 1e-3 # just a small value to account for floating point errors - -def mouseViewRay(screen_x, screen_y, localMatrix=None, useMid = False): - - # Constant function variables - p = mouseViewRay.p - d = mouseViewRay.d - - for win3d in Window.GetScreenInfo(Window.Types.VIEW3D): # we search all 3dwins for the one containing the point (screen_x, screen_y) (could be the mousecoords for example) - win_min_x, win_min_y, win_max_x, win_max_y = win3d['vertices'] - # calculate a few geometric extents for this window - - win_mid_x = (win_max_x + win_min_x + 1.0) * 0.5 - win_mid_y = (win_max_y + win_min_y + 1.0) * 0.5 - win_size_x = (win_max_x - win_min_x + 1.0) * 0.5 - win_size_y = (win_max_y - win_min_y + 1.0) * 0.5 - - #useMid is for projecting the coordinates when we subdivide the screen into bins - if useMid: # == True - screen_x = win_mid_x - screen_y = win_mid_y - - # if the given screencoords (screen_x, screen_y) are within the 3dwin we fount the right one... - if (win_max_x > screen_x > win_min_x) and ( win_max_y > screen_y > win_min_y): - # first we handle all pending events for this window (otherwise the matrices might come out wrong) - Window.QHandle(win3d['id']) - - # now we get a few matrices for our window... - # sorry - i cannot explain here what they all do - # - if you're not familiar with all those matrices take a look at an introduction to OpenGL... - pm = Window.GetPerspMatrix() # the prespective matrix - pmi = Matrix(pm); pmi.invert() # the inverted perspective matrix - - if (1.0 - epsilon < pmi[3][3] < 1.0 + epsilon): - # pmi[3][3] is 1.0 if the 3dwin is in ortho-projection mode (toggled with numpad 5) - hms = mouseViewRay.hms - ortho_d = mouseViewRay.ortho_d - - # ortho mode: is a bit strange - actually there's no definite location of the camera ... - # but the camera could be displaced anywhere along the viewing direction. - - ortho_d.x, ortho_d.y, ortho_d.z = Window.GetViewVector() - ortho_d.w = 0 - - # all rays are parallel in ortho mode - so the direction vector is simply the viewing direction - #hms.x, hms.y, hms.z, hms.w = (screen_x-win_mid_x) /win_size_x, (screen_y-win_mid_y) / win_size_y, 0.0, 1.0 - hms[:] = (screen_x-win_mid_x) /win_size_x, (screen_y-win_mid_y) / win_size_y, 0.0, 1.0 - - # these are the homogenious screencoords of the point (screen_x, screen_y) ranging from -1 to +1 - p=(hms*pmi) + (1000*ortho_d) - p.resize3D() - d[:] = ortho_d[:3] - - - # Finally we shift the position infinitely far away in - # the viewing direction to make sure the camera if outside the scene - # (this is actually a hack because this function - # is used in sculpt_mesh to initialize backface culling...) - else: - # PERSPECTIVE MODE: here everything is well defined - all rays converge at the camera's location - vmi = Matrix(Window.GetViewMatrix()); vmi.invert() # the inverse viewing matrix - fp = mouseViewRay.fp - - dx = pm[3][3] * (((screen_x-win_min_x)/win_size_x)-1.0) - pm[3][0] - dy = pm[3][3] * (((screen_y-win_min_y)/win_size_y)-1.0) - pm[3][1] - - fp[:] = \ - pmi[0][0]*dx+pmi[1][0]*dy,\ - pmi[0][1]*dx+pmi[1][1]*dy,\ - pmi[0][2]*dx+pmi[1][2]*dy - - # fp is a global 3dpoint obtained from "unprojecting" the screenspace-point (screen_x, screen_y) - #- figuring out how to calculate this took me quite some time. - # The calculation of dxy and fp are simplified versions of my original code - #- so it's almost impossible to explain what's going on geometrically... sorry - - p[:] = vmi[3][:3] - - # the camera's location in global 3dcoords can be read directly from the inverted viewmatrix - #d.x, d.y, d.z =normalize_v3(sub_v3v3(p, fp)) - d[:] = p.x-fp.x, p.y-fp.y, p.z-fp.z - - #print 'd', d, 'p', p, 'fp', fp - - - # the direction vector is simply the difference vector from the virtual camera's position - #to the unprojected (screenspace) point fp - - # Do we want to return a direction in object's localspace? - - if localMatrix: - localInvMatrix = Matrix(localMatrix) - localInvMatrix.invert() - localInvMatrix_notrans = localInvMatrix.rotationPart() - p = p * localInvMatrix - d = d * localInvMatrix # normalize_v3 - - # remove the translation from d - d.x -= localInvMatrix[3][0] - d.y -= localInvMatrix[3][1] - d.z -= localInvMatrix[3][2] - - - d.normalize() - ''' - # Debugging - me = Blender.Mesh.New() - me.verts.extend([p[0:3]]) - me.verts.extend([(p-d)[0:3]]) - me.edges.extend([0,1]) - ob = Blender.Scene.GetCurrent().objects.new(me) - ''' - return True, p, d # Origin, Direction - - # Mouse is not in any view, return None. - return False, None, None - -# Constant function variables -mouseViewRay.d = Vector(0,0,0) # Perspective, 3d -mouseViewRay.p = Vector(0,0,0) -mouseViewRay.fp = Vector(0,0,0) - -mouseViewRay.hms = Vector(0,0,0,0) # ortho only 4d -mouseViewRay.ortho_d = Vector(0,0,0,0) # ortho only 4d - - -LMB= Window.MButs['L'] -def mouseup(): - # Loop until click - mouse_buttons = Window.GetMouseButtons() - while not mouse_buttons & LMB: - Blender.sys.sleep(10) - mouse_buttons = Window.GetMouseButtons() - while mouse_buttons & LMB: - Blender.sys.sleep(10) - mouse_buttons = Window.GetMouseButtons() - - -if __name__=='__main__': - mouseup() - x,y= Window.GetMouseCoords() - isect, point, dir= mouseViewRay(x,y) - if isect: - scn= Blender.Scene.GetCurrent() - me = Blender.Mesh.New() - ob= Blender.Object.New('Mesh') - ob.link(me) - scn.link(ob) - ob.sel= 1 - me.verts.extend([point, dir]) - me.verts[0].sel= 1 - - print isect, point, dir - - - -def spaceRect(): - ''' - Returns the space rect - xmin,ymin,width,height - ''' - - __UI_RECT__ = Blender.BGL.Buffer(Blender.BGL.GL_FLOAT, 4) - Blender.BGL.glGetFloatv(Blender.BGL.GL_SCISSOR_BOX, __UI_RECT__) - __UI_RECT__ = __UI_RECT__.list - __UI_RECT__ = int(__UI_RECT__[0]), int(__UI_RECT__[1]), int(__UI_RECT__[2])-1, int(__UI_RECT__[3]) - - return __UI_RECT__ - -def mouseRelativeLoc2d(__UI_RECT__= None): - if not __UI_RECT__: - __UI_RECT__ = spaceRect() - - mco = Window.GetMouseCoords() - if mco[0] > __UI_RECT__[0] and\ - mco[1] > __UI_RECT__[1] and\ - mco[0] < __UI_RECT__[0] + __UI_RECT__[2] and\ - mco[1] < __UI_RECT__[1] + __UI_RECT__[3]: - - return (mco[0] - __UI_RECT__[0], mco[1] - __UI_RECT__[1]) - - else: - return None - - - - - - - - -
\ No newline at end of file diff --git a/release/scripts/bpymodules/blend2renderinfo.py b/release/scripts/bpymodules/blend2renderinfo.py deleted file mode 100644 index 1b9dec58d55..00000000000 --- a/release/scripts/bpymodules/blend2renderinfo.py +++ /dev/null @@ -1,95 +0,0 @@ -#!/usr/bin/python - -# -------------------------------------------------------------------------- -# ***** 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 ***** -# -------------------------------------------------------------------------- - -import struct - -# In Blender, selecting scenes in the databrowser (shift+f4) will tag for rendering. - -# This struct wont change according to ton. -# Note that the size differs on 32/64bit -''' -typedef struct BHead { - int code, len; - void *old; - int SDNAnr, nr; -} BHead; -''' - - -def read_blend_rend_chunk(path): - file = open(path, 'rb') - - if file.read(len('BLENDER')) != 'BLENDER': - return [] - - # - if file.read(1) == '-': - is64bit = True - else: # '_' - is64bit = False - - if file.read(1) == 'V': - isBigEndian = True # ppc - else: # 'V' - isBigEndian = False # x86 - - - # Now read the bhead chunk!!! - file.read(3) # skip the version - - scenes = [] - - while file.read(4) == 'REND': - - if is64bit: sizeof_bhead = sizeof_bhead_left = 24 # 64bit - else: sizeof_bhead = sizeof_bhead_left = 20 # 32bit - - sizeof_bhead_left -= 4 - - if isBigEndian: rend_length = struct.unpack('>i', file.read(4))[0] - else: rend_length = struct.unpack('<i', file.read(4))[0] - - sizeof_bhead_left -= 4 - - # We dont care about the rest of the bhead struct - file.read(sizeof_bhead_left) - - # Now we want the scene name, start and end frame. this is 32bites long - - if isBigEndian: start_frame, end_frame = struct.unpack('>2i', file.read(8)) - else: start_frame, end_frame = struct.unpack('<2i', file.read(8)) - - scene_name = file.read(24) - scene_name = scene_name[ : scene_name.index('\0') ] - - scenes.append( (start_frame, end_frame, scene_name) ) - return scenes - -def main(): - import sys - for arg in sys.argv[1:]: - if arg.lower().endswith('.blend'): - print read_blend_rend_chunk(arg) - -if __name__ == '__main__': - main() - diff --git a/release/scripts/bpymodules/defaultdoodads.py b/release/scripts/bpymodules/defaultdoodads.py deleted file mode 100644 index 987b8b8ae71..00000000000 --- a/release/scripts/bpymodules/defaultdoodads.py +++ /dev/null @@ -1,941 +0,0 @@ -# Default Doodad Set for Discombobulator -# by Evan J. Rosky, 2005 -# GPL- http://www.gnu.org/copyleft/gpl.html -# -# $Id$ -# -------------------------------------------------------------------------- -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Copyright (C) 2005: Evan J. Rosky -# -# 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 ***** -# -------------------------------------------------------------------------- - - -#Run discombobulator.py, not this. - -import Blender -from Blender import NMesh,Object,Material -from Blender.NMesh import Vert,Face -from Blender.Mathutils import * - -import BPyMathutils -from BPyMathutils import genrand -a = BPyMathutils.sgenrand(4859) - -#Create random numbers -def randnum(low,high): - num = genrand() - num = num*(high-low) - num = num+low - return num - -face = Face() -xmin = Vector([0,0,0]) -xmax = Vector([0,0,0]) -ymin = Vector([0,0,0]) -ymax = Vector([0,0,0]) -mxmin = Vector([0,0,0]) -mxmax = Vector([0,0,0]) -mymin = Vector([0,0,0]) -mymax = Vector([0,0,0]) -doodadCenter = Vector([0,0,0]) -orientation = 0 -center = Vector([0,0,0]) -tosel = 0 -seltopsonly = 0 -tempx = [] -doodadMesh = NMesh.GetRaw() - -global materialArray -global reassignMats -global thereAreMats -global currmat -global doodSideMat -global doodTopMat - -#face is the face to add the doodad to. -#sizeX and sizeY are values from 0.0 to 1.0 that represents a percentage the face that is covered by the doodad. -#height is how tall the doodad is. - -def settings(seltops,matArr,reasMats,therMats,sidemat,topmat): - global seltopsonly - global materialArray - global reassignMats - global thereAreMats - global currmat - global doodSideMat - global doodTopMat - materialArray = matArr - reassignMats = reasMats - thereAreMats = therMats - seltopsonly = seltops - doodSideMat = sidemat - doodTopMat = topmat - -def setCurrMat(curma): - global currmat - currmat = curma - -#Find center and orientation of doodad -def findDoodadCenter(sizeX, sizeY): - #globalizing junk - global face - global xmin - global xmax - global ymin - global ymax - global orientation - global doodadCenter - global center - global tosel - global mxmin - global mxmax - global mymin - global mymax - global tempx - global seltopsonly - - #Find the center of the face - center = Vector([0,0,0]) - for pt in face.v: - center = center + pt.co - center = divideVectorByInt(center,len(face.v)) - - #Find Temp Location Range by looking at the sizes - txmin = ((divideVectorByInt((face.v[0].co + face.v[3].co),2)) - center)*(1-sizeX) + center - txmax = ((divideVectorByInt((face.v[1].co + face.v[2].co),2)) - center)*(1-sizeX) + center - tymin = ((divideVectorByInt((face.v[0].co + face.v[1].co),2)) - center)*(1-sizeY) + center - tymax = ((divideVectorByInt((face.v[2].co + face.v[3].co),2)) - center)*(1-sizeY) + center - - #Find Center of doodad - amtx = randnum(0.0,1.0) - amty = randnum(0.0,1.0) - thepoint = (((((txmin - txmax)*amtx + txmax) - ((tymin - tymax)*amty + tymax))*.5 + ((tymin - tymax)*amty + tymax)) - center)*2 + center - doodadCenter = Vector([thepoint[0],thepoint[1],thepoint[2]]) - - #Find Main Range by looking at the sizes - mxmin = divideVectorByInt((face.v[0].co + face.v[3].co),2) - mxmax = divideVectorByInt((face.v[1].co + face.v[2].co),2) - mymin = divideVectorByInt((face.v[0].co + face.v[1].co),2) - mymax = divideVectorByInt((face.v[2].co + face.v[3].co),2) - - #Find x/y equivs for whole face - ve1 = (txmin - txmax)*amtx + txmax - ve1 = ve1 - mxmax - nax = ve1.length - ve1 = (mxmin - mxmax) - nax = nax/ve1.length - - ve1 = (tymin - tymax)*amty + tymax - ve1 = ve1 - mymax - nay = ve1.length - ve1 = (mymin - mymax) - nay = nay/ve1.length - - #Find new box thing - tempx = [] - amtx = nax-sizeX/2 - amty = nay-sizeY/2 - tempx.append((((((mxmin - mxmax)*amtx + mxmax) - ((mymin - mymax)*amty + mymax))*.5 + ((mymin - mymax)*amty + mymax)) - center)*2 + center) - - amtx = nax-sizeX/2 - amty = nay+sizeY/2 - tempx.append((((((mxmin - mxmax)*amtx + mxmax) - ((mymin - mymax)*amty + mymax))*.5 + ((mymin - mymax)*amty + mymax)) - center)*2 + center) - - amtx = nax+sizeX/2 - amty = nay+sizeY/2 - tempx.append((((((mxmin - mxmax)*amtx + mxmax) - ((mymin - mymax)*amty + mymax))*.5 + ((mymin - mymax)*amty + mymax)) - center)*2 + center) - - amtx = nax+sizeX/2 - amty = nay-sizeY/2 - tempx.append((((((mxmin - mxmax)*amtx + mxmax) - ((mymin - mymax)*amty + mymax))*.5 + ((mymin - mymax)*amty + mymax)) - center)*2 + center) - - #Find New Location Range by looking at the sizes - xmin = divideVectorByInt((tempx[0] + tempx[3]),2) - xmax = divideVectorByInt((tempx[1] + tempx[2]),2) - ymin = divideVectorByInt((tempx[0] + tempx[1]),2) - ymax = divideVectorByInt((tempx[2] + tempx[3]),2) - -#Make a point -def makePoint(x,y,z=0): - global xmin - global xmax - global ymin - global ymax - global doodadCenter - global tosel - global seltopsonly - global face - - amtx = x - amty = y - thepoint = (((((xmin - xmax)*amtx + xmax) - ((ymin - ymax)*amty + ymax))*.5 + ((ymin - ymax)*amty + ymax)) - doodadCenter)*2 + doodadCenter - thepoint = thepoint + z*Vector(face.no) - tver = Vert(thepoint[0],thepoint[1],thepoint[2]) - if tosel == 1 and seltopsonly == 0 and z == 0: - tver.sel = 1 - return tver - -#extrude ground-plane(s) -def extrudedoodad(vArray,heig): - global face - global doodadMesh - global tosel - - topVArray = [] - - doodadMesh.verts.extend(vArray) - - #Create array for extruded verts - for ind in range(0,(len(vArray))): - point = vArray[ind].co + heig*Vector(face.no) - ver = Vert(point[0],point[1],point[2]) - if tosel == 1: - ver.sel = 1 - topVArray.append(ver) - doodadMesh.verts.append(topVArray[ind]) - - #make faces around sides - for ind in range(0,(len(vArray) - 1)): - face = Face() - face.v.extend([vArray[ind],vArray[ind+1],topVArray[ind+1],topVArray[ind]]) - if tosel == 1 and seltopsonly == 0: face.sel = 1 - if thereAreMats == 1: - if reassignMats == 0 or doodSideMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = doodSideMat-1 - doodadMesh.faces.append(face) - face = Face() - face.v.extend([vArray[len(vArray) - 1],vArray[0],topVArray[0],topVArray[len(topVArray) - 1]]) - if tosel == 1 and seltopsonly == 0: - face.sel = 1 - if thereAreMats == 1: - if reassignMats == 0 or doodSideMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = doodSideMat-1 - doodadMesh.faces.append(face) - - return topVArray - -#For switching face vertices -def fixvertindex(ind): - if ind > 3: - indx = ind - 4 - else: - indx = ind - return indx - -#runs doodads -def createDoodad(indexArray,facec,minsi,maxsi,minhei,maxhei,selec,amtmin,amtmax,facpercent): - global doodadMesh - global seltopsonly - global tosel - - doodadMesh = NMesh.GetRaw() - - theamt = round(randnum(amtmin,amtmax),0) - theamt = int(theamt) - tosel = selec - - for i in range(0,(theamt)): - if randnum(0,1) <= facpercent: - index = round(randnum(1,len(indexArray)),0) - index = indexArray[(int(index) - 1)] - - Xsi = randnum(minsi,maxsi) - Ysi = randnum(minsi,maxsi) - hei = randnum(minhei,maxhei) - - #Determine orientation - orient = int(round(randnum(0.0,3.0))) - - #face to use as range - facer = Face() - facer.v.extend([facec.v[orient],facec.v[fixvertindex(1+orient)],facec.v[fixvertindex(2+orient)],facec.v[fixvertindex(3+orient)]]) - - if index == 1: - singleBox(facer,Xsi,Ysi,hei) - if index == 2: - doubleBox(facer,Xsi,Ysi,hei) - if index == 3: - tripleBox(facer,Xsi,Ysi,hei) - if index == 4: - LShape(facer,Xsi,Ysi,hei) - if index == 5: - TShape(facer,Xsi,Ysi,hei) - if index == 6: - if randnum(0.0,1.0) > .5: - SShape(facer,Xsi,Ysi,hei) - else: - ZShape(facer,Xsi,Ysi,hei) - - return doodadMesh - -def divideVectorByInt(thevect,theint): - thevect.x = thevect.x/theint - thevect.y = thevect.y/theint - thevect.z = thevect.z/theint - return thevect - -#Single Box Doodad -def singleBox(facel, Xsize, Ysize, height): - #globaling junk - global face - global tosel - global doodadMesh - - face = Face() - face = facel - - findDoodadCenter(Xsize, Ysize) - - vertArray = [] - - #place four points - vertArray.append(makePoint(0,0)) - vertArray.append(makePoint(0,1)) - vertArray.append(makePoint(1,1)) - vertArray.append(makePoint(1,0)) - topVertArray = extrudedoodad(vertArray,height) - - face = Face() - face.v.extend(vertArray) - face.v.reverse() - doodadMesh.faces.append(face) - face = Face() - face.v.extend(topVertArray) - if tosel == 1: - face.sel = 1 - if thereAreMats == 1: - if reassignMats == 0 or doodTopMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = doodTopMat-1 - doodadMesh.faces.append(face) - -#Double Box Doodad -def doubleBox(facel, Xsize, Ysize, height): - #globaling junk - global face - global tosel - global doodadMesh - - face = Face() - face = facel - - findDoodadCenter(Xsize, Ysize) - - vertArray = [] - - #place first box - vertArray.append(makePoint(0,0)) - vertArray.append(makePoint(0,1)) - vertArray.append(makePoint(0.45,1)) - vertArray.append(makePoint(0.45,0)) - topVertArray = extrudedoodad(vertArray,height) - - face = Face() - face.v.extend(vertArray) - face.v.reverse() - doodadMesh.faces.append(face) - face = Face() - face.v.extend(topVertArray) - if tosel == 1: - face.sel = 1 - if thereAreMats == 1: - if reassignMats == 0 or doodTopMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = doodTopMat-1 - doodadMesh.faces.append(face) - - vertArray = [] - - #place second box - vertArray.append(makePoint(0.55,0)) - vertArray.append(makePoint(0.55,1)) - vertArray.append(makePoint(1,1)) - vertArray.append(makePoint(1,0)) - topVertArray = extrudedoodad(vertArray,height) - - face = Face() - face.v.extend(vertArray) - face.v.reverse() - doodadMesh.faces.append(face) - face = Face() - face.v.extend(topVertArray) - if tosel == 1: - face.sel = 1 - if thereAreMats == 1: - if reassignMats == 0 or doodTopMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = doodTopMat-1 - doodadMesh.faces.append(face) - -#Triple Box Doodad -def tripleBox(facel, Xsize, Ysize, height): - #globaling junk - global face - global tosel - global doodadMesh - - face = Face() - face = facel - - findDoodadCenter(Xsize, Ysize) - - vertArray = [] - - #place first box - vertArray.append(makePoint(0,0)) - vertArray.append(makePoint(0,1)) - vertArray.append(makePoint(0.3,1)) - vertArray.append(makePoint(0.3,0)) - topVertArray = extrudedoodad(vertArray,height) - - face = Face() - face.v.extend(vertArray) - face.v.reverse() - doodadMesh.faces.append(face) - face = Face() - face.v.extend(topVertArray) - if tosel == 1: - face.sel = 1 - if thereAreMats == 1: - if reassignMats == 0 or doodTopMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = doodTopMat-1 - doodadMesh.faces.append(face) - - vertArray = [] - - #place second box - vertArray.append(makePoint(0.35,0)) - vertArray.append(makePoint(0.35,1)) - vertArray.append(makePoint(0.65,1)) - vertArray.append(makePoint(0.65,0)) - topVertArray = extrudedoodad(vertArray,height) - - face = Face() - face.v.extend(vertArray) - face.v.reverse() - doodadMesh.faces.append(face) - face = Face() - face.v.extend(topVertArray) - if tosel == 1: - face.sel = 1 - if thereAreMats == 1: - if reassignMats == 0 or doodTopMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = doodTopMat-1 - doodadMesh.faces.append(face) - - vertArray = [] - - #place third box - vertArray.append(makePoint(0.7,0)) - vertArray.append(makePoint(0.7,1)) - vertArray.append(makePoint(1,1)) - vertArray.append(makePoint(1,0)) - topVertArray = extrudedoodad(vertArray,height) - - face = Face() - face.v.extend(vertArray) - face.v.reverse() - doodadMesh.faces.append(face) - face = Face() - face.v.extend(topVertArray) - if tosel == 1: - face.sel = 1 - if thereAreMats == 1: - if reassignMats == 0 or doodTopMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = doodTopMat-1 - doodadMesh.faces.append(face) - -#The "L" Shape -def LShape(facel, Xsize, Ysize, height): - #globaling junk - global face - global tosel - global doodadMesh - - face = Face() - face = facel - - findDoodadCenter(Xsize, Ysize) - - rcon1 = randnum(0.2,0.8) - rcon2 = randnum(0.2,0.8) - - vertArray = [] - - #place L shape - vertArray.append(makePoint(0,0)) - vertArray.append(makePoint(0,rcon1)) - vertArray.append(makePoint(0,1)) - vertArray.append(makePoint(rcon2,1)) - vertArray.append(makePoint(rcon2,rcon1)) - vertArray.append(makePoint(1,rcon1)) - vertArray.append(makePoint(1,0)) - vertArray.append(makePoint(rcon2,0)) - topVertArray = extrudedoodad(vertArray,height) - - #This fills in the bottom of doodad with faceness - face = Face() - face.v.extend([vertArray[0],vertArray[1],vertArray[4],vertArray[7]]) - face.v.reverse() - if thereAreMats == 1: - if reassignMats == 0 or doodTopMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = doodTopMat-1 - doodadMesh.faces.append(face) - face = Face() - face.v.extend([vertArray[1],vertArray[2],vertArray[3],vertArray[4]]) - face.v.reverse() - if thereAreMats == 1: - if reassignMats == 0 or doodTopMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = doodTopMat-1 - doodadMesh.faces.append(face) - face = Face() - face.v.extend([vertArray[4],vertArray[5],vertArray[6],vertArray[7]]) - face.v.reverse() - if thereAreMats == 1: - if reassignMats == 0 or doodTopMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = doodTopMat-1 - doodadMesh.faces.append(face) - - #This fills in the top with faceness - face = Face() - face.v.extend([topVertArray[0],topVertArray[1],topVertArray[4],topVertArray[7]]) - if tosel == 1: - face.sel = 1 - if thereAreMats == 1: - if reassignMats == 0 or doodTopMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = doodTopMat-1 - doodadMesh.faces.append(face) - face = Face() - face.v.extend([topVertArray[1],topVertArray[2],topVertArray[3],topVertArray[4]]) - if tosel == 1: - face.sel = 1 - if thereAreMats == 1: - if reassignMats == 0 or doodTopMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = doodTopMat-1 - doodadMesh.faces.append(face) - face = Face() - face.v.extend([topVertArray[4],topVertArray[5],topVertArray[6],topVertArray[7]]) - if tosel == 1: - face.sel = 1 - if thereAreMats == 1: - if reassignMats == 0 or doodTopMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = doodTopMat-1 - doodadMesh.faces.append(face) - -#The "T" Shape -def TShape(facel, Xsize, Ysize, height): - #globaling junk - global face - global tosel - global doodadMesh - - face = Face() - face = facel - - findDoodadCenter(Xsize, Ysize) - - rcony = randnum(0.25,0.75) - rconx1 = randnum(0.1,0.49) - rconx2 = randnum(0.51,0.9) - - vertArray = [] - - #place T shape - vertArray.append(makePoint(0,0)) - vertArray.append(makePoint(0,rcony)) - vertArray.append(makePoint(rconx1,rcony)) - vertArray.append(makePoint(rconx1,1)) - vertArray.append(makePoint(rconx2,1)) - vertArray.append(makePoint(rconx2,rcony)) - vertArray.append(makePoint(1,rcony)) - vertArray.append(makePoint(1,0)) - vertArray.append(makePoint(rconx2,0)) - vertArray.append(makePoint(rconx1,0)) - topVertArray = extrudedoodad(vertArray,height) - - #fills bottom with faceness - face = Face() - face.v.extend([vertArray[0],vertArray[1],vertArray[2],vertArray[9]]) - face.v.reverse() - if thereAreMats == 1: - if reassignMats == 0 or doodTopMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = doodTopMat-1 - doodadMesh.faces.append(face) - face = Face() - face.v.extend([vertArray[2],vertArray[3],vertArray[4],vertArray[5]]) - face.v.reverse() - if thereAreMats == 1: - if reassignMats == 0 or doodTopMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = doodTopMat-1 - doodadMesh.faces.append(face) - face = Face() - face.v.extend([vertArray[5],vertArray[6],vertArray[7],vertArray[8]]) - face.v.reverse() - if thereAreMats == 1: - if reassignMats == 0 or doodTopMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = doodTopMat-1 - doodadMesh.faces.append(face) - face = Face() - face.v.extend([vertArray[8],vertArray[9],vertArray[2],vertArray[5]]) - face.v.reverse() - if thereAreMats == 1: - if reassignMats == 0 or doodTopMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = doodTopMat-1 - doodadMesh.faces.append(face) - - #fills top with faceness - face = Face() - face.v.extend([topVertArray[0],topVertArray[1],topVertArray[2],topVertArray[9]]) - if tosel == 1: - face.sel = 1 - if thereAreMats == 1: - if reassignMats == 0 or doodTopMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = doodTopMat-1 - doodadMesh.faces.append(face) - face = Face() - face.v.extend([topVertArray[2],topVertArray[3],topVertArray[4],topVertArray[5]]) - if tosel == 1: - face.sel = 1 - if thereAreMats == 1: - if reassignMats == 0 or doodTopMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = doodTopMat-1 - doodadMesh.faces.append(face) - face = Face() - face.v.extend([topVertArray[5],topVertArray[6],topVertArray[7],topVertArray[8]]) - if tosel == 1: - face.sel = 1 - if thereAreMats == 1: - if reassignMats == 0 or doodTopMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = doodTopMat-1 - doodadMesh.faces.append(face) - face = Face() - face.v.extend([topVertArray[8],topVertArray[9],topVertArray[2],topVertArray[5]]) - if tosel == 1: - face.sel = 1 - if thereAreMats == 1: - if reassignMats == 0 or doodTopMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = doodTopMat-1 - doodadMesh.faces.append(face) - -#The "S" or "Z" Shapes -def SShape(facel, Xsize, Ysize, height): - #globaling junk - global face - global tosel - global doodadMesh - - face = Face() - face = facel - - findDoodadCenter(Xsize, Ysize) - - rcony1 = randnum(0.1,0.49) - rcony2 = randnum(0.51,0.9) - rconx1 = randnum(0.1,0.49) - rconx2 = randnum(0.51,0.9) - - vertArray = [] - - #place S shape - vertArray.append(makePoint(0,0)) - vertArray.append(makePoint(0,rcony1)) - vertArray.append(makePoint(rconx1,rcony1)) - vertArray.append(makePoint(rconx1,rcony2)) - vertArray.append(makePoint(rconx1,1)) - vertArray.append(makePoint(rconx2,1)) - vertArray.append(makePoint(1,1)) - vertArray.append(makePoint(1,rcony2)) - vertArray.append(makePoint(rconx2,rcony2)) - vertArray.append(makePoint(rconx2,rcony1)) - vertArray.append(makePoint(rconx2,0)) - vertArray.append(makePoint(rconx1,0)) - topVertArray = extrudedoodad(vertArray,height) - - #fills bottom with faceness - face = Face() - face.v.extend([vertArray[0],vertArray[1],vertArray[2],vertArray[11]]) - face.v.reverse() - if thereAreMats == 1: - if reassignMats == 0 or doodTopMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = doodTopMat-1 - doodadMesh.faces.append(face) - face = Face() - face.v.extend([vertArray[2],vertArray[9],vertArray[10],vertArray[11]]) - face.v.reverse() - if thereAreMats == 1: - if reassignMats == 0 or doodTopMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = doodTopMat-1 - doodadMesh.faces.append(face) - face = Face() - face.v.extend([vertArray[2],vertArray[3],vertArray[8],vertArray[9]]) - face.v.reverse() - if thereAreMats == 1: - if reassignMats == 0 or doodTopMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = doodTopMat-1 - doodadMesh.faces.append(face) - face = Face() - face.v.extend([vertArray[3],vertArray[4],vertArray[5],vertArray[8]]) - face.v.reverse() - if thereAreMats == 1: - if reassignMats == 0 or doodTopMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = doodTopMat-1 - doodadMesh.faces.append(face) - face = Face() - face.v.extend([vertArray[5],vertArray[6],vertArray[7],vertArray[8]]) - face.v.reverse() - if thereAreMats == 1: - if reassignMats == 0 or doodTopMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = doodTopMat-1 - doodadMesh.faces.append(face) - - #fills top with faceness - face = Face() - face.v.extend([topVertArray[0],topVertArray[1],topVertArray[2],topVertArray[11]]) - if tosel == 1: - face.sel = 1 - if thereAreMats == 1: - if reassignMats == 0 or doodTopMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = doodTopMat-1 - doodadMesh.faces.append(face) - face = Face() - face.v.extend([topVertArray[2],topVertArray[9],topVertArray[10],topVertArray[11]]) - if tosel == 1: - face.sel = 1 - if thereAreMats == 1: - if reassignMats == 0 or doodTopMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = doodTopMat-1 - doodadMesh.faces.append(face) - face = Face() - face.v.extend([topVertArray[2],topVertArray[3],topVertArray[8],topVertArray[9]]) - if tosel == 1: - face.sel = 1 - if thereAreMats == 1: - if reassignMats == 0 or doodTopMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = doodTopMat-1 - doodadMesh.faces.append(face) - face = Face() - face.v.extend([topVertArray[3],topVertArray[4],topVertArray[5],topVertArray[8]]) - if tosel == 1: - face.sel = 1 - if thereAreMats == 1: - if reassignMats == 0 or doodTopMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = doodTopMat-1 - doodadMesh.faces.append(face) - face = Face() - face.v.extend([topVertArray[5],topVertArray[6],topVertArray[7],topVertArray[8]]) - if tosel == 1: - face.sel = 1 - if thereAreMats == 1: - if reassignMats == 0 or doodTopMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = doodTopMat-1 - doodadMesh.faces.append(face) - -def ZShape(facel, Xsize, Ysize, height): - #globaling junk - global face - global tosel - global doodadMesh - - face = Face() - face = facel - - findDoodadCenter(Xsize, Ysize) - - rcony1 = randnum(0.1,0.49) - rcony2 = randnum(0.51,0.9) - rconx1 = randnum(0.1,0.49) - rconx2 = randnum(0.51,0.9) - - vertArray = [] - - #place Z shape - vertArray.append(makePoint(0,0)) - vertArray.append(makePoint(0,rcony1)) - vertArray.append(makePoint(0,rcony2)) - vertArray.append(makePoint(rconx1,rcony2)) - vertArray.append(makePoint(rconx2,rcony2)) - vertArray.append(makePoint(rconx2,1)) - vertArray.append(makePoint(1,1)) - vertArray.append(makePoint(1,rcony2)) - vertArray.append(makePoint(1,rcony1)) - vertArray.append(makePoint(rconx2,rcony1)) - vertArray.append(makePoint(rconx1,rcony1)) - vertArray.append(makePoint(rconx1,0)) - topVertArray = extrudedoodad(vertArray,height) - - #fills bottom with faceness - face = Face() - face.v.extend([vertArray[0],vertArray[1],vertArray[10],vertArray[11]]) - face.v.reverse() - if thereAreMats == 1: - if reassignMats == 0 or doodTopMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = doodTopMat-1 - doodadMesh.faces.append(face) - face = Face() - face.v.extend([vertArray[1],vertArray[2],vertArray[3],vertArray[10]]) - face.v.reverse() - if thereAreMats == 1: - if reassignMats == 0 or doodTopMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = doodTopMat-1 - doodadMesh.faces.append(face) - face = Face() - face.v.extend([vertArray[3],vertArray[4],vertArray[9],vertArray[10]]) - face.v.reverse() - if thereAreMats == 1: - if reassignMats == 0 or doodTopMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = doodTopMat-1 - doodadMesh.faces.append(face) - face = Face() - face.v.extend([vertArray[4],vertArray[7],vertArray[8],vertArray[9]]) - face.v.reverse() - if thereAreMats == 1: - if reassignMats == 0 or doodTopMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = doodTopMat-1 - doodadMesh.faces.append(face) - face = Face() - face.v.extend([vertArray[4],vertArray[5],vertArray[6],vertArray[7]]) - face.v.reverse() - if thereAreMats == 1: - if reassignMats == 0 or doodTopMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = doodTopMat-1 - doodadMesh.faces.append(face) - - #fills top with faceness - face = Face() - face.v.extend([topVertArray[0],topVertArray[1],topVertArray[10],topVertArray[11]]) - if tosel == 1: - face.sel = 1 - if thereAreMats == 1: - if reassignMats == 0 or doodTopMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = doodTopMat-1 - doodadMesh.faces.append(face) - face = Face() - face.v.extend([topVertArray[1],topVertArray[2],topVertArray[3],topVertArray[10]]) - if tosel == 1: - face.sel = 1 - if thereAreMats == 1: - if reassignMats == 0 or doodTopMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = doodTopMat-1 - doodadMesh.faces.append(face) - face = Face() - face.v.extend([topVertArray[3],topVertArray[4],topVertArray[9],topVertArray[10]]) - if tosel == 1: - face.sel = 1 - if thereAreMats == 1: - if reassignMats == 0 or doodTopMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = doodTopMat-1 - doodadMesh.faces.append(face) - face = Face() - face.v.extend([topVertArray[4],topVertArray[7],topVertArray[8],topVertArray[9]]) - if tosel == 1: - face.sel = 1 - if thereAreMats == 1: - if reassignMats == 0 or doodTopMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = doodTopMat-1 - doodadMesh.faces.append(face) - face = Face() - face.v.extend([topVertArray[4],topVertArray[5],topVertArray[6],topVertArray[7]]) - if tosel == 1: - face.sel = 1 - if thereAreMats == 1: - if reassignMats == 0 or doodTopMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = doodTopMat-1 - doodadMesh.faces.append(face) - diff --git a/release/scripts/bpymodules/dxfColorMap.py b/release/scripts/bpymodules/dxfColorMap.py deleted file mode 100644 index 66c0bd4e9a2..00000000000 --- a/release/scripts/bpymodules/dxfColorMap.py +++ /dev/null @@ -1,282 +0,0 @@ -# dictionary mapping AutoCAD color indexes with Blender colors - -# -------------------------------------------------------------------------- -# color_map.py Final by Ed Blake (AKA Kitsu) -# -------------------------------------------------------------------------- -# ***** 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 ***** -# -------------------------------------------------------------------------- - -color_map = { - 0:[0.0, 0.0, 0.0], - 1:[0.99609375, 0.0, 0.0], - 2:[0.99609375, 0.99609375, 0.0], - 3:[0.0, 0.99609375, 0.0], - 4:[0.0, 0.99609375, 0.99609375], - 5:[0.0, 0.0, 0.99609375], - 6:[0.99609375, 0.0, 0.99609375], - 7:[0.99609375, 0.99609375, 0.99609375], - 8:[0.25390625, 0.25390625, 0.25390625], - 9:[0.5, 0.5, 0.5], - 10:[0.99609375, 0.0, 0.0], - 11:[0.99609375, 0.6640625, 0.6640625], - 12:[0.73828125, 0.0, 0.0], - 13:[0.73828125, 0.4921875, 0.4921875], - 14:[0.50390625, 0.0, 0.0], - 15:[0.50390625, 0.3359375, 0.3359375], - 16:[0.40625, 0.0, 0.0], - 17:[0.40625, 0.26953125, 0.26953125], - 18:[0.30859375, 0.0, 0.0], - 19:[0.30859375, 0.20703125, 0.20703125], - 20:[0.99609375, 0.24609375, 0.0], - 21:[0.99609375, 0.74609375, 0.6640625], - 22:[0.73828125, 0.1796875, 0.0], - 23:[0.73828125, 0.55078125, 0.4921875], - 24:[0.50390625, 0.12109375, 0.0], - 25:[0.50390625, 0.375, 0.3359375], - 26:[0.40625, 0.09765625, 0.0], - 27:[0.40625, 0.3046875, 0.26953125], - 28:[0.30859375, 0.07421875, 0.0], - 29:[0.30859375, 0.23046875, 0.20703125], - 30:[0.99609375, 0.49609375, 0.0], - 31:[0.99609375, 0.828125, 0.6640625], - 32:[0.73828125, 0.3671875, 0.0], - 33:[0.73828125, 0.61328125, 0.4921875], - 34:[0.50390625, 0.25, 0.0], - 35:[0.50390625, 0.41796875, 0.3359375], - 36:[0.40625, 0.203125, 0.0], - 37:[0.40625, 0.3359375, 0.26953125], - 38:[0.30859375, 0.15234375, 0.0], - 39:[0.30859375, 0.2578125, 0.20703125], - 40:[0.99609375, 0.74609375, 0.0], - 41:[0.99609375, 0.9140625, 0.6640625], - 42:[0.73828125, 0.55078125, 0.0], - 43:[0.73828125, 0.67578125, 0.4921875], - 44:[0.50390625, 0.375, 0.0], - 45:[0.50390625, 0.4609375, 0.3359375], - 46:[0.40625, 0.3046875, 0.0], - 47:[0.40625, 0.37109375, 0.26953125], - 48:[0.30859375, 0.23046875, 0.0], - 49:[0.30859375, 0.28515625, 0.20703125], - 50:[0.99609375, 0.99609375, 0.0], - 51:[0.99609375, 0.99609375, 0.6640625], - 52:[0.73828125, 0.73828125, 0.0], - 53:[0.73828125, 0.73828125, 0.4921875], - 54:[0.50390625, 0.50390625, 0.0], - 55:[0.50390625, 0.50390625, 0.3359375], - 56:[0.40625, 0.40625, 0.0], - 57:[0.40625, 0.40625, 0.26953125], - 58:[0.30859375, 0.30859375, 0.0], - 59:[0.30859375, 0.30859375, 0.20703125], - 60:[0.74609375, 0.99609375, 0.0], - 61:[0.9140625, 0.99609375, 0.6640625], - 62:[0.55078125, 0.73828125, 0.0], - 63:[0.67578125, 0.73828125, 0.4921875], - 64:[0.375, 0.50390625, 0.0], - 65:[0.4609375, 0.50390625, 0.3359375], - 66:[0.3046875, 0.40625, 0.0], - 67:[0.37109375, 0.40625, 0.26953125], - 68:[0.23046875, 0.30859375, 0.0], - 69:[0.28515625, 0.30859375, 0.20703125], - 70:[0.49609375, 0.99609375, 0.0], - 71:[0.828125, 0.99609375, 0.6640625], - 72:[0.3671875, 0.73828125, 0.0], - 73:[0.61328125, 0.73828125, 0.4921875], - 74:[0.25, 0.50390625, 0.0], - 75:[0.41796875, 0.50390625, 0.3359375], - 76:[0.203125, 0.40625, 0.0], - 77:[0.3359375, 0.40625, 0.26953125], - 78:[0.15234375, 0.30859375, 0.0], - 79:[0.2578125, 0.30859375, 0.20703125], - 80:[0.24609375, 0.99609375, 0.0], - 81:[0.74609375, 0.99609375, 0.6640625], - 82:[0.1796875, 0.73828125, 0.0], - 83:[0.55078125, 0.73828125, 0.4921875], - 84:[0.12109375, 0.50390625, 0.0], - 85:[0.375, 0.50390625, 0.3359375], - 86:[0.09765625, 0.40625, 0.0], - 87:[0.3046875, 0.40625, 0.26953125], - 88:[0.07421875, 0.30859375, 0.0], - 89:[0.23046875, 0.30859375, 0.20703125], - 90:[0.0, 0.99609375, 0.0], - 91:[0.6640625, 0.99609375, 0.6640625], - 92:[0.0, 0.73828125, 0.0], - 93:[0.4921875, 0.73828125, 0.4921875], - 94:[0.0, 0.50390625, 0.0], - 95:[0.3359375, 0.50390625, 0.3359375], - 96:[0.0, 0.40625, 0.0], - 97:[0.26953125, 0.40625, 0.26953125], - 98:[0.0, 0.30859375, 0.0], - 99:[0.20703125, 0.30859375, 0.20703125], - 100:[0.0, 0.99609375, 0.24609375], - 101:[0.6640625, 0.99609375, 0.74609375], - 102:[0.0, 0.73828125, 0.1796875], - 103:[0.4921875, 0.73828125, 0.55078125], - 104:[0.0, 0.50390625, 0.12109375], - 105:[0.3359375, 0.50390625, 0.375], - 106:[0.0, 0.40625, 0.09765625], - 107:[0.26953125, 0.40625, 0.3046875], - 108:[0.0, 0.30859375, 0.07421875], - 109:[0.20703125, 0.30859375, 0.23046875], - 110:[0.0, 0.99609375, 0.49609375], - 111:[0.6640625, 0.99609375, 0.828125], - 112:[0.0, 0.73828125, 0.3671875], - 113:[0.4921875, 0.73828125, 0.61328125], - 114:[0.0, 0.50390625, 0.25], - 115:[0.3359375, 0.50390625, 0.41796875], - 116:[0.0, 0.40625, 0.203125], - 117:[0.26953125, 0.40625, 0.3359375], - 118:[0.0, 0.30859375, 0.15234375], - 119:[0.20703125, 0.30859375, 0.2578125], - 120:[0.0, 0.99609375, 0.74609375], - 121:[0.6640625, 0.99609375, 0.9140625], - 122:[0.0, 0.73828125, 0.55078125], - 123:[0.4921875, 0.73828125, 0.67578125], - 124:[0.0, 0.50390625, 0.375], - 125:[0.3359375, 0.50390625, 0.4609375], - 126:[0.0, 0.40625, 0.3046875], - 127:[0.26953125, 0.40625, 0.37109375], - 128:[0.0, 0.30859375, 0.23046875], - 129:[0.20703125, 0.30859375, 0.28515625], - 130:[0.0, 0.99609375, 0.99609375], - 131:[0.6640625, 0.99609375, 0.99609375], - 132:[0.0, 0.73828125, 0.73828125], - 133:[0.4921875, 0.73828125, 0.73828125], - 134:[0.0, 0.50390625, 0.50390625], - 135:[0.3359375, 0.50390625, 0.50390625], - 136:[0.0, 0.40625, 0.40625], - 137:[0.26953125, 0.40625, 0.40625], - 138:[0.0, 0.30859375, 0.30859375], - 139:[0.20703125, 0.30859375, 0.30859375], - 140:[0.0, 0.74609375, 0.99609375], - 141:[0.6640625, 0.9140625, 0.99609375], - 142:[0.0, 0.55078125, 0.73828125], - 143:[0.4921875, 0.67578125, 0.73828125], - 144:[0.0, 0.375, 0.50390625], - 145:[0.3359375, 0.4609375, 0.50390625], - 146:[0.0, 0.3046875, 0.40625], - 147:[0.26953125, 0.37109375, 0.40625], - 148:[0.0, 0.23046875, 0.30859375], - 149:[0.20703125, 0.28515625, 0.30859375], - 150:[0.0, 0.49609375, 0.99609375], - 151:[0.6640625, 0.828125, 0.99609375], - 152:[0.0, 0.3671875, 0.73828125], - 153:[0.4921875, 0.61328125, 0.73828125], - 154:[0.0, 0.25, 0.50390625], - 155:[0.3359375, 0.41796875, 0.50390625], - 156:[0.0, 0.203125, 0.40625], - 157:[0.26953125, 0.3359375, 0.40625], - 158:[0.0, 0.15234375, 0.30859375], - 159:[0.20703125, 0.2578125, 0.30859375], - 160:[0.0, 0.24609375, 0.99609375], - 161:[0.6640625, 0.74609375, 0.99609375], - 162:[0.0, 0.1796875, 0.73828125], - 163:[0.4921875, 0.55078125, 0.73828125], - 164:[0.0, 0.12109375, 0.50390625], - 165:[0.3359375, 0.375, 0.50390625], - 166:[0.0, 0.09765625, 0.40625], - 167:[0.26953125, 0.3046875, 0.40625], - 168:[0.0, 0.07421875, 0.30859375], - 169:[0.20703125, 0.23046875, 0.30859375], - 170:[0.0, 0.0, 0.99609375], - 171:[0.6640625, 0.6640625, 0.99609375], - 172:[0.0, 0.0, 0.73828125], - 173:[0.4921875, 0.4921875, 0.73828125], - 174:[0.0, 0.0, 0.50390625], - 175:[0.3359375, 0.3359375, 0.50390625], - 176:[0.0, 0.0, 0.40625], - 177:[0.26953125, 0.26953125, 0.40625], - 178:[0.0, 0.0, 0.30859375], - 179:[0.20703125, 0.20703125, 0.30859375], - 180:[0.24609375, 0.0, 0.99609375], - 181:[0.74609375, 0.6640625, 0.99609375], - 182:[0.1796875, 0.0, 0.73828125], - 183:[0.55078125, 0.4921875, 0.73828125], - 184:[0.12109375, 0.0, 0.50390625], - 185:[0.375, 0.3359375, 0.50390625], - 186:[0.09765625, 0.0, 0.40625], - 187:[0.3046875, 0.26953125, 0.40625], - 188:[0.07421875, 0.0, 0.30859375], - 189:[0.23046875, 0.20703125, 0.30859375], - 190:[0.49609375, 0.0, 0.99609375], - 191:[0.828125, 0.6640625, 0.99609375], - 192:[0.3671875, 0.0, 0.73828125], - 193:[0.61328125, 0.4921875, 0.73828125], - 194:[0.25, 0.0, 0.50390625], - 195:[0.41796875, 0.3359375, 0.50390625], - 196:[0.203125, 0.0, 0.40625], - 197:[0.3359375, 0.26953125, 0.40625], - 198:[0.15234375, 0.0, 0.30859375], - 199:[0.2578125, 0.20703125, 0.30859375], - 200:[0.74609375, 0.0, 0.99609375], - 201:[0.9140625, 0.6640625, 0.99609375], - 202:[0.55078125, 0.0, 0.73828125], - 203:[0.67578125, 0.4921875, 0.73828125], - 204:[0.375, 0.0, 0.50390625], - 205:[0.4609375, 0.3359375, 0.50390625], - 206:[0.3046875, 0.0, 0.40625], - 207:[0.37109375, 0.26953125, 0.40625], - 208:[0.23046875, 0.0, 0.30859375], - 209:[0.28515625, 0.20703125, 0.30859375], - 210:[0.99609375, 0.0, 0.99609375], - 211:[0.99609375, 0.6640625, 0.99609375], - 212:[0.73828125, 0.0, 0.73828125], - 213:[0.73828125, 0.4921875, 0.73828125], - 214:[0.50390625, 0.0, 0.50390625], - 215:[0.50390625, 0.3359375, 0.50390625], - 216:[0.40625, 0.0, 0.40625], - 217:[0.40625, 0.26953125, 0.40625], - 218:[0.30859375, 0.0, 0.30859375], - 219:[0.30859375, 0.20703125, 0.30859375], - 220:[0.99609375, 0.0, 0.74609375], - 221:[0.99609375, 0.6640625, 0.9140625], - 222:[0.73828125, 0.0, 0.55078125], - 223:[0.73828125, 0.4921875, 0.67578125], - 224:[0.50390625, 0.0, 0.375], - 225:[0.50390625, 0.3359375, 0.4609375], - 226:[0.40625, 0.0, 0.3046875], - 227:[0.40625, 0.26953125, 0.37109375], - 228:[0.30859375, 0.0, 0.23046875], - 229:[0.30859375, 0.20703125, 0.28515625], - 230:[0.99609375, 0.0, 0.49609375], - 231:[0.99609375, 0.6640625, 0.828125], - 232:[0.73828125, 0.0, 0.3671875], - 233:[0.73828125, 0.4921875, 0.61328125], - 234:[0.50390625, 0.0, 0.25], - 235:[0.50390625, 0.3359375, 0.41796875], - 236:[0.40625, 0.0, 0.203125], - 237:[0.40625, 0.26953125, 0.3359375], - 238:[0.30859375, 0.0, 0.15234375], - 239:[0.30859375, 0.20703125, 0.2578125], - 240:[0.99609375, 0.0, 0.24609375], - 241:[0.99609375, 0.6640625, 0.74609375], - 242:[0.73828125, 0.0, 0.1796875], - 243:[0.73828125, 0.4921875, 0.55078125], - 244:[0.50390625, 0.0, 0.12109375], - 245:[0.50390625, 0.3359375, 0.375], - 246:[0.40625, 0.0, 0.09765625], - 247:[0.40625, 0.26953125, 0.3046875], - 248:[0.30859375, 0.0, 0.07421875], - 249:[0.30859375, 0.20703125, 0.23046875], - 250:[0.19921875, 0.19921875, 0.19921875], - 251:[0.3125, 0.3125, 0.3125], - 252:[0.41015625, 0.41015625, 0.41015625], - 253:[0.5078125, 0.5078125, 0.5078125], - 254:[0.7421875, 0.7421875, 0.7421875], - 255:[0.99609375, 0.99609375, 0.99609375], -} diff --git a/release/scripts/bpymodules/dxfLibrary.py b/release/scripts/bpymodules/dxfLibrary.py deleted file mode 100644 index ccd8ef9b625..00000000000 --- a/release/scripts/bpymodules/dxfLibrary.py +++ /dev/null @@ -1,880 +0,0 @@ -#dxfLibrary.py : provides functions for generating DXF files -# -------------------------------------------------------------------------- -__version__ = "v1.33 - 2009.06.16" -__author__ = "Stani Michiels(Stani), Remigiusz Fiedler(migius)" -__license__ = "GPL" -__url__ = "http://wiki.blender.org/index.php/Scripts/Manual/Export/autodesk_dxf" -__bpydoc__ ="""The library to export geometry data to DXF format r12 version. - -Copyright %s -Version %s -License %s -Homepage %s - -See the homepage for documentation. -Dedicated thread on BlenderArtists: http://blenderartists.org/forum/showthread.php?t=136439 - -IDEAs: -- - -TODO: -- add support for DXFr14 (needs extended file header) -- add support for SPLINEs (possible first in DXFr14 version) -- add user preset for floating point precision (3-16?) - -History -v1.33 - 2009.06.16 by migius - - modif _point(): converts all coords to floats - - modif LineType class: implement elements - - added VPORT class, incl. defaults - - fix Insert class -v1.32 - 2009.06.06 by migius - - modif Style class: changed defaults to widthFactor=1.0, obliqueAngle=0.0 - - modif Text class: alignment parameter reactivated -v1.31 - 2009.06.02 by migius - - modif _Entity class: added paperspace,elevation -v1.30 - 2009.05.28 by migius - - bugfix 3dPOLYLINE/POLYFACE: VERTEX needs x,y,z coordinates, index starts with 1 not 0 -v1.29 - 2008.12.28 by Yorik - - modif POLYLINE to support bulge segments -v1.28 - 2008.12.13 by Steeve/BlenderArtists - - bugfix for EXTMIN/EXTMAX to suit Cycas-CAD -v1.27 - 2008.10.07 by migius - - beautifying output code: keys whitespace prefix - - refactoring DXF-strings format: NewLine moved to the end of -v1.26 - 2008.10.05 by migius - - modif POLYLINE to support POLYFACE -v1.25 - 2008.09.28 by migius - - modif FACE class for r12 -v1.24 - 2008.09.27 by migius - - modif POLYLINE class for r12 - - changing output format from r9 to r12(AC1009) -v1.1 (20/6/2005) by www.stani.be/python/sdxf - - Python library to generate dxf drawings -______________________________________________________________ -""" % (__author__,__version__,__license__,__url__) - -# -------------------------------------------------------------------------- -# DXF Library: copyright (C) 2005 by Stani Michiels (AKA Stani) -# 2008/2009 modif by Remigiusz Fiedler (AKA migius) -# -------------------------------------------------------------------------- -# ***** 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 ***** - - -#import Blender -#from Blender import Mathutils, Window, Scene, sys, Draw -#import BPyMessages - -try: - import copy - #from struct import pack -except: - copy = None - -####1) Private (only for developpers) -_HEADER_POINTS=['insbase','extmin','extmax'] - -#---helper functions----------------------------------- -def _point(x,index=0): - """Convert tuple to a dxf point""" - #print 'deb: _point=', x #------------- - return '\n'.join([' %s\n%s'%((i+1)*10+index,float(x[i])) for i in range(len(x))]) - -def _points(plist): - """Convert a list of tuples to dxf points""" - out = '\n'.join([_point(plist[i],i)for i in range(len(plist))]) - return out - -#---base classes---------------------------------------- -class _Call: - """Makes a callable class.""" - def copy(self): - """Returns a copy.""" - return copy.deepcopy(self) - - def __call__(self,**attrs): - """Returns a copy with modified attributes.""" - copied=self.copy() - for attr in attrs:setattr(copied,attr,attrs[attr]) - return copied - -#------------------------------------------------------- -class _Entity(_Call): - """Base class for _common group codes for entities.""" - def __init__(self,paperspace=None,color=None,layer='0', - lineType=None,lineTypeScale=None,lineWeight=None, - extrusion=None,elevation=None,thickness=None, - parent=None): - """None values will be omitted.""" - self.paperspace = paperspace - self.color = color - self.layer = layer - self.lineType = lineType - self.lineTypeScale = lineTypeScale - self.lineWeight = lineWeight - self.extrusion = extrusion - self.elevation = elevation - self.thickness = thickness - #self.visible = visible - self.parent = parent - - def _common(self): - """Return common group codes as a string.""" - if self.parent:parent=self.parent - else:parent=self - result ='' - if parent.paperspace==1: result+=' 67\n1\n' - if parent.layer!=None: result+=' 8\n%s\n'%parent.layer - if parent.color!=None: result+=' 62\n%s\n'%parent.color - if parent.lineType!=None: result+=' 6\n%s\n'%parent.lineType - # TODO: if parent.lineWeight!=None: result+='370\n%s\n'%parent.lineWeight - # TODO: if parent.visible!=None: result+='60\n%s\n'%parent.visible - if parent.lineTypeScale!=None: result+=' 48\n%s\n'%parent.lineTypeScale - if parent.elevation!=None: result+=' 38\n%s\n'%parent.elevation - if parent.thickness!=None: result+=' 39\n%s\n'%parent.thickness - if parent.extrusion!=None: result+='%s\n'%_point(parent.extrusion,200) - return result - -#-------------------------- -class _Entities: - """Base class to deal with composed objects.""" - def __dxf__(self): - return [] - - def __str__(self): - return ''.join([str(x) for x in self.__dxf__()]) - -#-------------------------- -class _Collection(_Call): - """Base class to expose entities methods to main object.""" - def __init__(self,entities=[]): - self.entities=copy.copy(entities) - #link entities methods to drawing - for attr in dir(self.entities): - if attr[0]!='_': - attrObject=getattr(self.entities,attr) - if callable(attrObject): - setattr(self,attr,attrObject) - -####2) Constants -#---color values -BYBLOCK=0 -BYLAYER=256 - -#---block-type flags (bit coded values, may be combined): -ANONYMOUS =1 # This is an anonymous block generated by hatching, associative dimensioning, other internal operations, or an application -NON_CONSTANT_ATTRIBUTES =2 # This block has non-constant attribute definitions (this bit is not set if the block has any attribute definitions that are constant, or has no attribute definitions at all) -XREF =4 # This block is an external reference (xref) -XREF_OVERLAY =8 # This block is an xref overlay -EXTERNAL =16 # This block is externally dependent -RESOLVED =32 # This is a resolved external reference, or dependent of an external reference (ignored on input) -REFERENCED =64 # This definition is a referenced external reference (ignored on input) - -#---mtext flags -#attachment point -TOP_LEFT = 1 -TOP_CENTER = 2 -TOP_RIGHT = 3 -MIDDLE_LEFT = 4 -MIDDLE_CENTER = 5 -MIDDLE_RIGHT = 6 -BOTTOM_LEFT = 7 -BOTTOM_CENTER = 8 -BOTTOM_RIGHT = 9 -#drawing direction -LEFT_RIGHT = 1 -TOP_BOTTOM = 3 -BY_STYLE = 5 #the flow direction is inherited from the associated text style -#line spacing style (optional): -AT_LEAST = 1 #taller characters will override -EXACT = 2 #taller characters will not override - -#---polyline flags -CLOSED =1 # This is a closed polyline (or a polygon mesh closed in the M direction) -CURVE_FIT =2 # Curve-fit vertices have been added -SPLINE_FIT =4 # Spline-fit vertices have been added -POLYLINE_3D =8 # This is a 3D polyline -POLYGON_MESH =16 # This is a 3D polygon mesh -CLOSED_N =32 # The polygon mesh is closed in the N direction -POLYFACE_MESH =64 # The polyline is a polyface mesh -CONTINOUS_LINETYPE_PATTERN =128 # The linetype pattern is generated continuously around the vertices of this polyline - -#---text flags -#horizontal -LEFT = 0 -CENTER = 1 -RIGHT = 2 -ALIGNED = 3 #if vertical alignment = 0 -MIDDLE = 4 #if vertical alignment = 0 -FIT = 5 #if vertical alignment = 0 -#vertical -BASELINE = 0 -BOTTOM = 1 -MIDDLE = 2 -TOP = 3 - -####3) Classes -#---entitities ----------------------------------------------- -#-------------------------- -class Arc(_Entity): - """Arc, angles in degrees.""" - def __init__(self,center=(0,0,0),radius=1, - startAngle=0.0,endAngle=90,**common): - """Angles in degrees.""" - _Entity.__init__(self,**common) - self.center=center - self.radius=radius - self.startAngle=startAngle - self.endAngle=endAngle - def __str__(self): - return ' 0\nARC\n%s%s\n 40\n%s\n 50\n%s\n 51\n%s\n'%\ - (self._common(),_point(self.center), - self.radius,self.startAngle,self.endAngle) - -#----------------------------------------------- -class Circle(_Entity): - """Circle""" - def __init__(self,center=(0,0,0),radius=1,**common): - _Entity.__init__(self,**common) - self.center=center - self.radius=radius - def __str__(self): - return ' 0\nCIRCLE\n%s%s\n 40\n%s\n'%\ - (self._common(),_point(self.center),self.radius) - -#----------------------------------------------- -class Face(_Entity): - """3dface""" - def __init__(self,points,**common): - _Entity.__init__(self,**common) - while len(points)<4: #fix for r12 format - points.append(points[-1]) - self.points=points - - def __str__(self): - out = ' 0\n3DFACE\n%s%s\n' %(self._common(),_points(self.points)) - #print 'deb:out=', out #------------------- - return out - -#----------------------------------------------- -class Insert(_Entity): - """Block instance.""" - def __init__(self,name,point=(0,0,0), - xscale=None,yscale=None,zscale=None, - cols=None,colspacing=None,rows=None,rowspacing=None, - rotation=None, - **common): - _Entity.__init__(self,**common) - self.name=name - self.point=point - self.xscale=xscale - self.yscale=yscale - self.zscale=zscale - self.cols=cols - self.colspacing=colspacing - self.rows=rows - self.rowspacing=rowspacing - self.rotation=rotation - - def __str__(self): - result=' 0\nINSERT\n 2\n%s\n%s%s\n'%\ - (self.name,self._common(),_point(self.point)) - if self.xscale!=None:result+=' 41\n%s\n'%self.xscale - if self.yscale!=None:result+=' 42\n%s\n'%self.yscale - if self.zscale!=None:result+=' 43\n%s\n'%self.zscale - if self.rotation:result+=' 50\n%s\n'%self.rotation - if self.cols!=None:result+=' 70\n%s\n'%self.cols - if self.colspacing!=None:result+=' 44\n%s\n'%self.colspacing - if self.rows!=None:result+=' 71\n%s\n'%self.rows - if self.rowspacing!=None:result+=' 45\n%s\n'%self.rowspacing - return result - -#----------------------------------------------- -class Line(_Entity): - """Line""" - def __init__(self,points,**common): - _Entity.__init__(self,**common) - self.points=points - def __str__(self): - return ' 0\nLINE\n%s%s\n' %( - self._common(), _points(self.points)) - - -#----------------------------------------------- -class PolyLine(_Entity): - def __init__(self,points,org_point=[0,0,0],flag=0,width=None,**common): - #width = number, or width = list [width_start=None, width_end=None] - #for 2d-polyline: points = [ [x, y, z, width_start=None, width_end=None, bulge=0 or None], ...] - #for 3d-polyline: points = [ [x, y, z], ...] - #for polyface: points = [points_list, faces_list] - _Entity.__init__(self,**common) - self.points=points - self.org_point=org_point - self.flag=flag - self.polyface = False - self.polyline2d = False - self.faces = [] # dummy value - self.width= None # dummy value - if self.flag & POLYFACE_MESH: - self.polyface=True - self.points=points[0] - self.faces=points[1] - self.p_count=len(self.points) - self.f_count=len(self.faces) - elif not self.flag & POLYLINE_3D: - self.polyline2d = True - if width: - if type(width)!='list': - width=[width,width] - self.width=width - - def __str__(self): - result= ' 0\nPOLYLINE\n%s 70\n%s\n' %(self._common(),self.flag) - result+=' 66\n1\n' - result+='%s\n' %_point(self.org_point) - if self.polyface: - result+=' 71\n%s\n' %self.p_count - result+=' 72\n%s\n' %self.f_count - elif self.polyline2d: - if self.width!=None: result+=' 40\n%s\n 41\n%s\n' %(self.width[0],self.width[1]) - for point in self.points: - result+=' 0\nVERTEX\n' - result+=' 8\n%s\n' %self.layer - if self.polyface: - result+='%s\n' %_point(point[0:3]) - result+=' 70\n192\n' - elif self.polyline2d: - result+='%s\n' %_point(point[0:2]) - if len(point)>4: - width1, width2 = point[3], point[4] - if width1!=None: result+=' 40\n%s\n' %width1 - if width2!=None: result+=' 41\n%s\n' %width2 - if len(point)==6: - bulge = point[5] - if bulge: result+=' 42\n%s\n' %bulge - else: - result+='%s\n' %_point(point[0:3]) - for face in self.faces: - result+=' 0\nVERTEX\n' - result+=' 8\n%s\n' %self.layer - result+='%s\n' %_point(self.org_point) - result+=' 70\n128\n' - result+=' 71\n%s\n' %face[0] - result+=' 72\n%s\n' %face[1] - result+=' 73\n%s\n' %face[2] - if len(face)==4: result+=' 74\n%s\n' %face[3] - result+=' 0\nSEQEND\n' - result+=' 8\n%s\n' %self.layer - return result - -#----------------------------------------------- -class Point(_Entity): - """Point.""" - def __init__(self,points=None,**common): - _Entity.__init__(self,**common) - self.points=points - def __str__(self): # TODO: - return ' 0\nPOINT\n%s%s\n' %(self._common(), - _points(self.points) - ) - -#----------------------------------------------- -class Solid(_Entity): - """Colored solid fill.""" - def __init__(self,points=None,**common): - _Entity.__init__(self,**common) - self.points=points - def __str__(self): - return ' 0\nSOLID\n%s%s\n' %(self._common(), - _points(self.points[:2]+[self.points[3],self.points[2]]) - ) - - -#----------------------------------------------- -class Text(_Entity): - """Single text line.""" - def __init__(self,text='',point=(0,0,0),alignment=None, - flag=None,height=1,justifyhor=None,justifyver=None, - rotation=None,obliqueAngle=None,style=None,xscale=None,**common): - _Entity.__init__(self,**common) - self.text=text - self.point=point - self.alignment=alignment - self.flag=flag - self.height=height - self.justifyhor=justifyhor - self.justifyver=justifyver - self.rotation=rotation - self.obliqueAngle=obliqueAngle - self.style=style - self.xscale=xscale - def __str__(self): - result= ' 0\nTEXT\n%s%s\n 40\n%s\n 1\n%s\n'%\ - (self._common(),_point(self.point),self.height,self.text) - if self.rotation: result+=' 50\n%s\n'%self.rotation - if self.xscale: result+=' 41\n%s\n'%self.xscale - if self.obliqueAngle: result+=' 51\n%s\n'%self.obliqueAngle - if self.style: result+=' 7\n%s\n'%self.style - if self.flag: result+=' 71\n%s\n'%self.flag - if self.justifyhor: result+=' 72\n%s\n'%self.justifyhor - if self.alignment: result+='%s\n'%_point(self.alignment,1) - if self.justifyver: result+=' 73\n%s\n'%self.justifyver - return result - -#----------------------------------------------- -class Mtext(Text): - """Surrogate for mtext, generates some Text instances.""" - def __init__(self,text='',point=(0,0,0),width=250,spacingFactor=1.5,down=0,spacingWidth=None,**options): - Text.__init__(self,text=text,point=point,**options) - if down:spacingFactor*=-1 - self.spacingFactor=spacingFactor - self.spacingWidth=spacingWidth - self.width=width - self.down=down - def __str__(self): - texts=self.text.replace('\r\n','\n').split('\n') - if not self.down:texts.reverse() - result='' - x=y=0 - if self.spacingWidth:spacingWidth=self.spacingWidth - else:spacingWidth=self.height*self.spacingFactor - for text in texts: - while text: - result+='%s\n'%Text(text[:self.width], - point=(self.point[0]+x*spacingWidth, - self.point[1]+y*spacingWidth, - self.point[2]), - alignment=self.alignment,flag=self.flag,height=self.height, - justifyhor=self.justifyhor,justifyver=self.justifyver, - rotation=self.rotation,obliqueAngle=self.obliqueAngle, - style=self.style,xscale=self.xscale,parent=self - ) - text=text[self.width:] - if self.rotation:x+=1 - else:y+=1 - return result[1:] - -#----------------------------------------------- -##class _Mtext(_Entity): -## """Mtext not functioning for minimal dxf.""" -## def __init__(self,text='',point=(0,0,0),attachment=1, -## charWidth=None,charHeight=1,direction=1,height=100,rotation=0, -## spacingStyle=None,spacingFactor=None,style=None,width=100, -## xdirection=None,**common): -## _Entity.__init__(self,**common) -## self.text=text -## self.point=point -## self.attachment=attachment -## self.charWidth=charWidth -## self.charHeight=charHeight -## self.direction=direction -## self.height=height -## self.rotation=rotation -## self.spacingStyle=spacingStyle -## self.spacingFactor=spacingFactor -## self.style=style -## self.width=width -## self.xdirection=xdirection -## def __str__(self): -## input=self.text -## text='' -## while len(input)>250: -## text+='3\n%s\n'%input[:250] -## input=input[250:] -## text+='1\n%s\n'%input -## result= '0\nMTEXT\n%s\n%s\n40\n%s\n41\n%s\n71\n%s\n72\n%s%s\n43\n%s\n50\n%s\n'%\ -## (self._common(),_point(self.point),self.charHeight,self.width, -## self.attachment,self.direction,text, -## self.height, -## self.rotation) -## if self.style:result+='7\n%s\n'%self.style -## if self.xdirection:result+='%s\n'%_point(self.xdirection,1) -## if self.charWidth:result+='42\n%s\n'%self.charWidth -## if self.spacingStyle:result+='73\n%s\n'%self.spacingStyle -## if self.spacingFactor:result+='44\n%s\n'%self.spacingFactor -## return result - -#---tables --------------------------------------------------- -#----------------------------------------------- -class Block(_Collection): - """Use list methods to add entities, eg append.""" - def __init__(self,name,layer='0',flag=0,base=(0,0,0),entities=[]): - self.entities=copy.copy(entities) - _Collection.__init__(self,entities) - self.layer=layer - self.name=name - self.flag=0 - self.base=base - def __str__(self): # TODO: - e=''.join([str(x)for x in self.entities]) - return ' 0\nBLOCK\n 8\n%s\n 2\n%s\n 70\n%s\n%s\n 3\n%s\n%s 0\nENDBLK\n'%\ - (self.layer,self.name.upper(),self.flag,_point(self.base),self.name.upper(),e) - -#----------------------------------------------- -class Layer(_Call): - """Layer""" - def __init__(self,name='pydxf',color=7,lineType='continuous',flag=64): - self.name=name - self.color=color - self.lineType=lineType - self.flag=flag - def __str__(self): - return ' 0\nLAYER\n 2\n%s\n 70\n%s\n 62\n%s\n 6\n%s\n'%\ - (self.name.upper(),self.flag,self.color,self.lineType) - -#----------------------------------------------- -class LineType(_Call): - """Custom linetype""" - def __init__(self,name='CONTINUOUS',description='Solid line',elements=[0.0],flag=0): - self.name=name - self.description=description - self.elements=copy.copy(elements) - self.flag=flag - def __str__(self): - result = ' 0\nLTYPE\n 2\n%s\n 70\n%s\n 3\n%s\n 72\n65\n'%\ - (self.name.upper(),self.flag,self.description) - if self.elements: - elements = ' 73\n%s\n' %(len(self.elements)-1) - elements += ' 40\n%s\n' %(self.elements[0]) - for e in self.elements[1:]: - elements += ' 49\n%s\n' %e - result += elements - return result - - -#----------------------------------------------- -class Style(_Call): - """Text style""" - def __init__(self,name='standard',flag=0,height=0,widthFactor=1.0,obliqueAngle=0.0, - mirror=0,lastHeight=1,font='arial.ttf',bigFont=''): - self.name=name - self.flag=flag - self.height=height - self.widthFactor=widthFactor - self.obliqueAngle=obliqueAngle - self.mirror=mirror - self.lastHeight=lastHeight - self.font=font - self.bigFont=bigFont - def __str__(self): - return ' 0\nSTYLE\n 2\n%s\n 70\n%s\n 40\n%s\n 41\n%s\n 50\n%s\n 71\n%s\n 42\n%s\n 3\n%s\n 4\n%s\n'%\ - (self.name.upper(),self.flag,self.flag,self.widthFactor, - self.obliqueAngle,self.mirror,self.lastHeight, - self.font.upper(),self.bigFont.upper()) - -#----------------------------------------------- -class VPort(_Call): - def __init__(self,name,flag=0, - leftBottom=(0.0,0.0), - rightTop=(1.0,1.0), - center=(0.5,0.5), - snap_base=(0.0,0.0), - snap_spacing=(0.1,0.1), - grid_spacing=(0.1,0.1), - direction=(0.0,0.0,1.0), - target=(0.0,0.0,0.0), - height=1.0, - ratio=1.0, - lens=50, - frontClipping=0, - backClipping=0, - snap_rotation=0, - twist=0, - mode=0, - circle_zoom=100, - fast_zoom=1, - ucsicon=1, - snap_on=0, - grid_on=0, - snap_style=0, - snap_isopair=0 - ): - self.name=name - self.flag=flag - self.leftBottom=leftBottom - self.rightTop=rightTop - self.center=center - self.snap_base=snap_base - self.snap_spacing=snap_spacing - self.grid_spacing=grid_spacing - self.direction=direction - self.target=target - self.height=float(height) - self.ratio=float(ratio) - self.lens=float(lens) - self.frontClipping=float(frontClipping) - self.backClipping=float(backClipping) - self.snap_rotation=float(snap_rotation) - self.twist=float(twist) - self.mode=mode - self.circle_zoom=circle_zoom - self.fast_zoom=fast_zoom - self.ucsicon=ucsicon - self.snap_on=snap_on - self.grid_on=grid_on - self.snap_style=snap_style - self.snap_isopair=snap_isopair - def __str__(self): - output = [' 0', 'VPORT', - ' 2', self.name, - ' 70', self.flag, - _point(self.leftBottom), - _point(self.rightTop,1), - _point(self.center,2), # View center point (in DCS) - _point(self.snap_base,3), - _point(self.snap_spacing,4), - _point(self.grid_spacing,5), - _point(self.direction,6), #view direction from target (in WCS) - _point(self.target,7), - ' 40', self.height, - ' 41', self.ratio, - ' 42', self.lens, - ' 43', self.frontClipping, - ' 44', self.backClipping, - ' 50', self.snap_rotation, - ' 51', self.twist, - ' 71', self.mode, - ' 72', self.circle_zoom, - ' 73', self.fast_zoom, - ' 74', self.ucsicon, - ' 75', self.snap_on, - ' 76', self.grid_on, - ' 77', self.snap_style, - ' 78', self.snap_isopair - ] - - output_str = '' - for s in output: - output_str += '%s\n' %s - return output_str - - - -#----------------------------------------------- -class View(_Call): - def __init__(self,name,flag=0, - width=1, - height=1, - center=(0.5,0.5), - direction=(0,0,1), - target=(0,0,0), - lens=50, - frontClipping=0, - backClipping=0, - twist=0,mode=0 - ): - self.name=name - self.flag=flag - self.width=float(width) - self.height=float(height) - self.center=center - self.direction=direction - self.target=target - self.lens=float(lens) - self.frontClipping=float(frontClipping) - self.backClipping=float(backClipping) - self.twist=float(twist) - self.mode=mode - def __str__(self): - output = [' 0', 'VIEW', - ' 2', self.name, - ' 70', self.flag, - ' 40', self.height, - _point(self.center), - ' 41', self.width, - _point(self.direction,1), - _point(self.target,2), - ' 42', self.lens, - ' 43', self.frontClipping, - ' 44', self.backClipping, - ' 50', self.twist, - ' 71', self.mode - ] - output_str = '' - for s in output: - output_str += '%s\n' %s - return output_str - -#----------------------------------------------- -def ViewByWindow(name,leftBottom=(0,0),rightTop=(1,1),**options): - width=abs(rightTop[0]-leftBottom[0]) - height=abs(rightTop[1]-leftBottom[1]) - center=((rightTop[0]+leftBottom[0])*0.5,(rightTop[1]+leftBottom[1])*0.5) - return View(name=name,width=width,height=height,center=center,**options) - -#---drawing -#----------------------------------------------- -class Drawing(_Collection): - """Dxf drawing. Use append or any other list methods to add objects.""" - def __init__(self,insbase=(0.0,0.0,0.0),extmin=(0.0,0.0,0.0),extmax=(0.0,0.0,0.0), - layers=[Layer()],linetypes=[LineType()],styles=[Style()],blocks=[], - views=[],vports=[],entities=None,fileName='test.dxf'): - # TODO: replace list with None,arial - if not entities: - entities=[] - _Collection.__init__(self,entities) - self.insbase=insbase - self.extmin=extmin - self.extmax=extmax - self.layers=copy.copy(layers) - self.linetypes=copy.copy(linetypes) - self.styles=copy.copy(styles) - self.views=copy.copy(views) - self.vports=copy.copy(vports) - self.blocks=copy.copy(blocks) - self.fileName=fileName - #private - #self.acadver='9\n$ACADVER\n1\nAC1006\n' - self.acadver=' 9\n$ACADVER\n 1\nAC1009\n' - """DXF AutoCAD-Release format codes - AC1021 2008, 2007 - AC1018 2006, 2005, 2004 - AC1015 2002, 2000i, 2000 - AC1014 R14,14.01 - AC1012 R13 - AC1009 R12,11 - AC1006 R10 - AC1004 R9 - AC1002 R2.6 - AC1.50 R2.05 - """ - - def _name(self,x): - """Helper function for self._point""" - return ' 9\n$%s\n' %x.upper() - - def _point(self,name,x): - """Point setting from drawing like extmin,extmax,...""" - return '%s%s' %(self._name(name),_point(x)) - - def _section(self,name,x): - """Sections like tables,blocks,entities,...""" - if x: xstr=''.join(x) - else: xstr='' - return ' 0\nSECTION\n 2\n%s\n%s 0\nENDSEC\n'%(name.upper(),xstr) - - def _table(self,name,x): - """Tables like ltype,layer,style,...""" - if x: xstr=''.join(x) - else: xstr='' - return ' 0\nTABLE\n 2\n%s\n 70\n%s\n%s 0\nENDTAB\n'%(name.upper(),len(x),xstr) - - def __str__(self): - """Returns drawing as dxf string.""" - header=[self.acadver]+[self._point(attr,getattr(self,attr))+'\n' for attr in _HEADER_POINTS] - header=self._section('header',header) - - tables=[self._table('vport',[str(x) for x in self.vports]), - self._table('ltype',[str(x) for x in self.linetypes]), - self._table('layer',[str(x) for x in self.layers]), - self._table('style',[str(x) for x in self.styles]), - self._table('view',[str(x) for x in self.views]), - ] - tables=self._section('tables',tables) - - blocks=self._section('blocks',[str(x) for x in self.blocks]) - - entities=self._section('entities',[str(x) for x in self.entities]) - - all=''.join([header,tables,blocks,entities,' 0\nEOF\n']) - return all - - def saveas(self,fileName): - self.fileName=fileName - self.save() - - def save(self): - test=open(self.fileName,'w') - test.write(str(self)) - test.close() - - -#---extras -#----------------------------------------------- -class Rectangle(_Entity): - """Rectangle, creates lines.""" - def __init__(self,point=(0,0,0),width=1,height=1,solid=None,line=1,**common): - _Entity.__init__(self,**common) - self.point=point - self.width=width - self.height=height - self.solid=solid - self.line=line - def __str__(self): - result='' - points=[self.point,(self.point[0]+self.width,self.point[1],self.point[2]), - (self.point[0]+self.width,self.point[1]+self.height,self.point[2]), - (self.point[0],self.point[1]+self.height,self.point[2]),self.point] - if self.solid: - result+= Solid(points=points[:-1],parent=self.solid) - if self.line: - for i in range(4): - result+= Line(points=[points[i],points[i+1]],parent=self) - return result[1:] - -#----------------------------------------------- -class LineList(_Entity): - """Like polyline, but built of individual lines.""" - def __init__(self,points=[],org_point=[0,0,0],closed=0,**common): - _Entity.__init__(self,**common) - self.closed=closed - self.points=copy.copy(points) - def __str__(self): - if self.closed:points=self.points+[self.points[0]] - else: points=self.points - result='' - for i in range(len(points)-1): - result+= Line(points=[points[i],points[i+1]],parent=self) - return result[1:] - -#----------------------------------------------------- -def test(): - #Blocks - b=Block('test') - b.append(Solid(points=[(0,0,0),(1,0,0),(1,1,0),(0,1,0)],color=1)) - b.append(Arc(center=(1,0,0),color=2)) - - #Drawing - d=Drawing() - #tables - d.blocks.append(b) #table blocks - d.styles.append(Style()) #table styles - d.views.append(View('Normal')) #table view - d.views.append(ViewByWindow('Window',leftBottom=(1,0),rightTop=(2,1))) #idem - - #entities - d.append(Circle(center=(1,1,0),color=3)) - d.append(Face(points=[(0,0,0),(1,0,0),(1,1,0),(0,1,0)],color=4)) - d.append(Insert('test',point=(3,3,3),cols=5,colspacing=2)) - d.append(Line(points=[(0,0,0),(1,1,1)])) - d.append(Mtext('Click on Ads\nmultiple lines with mtext',point=(1,1,1),color=5,rotation=90)) - d.append(Text('Please donate!',point=(3,0,1))) - #d.append(Rectangle(point=(2,2,2),width=4,height=3,color=6,solid=Solid(color=2))) - d.append(Solid(points=[(4,4,0),(5,4,0),(7,8,0),(9,9,0)],color=3)) - #d.append(PolyLine(points=[(1,1,1),(2,1,1),(2,2,1),(1,2,1)],flag=1,color=1)) - - #d.saveas('c:\\test.dxf') - d.saveas('test.dxf') - -#----------------------------------------------------- -if __name__=='__main__': - if not copy: - Draw.PupMenu('Error%t|This script requires a full python install') - else: test() -
\ No newline at end of file diff --git a/release/scripts/bpymodules/dxfReader.py b/release/scripts/bpymodules/dxfReader.py deleted file mode 100644 index df4ebc309e4..00000000000 --- a/release/scripts/bpymodules/dxfReader.py +++ /dev/null @@ -1,381 +0,0 @@ -"""This module provides a function for reading dxf files and parsing them into a useful tree of objects and data. - - The convert function is called by the readDXF fuction to convert dxf strings into the correct data based - on their type code. readDXF expects a (full path) file name as input. -""" - -# -------------------------------------------------------------------------- -# DXF Reader v0.9 by Ed Blake (AKA Kitsu) -# 2008.05.08 modif.def convert() by Remigiusz Fiedler (AKA migius) -# -------------------------------------------------------------------------- -# ***** 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 ***** -# -------------------------------------------------------------------------- - - -#from dxfImportObjects import * - -class Object: - """Empty container class for dxf objects""" - - def __init__(self, _type='', block=False): - """_type expects a string value.""" - self.type = _type - self.name = '' - self.data = [] - - def __str__(self): - if self.name: - return self.name - else: - return self.type - - def __repr__(self): - return str(self.data) - - def get_type(self, kind=''): - """Despite the name, this method actually returns all objects of type 'kind' from self.data.""" - if type: - objects = [] - for item in self.data: - if type(item) != list and item.type == kind: - # we want this type of object - objects.append(item) - elif type(item) == list and item[0] == kind: - # we want this type of data - objects.append(item[1]) - return objects - - -class InitializationError(Exception): pass - -class StateMachine: - """(finite) State Machine from the great David Mertz's great Charming Python article.""" - - def __init__(self): - self.handlers = [] - self.startState = None - self.endStates = [] - - def add_state(self, handler, end_state=0): - """All states and handlers are functions which return - a state and a cargo.""" - self.handlers.append(handler) - if end_state: - self.endStates.append(handler) - def set_start(self, handler): - """Sets the starting handler function.""" - self.startState = handler - - - def run(self, cargo=None): - if not self.startState: - raise InitializationError,\ - "must call .set_start() before .run()" - if not self.endStates: - raise InitializationError, \ - "at least one state must be an end_state" - handler = self.startState - while 1: - (newState, cargo) = handler(cargo) - #print cargo - if newState in self.endStates: - return newState(cargo) - #break - elif newState not in self.handlers: - raise RuntimeError, "Invalid target %s" % newState - else: - handler = newState - -def get_name(data): - """Get the name of an object from its object data. - - Returns a pair of (data_item, name) where data_item is the list entry where the name was found - (the data_item can be used to remove the entry from the object data). Be sure to check - name not None before using the returned values! - """ - value = None - for item in data: - if item[0] == 2: - value = item[1] - break - return item, value - -def get_layer(data): - """Expects object data as input. - - Returns (entry, layer_name) where entry is the data item that provided the layer name. - """ - value = None - for item in data: - if item[0] == 8: - value = item[1] - break - return item, value - - -def convert(code, value): - """Convert a string to the correct Python type based on its dxf code. - code types: - ints = 60-79, 170-179, 270-289, 370-389, 400-409, 1060-1070 - longs = 90-99, 420-429, 440-459, 1071 - floats = 10-39, 40-59, 110-139, 140-149, 210-239, 460-469, 1010-1059 - hex = 105, 310-379, 390-399 - strings = 0-9, 100, 102, 300-309, 410-419, 430-439, 470-479, 999, 1000-1009 - """ - if 59 < code < 80 or 169 < code < 180 or 269 < code < 290 or 369 < code < 390 or 399 < code < 410 or 1059 < code < 1071: - value = int(float(value)) - elif 89 < code < 100 or 419 < code < 430 or 439 < code < 460 or code == 1071: - value = long(float(value)) - elif 9 < code < 60 or 109 < code < 150 or 209 < code < 240 or 459 < code < 470 or 1009 < code < 1060: - value = float(value) - elif code == 105 or 309 < code < 380 or 389 < code < 400: - value = int(value, 16) # should be left as string? - else: # it's already a string so do nothing - pass - return value - - -def findObject(infile, kind=''): - """Finds the next occurance of an object.""" - obj = False - while 1: - line = infile.readline() - if not line: # readline returns '' at eof - return False - if not obj: # We're still looking for our object code - if line.lower().strip() == '0': - obj = True # found it - else: # we are in an object definition - if kind: # if we're looking for a particular kind - if line.lower().strip() == kind: - obj = Object(line.lower().strip()) - break - else: # otherwise take anything non-numeric - if line.lower().strip() not in string.digits: - obj = Object(line.lower().strip()) - break - obj = False # whether we found one or not it's time to start over - return obj - -def handleObject(infile): - """Add data to an object until end of object is found.""" - line = infile.readline() - if line.lower().strip() == 'section': - return 'section' # this would be a problem - elif line.lower().strip() == 'endsec': - return 'endsec' # this means we are done with a section - else: # add data to the object until we find a new object - obj = Object(line.lower().strip()) - obj.name = obj.type - done = False - data = [] - while not done: - line = infile.readline() - if not data: - if line.lower().strip() == '0': - #we've found an object, time to return - return obj - else: - # first part is always an int - data.append(int(line.lower().strip())) - else: - data.append(convert(data[0], line.strip())) - obj.data.append(data) - data = [] - -def handleTable(table, infile): - """Special handler for dealing with nested table objects.""" - item, name = get_name(table.data) - if name: # We should always find a name - table.data.remove(item) - table.name = name.lower() - # This next bit is from handleObject - # handleObject should be generalized to work with any section like object - while 1: - obj = handleObject(infile) - if obj.type == 'table': - print "Warning: previous table not closed!" - return table - elif obj.type == 'endtab': - return table # this means we are done with the table - else: # add objects to the table until one of the above is found - table.data.append(obj) - - - - -def handleBlock(block, infile): - """Special handler for dealing with nested table objects.""" - item, name = get_name(block.data) - if name: # We should always find a name - block.data.remove(item) - block.name = name - # This next bit is from handleObject - # handleObject should be generalized to work with any section like object - while 1: - obj = handleObject(infile) - if obj.type == 'block': - print "Warning: previous block not closed!" - return block - elif obj.type == 'endblk': - return block # this means we are done with the table - else: # add objects to the table until one of the above is found - block.data.append(obj) - - - - -"""These are the states/functions used in the State Machine. -states: - start - find first section - start_section - add data, find first object - object - add obj-data, watch for next obj (called directly by start_section) - end_section - look for next section or eof - end - return results -""" - -def start(cargo): - """Expects the infile as cargo, initializes the cargo.""" - #print "Entering start state!" - infile = cargo - drawing = Object('drawing') - section = findObject(infile, 'section') - if section: - return start_section, (infile, drawing, section) - else: - return error, (infile, "Failed to find any sections!") - -def start_section(cargo): - """Expects [infile, drawing, section] as cargo, builds a nested section object.""" - #print "Entering start_section state!" - infile = cargo[0] - drawing = cargo[1] - section = cargo[2] - # read each line, if it is an object declaration go to object mode - # otherwise create a [index, data] pair and add it to the sections data. - done = False - data = [] - while not done: - line = infile.readline() - - if not data: # if we haven't found a dxf code yet - if line.lower().strip() == '0': - # we've found an object - while 1: # no way out unless we find an end section or a new section - obj = handleObject(infile) - if obj == 'section': # shouldn't happen - print "Warning: failed to close previous section!" - return end_section, (infile, drawing) - elif obj == 'endsec': # This section is over, look for the next - drawing.data.append(section) - return end_section, (infile, drawing) - elif obj.type == 'table': # tables are collections of data - obj = handleTable(obj, infile) # we need to find all there contents - section.data.append(obj) # before moving on - elif obj.type == 'block': # the same is true of blocks - obj = handleBlock(obj, infile) # we need to find all there contents - section.data.append(obj) # before moving on - else: # found another sub-object - section.data.append(obj) - else: - data.append(int(line.lower().strip())) - else: # we have our code, now we just need to convert the data and add it to our list. - data.append(convert(data[0], line.strip())) - section.data.append(data) - data = [] -def end_section(cargo): - """Expects (infile, drawing) as cargo, searches for next section.""" - #print "Entering end_section state!" - infile = cargo[0] - drawing = cargo[1] - section = findObject(infile, 'section') - if section: - return start_section, (infile, drawing, section) - else: - return end, (infile, drawing) - -def end(cargo): - """Expects (infile, drawing) as cargo, called when eof has been reached.""" - #print "Entering end state!" - infile = cargo[0] - drawing = cargo[1] - #infile.close() - return drawing - -def error(cargo): - """Expects a (infile, string) as cargo, called when there is an error during processing.""" - #print "Entering error state!" - infile = cargo[0] - err = cargo[1] - infile.close() - print "There has been an error:" - print err - return False - -def readDXF(filename, objectify): - """Given a file name try to read it as a dxf file. - - Output is an object with the following structure - drawing - header - header data - classes - class data - tables - table data - blocks - block data - entities - entity data - objects - object data - where foo data is a list of sub-objects. True object data - is of the form [code, data]. -""" - infile = open(filename) - - sm = StateMachine() - sm.add_state(error, True) - sm.add_state(end, True) - sm.add_state(start_section) - sm.add_state(end_section) - sm.add_state(start) - sm.set_start(start) - try: - drawing = sm.run(infile) - if drawing: - drawing.name = filename - for obj in drawing.data: - item, name = get_name(obj.data) - if name: - obj.data.remove(item) - obj.name = name.lower() - setattr(drawing, name.lower(), obj) - # Call the objectify function to cast - # raw objects into the right types of object - obj.data = objectify(obj.data) - #print obj.name - finally: - infile.close() - return drawing -if __name__ == "__main__": - filename = r".\examples\block-test.dxf" - drawing = readDXF(filename) - for item in drawing.entities.data: - print item diff --git a/release/scripts/bpymodules/mesh_gradient.py b/release/scripts/bpymodules/mesh_gradient.py deleted file mode 100644 index e582a30152b..00000000000 --- a/release/scripts/bpymodules/mesh_gradient.py +++ /dev/null @@ -1,229 +0,0 @@ -# This is not to be used directly, vertexGradientPick can be used externaly - -import Blender -import BPyMesh -import BPyWindow - -mouseViewRay= BPyWindow.mouseViewRay -from Blender import Mathutils, Window, Scene, Draw, sys -from Blender.Mathutils import Vector, Intersect, LineIntersect, AngleBetweenVecs -LMB= Window.MButs['L'] - -def mouseup(): - # Loop until click - mouse_buttons = Window.GetMouseButtons() - while not mouse_buttons & LMB: - sys.sleep(10) - mouse_buttons = Window.GetMouseButtons() - while mouse_buttons & LMB: - sys.sleep(10) - mouse_buttons = Window.GetMouseButtons() - -def mousedown_wait(): - # If the menu has just been pressed dont use its mousedown, - mouse_buttons = Window.GetMouseButtons() - while mouse_buttons & LMB: - mouse_buttons = Window.GetMouseButtons() - -eps= 0.0001 -def vertexGradientPick(ob, MODE): - #MODE 0 == VWEIGHT, 1 == VCOL - - me= ob.getData(mesh=1) - if not me.faceUV: me.faceUV= True - - Window.DrawProgressBar (0.0, '') - - mousedown_wait() - - if MODE==0: - act_group= me.activeGroup - if act_group == None: - mousedown_wait() - Draw.PupMenu('Error, mesh has no active group.') - return - - # Loop until click - Window.DrawProgressBar (0.25, 'Click to set gradient start') - mouseup() - - obmat= ob.matrixWorld - screen_x, screen_y = Window.GetMouseCoords() - mouseInView, OriginA, DirectionA = mouseViewRay(screen_x, screen_y, obmat) - if not mouseInView or not OriginA: - return - - # get the mouse weight - - if MODE==0: - pickValA= BPyMesh.pickMeshGroupWeight(me, act_group, OriginA, DirectionA) - if MODE==1: - pickValA= BPyMesh.pickMeshGroupVCol(me, OriginA, DirectionA) - - Window.DrawProgressBar (0.75, 'Click to set gradient end') - mouseup() - - TOALPHA= Window.GetKeyQualifiers() & Window.Qual.SHIFT - - screen_x, screen_y = Window.GetMouseCoords() - mouseInView, OriginB, DirectionB = mouseViewRay(screen_x, screen_y, obmat) - if not mouseInView or not OriginB: - return - - if not TOALPHA: # Only get a second opaque value if we are not blending to alpha - if MODE==0: pickValB= BPyMesh.pickMeshGroupWeight(me, act_group, OriginB, DirectionB) - else: - pickValB= BPyMesh.pickMeshGroupVCol(me, OriginB, DirectionB) - else: - if MODE==0: pickValB= 0.0 - else: pickValB= [0.0, 0.0, 0.0] # Dummy value - - # Neither points touched a face - if pickValA == pickValB == None: - return - - # clicking on 1 non face is fine. just set the weight to 0.0 - if pickValA==None: - pickValA= 0.0 - - # swap A/B - OriginA, OriginB= OriginB, OriginA - DirectionA, DirectionB= DirectionB, DirectionA - pickValA, pickValB= pickValA, pickValB - - TOALPHA= True - - if pickValB==None: - pickValB= 0.0 - TOALPHA= True - - # set up 2 lines so we can measure their distances and calc the gradient - - # make a line 90d to the grad in screenspace. - if (OriginA-OriginB).length <= eps: # Persp view. same origin different direction - cross_grad= DirectionA.cross(DirectionB) - ORTHO= False - - else: # Ortho - Same direction, different origin - cross_grad= DirectionA.cross(OriginA-OriginB) - ORTHO= True - - cross_grad.normalize() - cross_grad= cross_grad * 100 - - lineA= (OriginA, OriginA+(DirectionA*100)) - lineB= (OriginB, OriginB+(DirectionB*100)) - - if not ORTHO: - line_angle= AngleBetweenVecs(lineA[1], lineB[1])/2 - line_mid= (lineA[1]+lineB[1])*0.5 - - VSEL= [False] * (len(me.verts)) - - # Get the selected faces and apply the selection to the verts. - for f in me.faces: - if f.sel: - for v in f.v: - VSEL[v.index]= True - groupNames, vWeightDict= BPyMesh.meshWeight2Dict(me) - - - - def grad_weight_from_co(v): - ''' - Takes a vert and retuens its gradient radio between A and B - ''' - - if not VSEL[v.index]: # Not bart of a selected face? - return None, None - - v_co= v.co - # make a line 90d to the 2 lines the user clicked. - vert_line= (v_co - cross_grad, v_co + cross_grad) - - xA= LineIntersect(vert_line[0], vert_line[1], lineA[0], lineA[1]) - xB= LineIntersect(vert_line[0], vert_line[1], lineB[0], lineB[1]) - - if not xA or not xB: # Should never happen but support it anyhow - return None, None - - wA= (xA[0]-xA[1]).length - wB= (xB[0]-xB[1]).length - - wTot= wA+wB - if not wTot: # lines are on the same point. - return None, None - - ''' - Get the length of the line between both intersections on the - 2x view lines. - if the dist between lineA+VertLine and lineB+VertLine is - greater then the lenth between lineA and lineB intersection points, it means - that the verts are not inbetween the 2 lines. - ''' - lineAB_length= (xA[1]-xB[1]).length - - # normalzie - wA= wA/wTot - wB= wB/wTot - - if ORTHO: # Con only use line length method with parelelle lines - if wTot > lineAB_length+eps: - # vert is outside the range on 1 side. see what side of the grad - if wA>wB: wA, wB= 1.0, 0.0 - else: wA, wB= 0.0, 1.0 - else: - # PERSP, lineA[0] is the same origin as lineB[0] - - # Either xA[0] or xB[0] can be used instead of a possible x_mid between the 2 - # as long as the point is inbetween lineA and lineB it dosent matter. - a= AngleBetweenVecs(lineA[0]-xA[0], line_mid) - if a>line_angle: - # vert is outside the range on 1 side. see what side of the grad - if wA>wB: wA, wB= 1.0, 0.0 - else: wA, wB= 0.0, 1.0 - - return wA, wB - - - grad_weights= [grad_weight_from_co(v) for v in me.verts] - - - if MODE==0: - for v in me.verts: - i= v.index - if VSEL[i]: - wA, wB = grad_weights[i] - if wA != None: # and wB - if TOALPHA: - # Do alpha by using the exiting weight for - try: pickValB= vWeightDict[i][act_group] - except: pickValB= 0.0 # The weights not there? assume zero - # Mix2 2 opaque weights - vWeightDict[i][act_group]= pickValB*wA + pickValA*wB - - else: # MODE==1 VCol - for f in me.faces: - if f.sel: - f_v= f.v - for i in xrange(len(f_v)): - v= f_v[i] - wA, wB = grad_weights[v.index] - - c= f.col[i] - - if TOALPHA: - pickValB= c.r, c.g, c.b - - c.r = int(pickValB[0]*wA + pickValA[0]*wB) - c.g = int(pickValB[1]*wA + pickValA[1]*wB) - c.b = int(pickValB[2]*wA + pickValA[2]*wB) - - - - - # Copy weights back to the mesh. - BPyMesh.dict2MeshWeight(me, groupNames, vWeightDict) - Window.DrawProgressBar (1.0, '') - - diff --git a/release/scripts/bpymodules/meshtools.py b/release/scripts/bpymodules/meshtools.py deleted file mode 100644 index 274a12ea6da..00000000000 --- a/release/scripts/bpymodules/meshtools.py +++ /dev/null @@ -1,355 +0,0 @@ -# $Id$ -# -# +---------------------------------------------------------+ -# | Copyright (c) 2001 Anthony D'Agostino | -# | http://www.redrival.com/scorpius | -# | scorpius@netzero.com | -# | September 28, 2002 | -# +---------------------------------------------------------+ -# | Common Functions & Global Variables For All IO Modules | -# +---------------------------------------------------------+ - -# ***** 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 ***** - -import Blender -import sys - -show_progress = 1 # Set to 0 for faster performance -average_vcols = 1 # Off for per-face, On for per-vertex -overwrite_mesh_name = 0 # Set to 0 to increment object-name version - -blender_version = Blender.Get('version') -blender_version_str = `blender_version`[0] + '.' + `blender_version`[1:] - -try: - import operator -except: - msg = "Error: you need a full Python install to run this script." - meshtools.print_boxed(msg) - Blender.Draw.PupMenu("ERROR%t|"+msg) - -# ================================= -# === Append Faces To Face List === -# ================================= -def append_faces(mesh, faces, facesuv, uvcoords): - for i in xrange(len(faces)): - if not i%100 and show_progress: Blender.Window.DrawProgressBar(float(i)/len(faces), "Generating Faces") - numfaceverts=len(faces[i]) - if numfaceverts == 2: #This is not a face is an edge - if mesh.edges == None: #first run - mesh.addEdgeData() - #rev_face = revert(cur_face) - i1 = faces[i][0] - i2 = faces[i][1] - ee = mesh.addEdge(mesh.verts[i1],mesh.verts[i2]) - ee.flag |= Blender.NMesh.EdgeFlags.EDGEDRAW - ee.flag |= Blender.NMesh.EdgeFlags.EDGERENDER - elif numfaceverts in [3,4]: # This face is a triangle or quad - face = Blender.NMesh.Face() - for j in xrange(numfaceverts): - index = faces[i][j] - face.v.append(mesh.verts[index]) - if len(uvcoords) > 1: - uvidx = facesuv[i][j] - face.uv.append(uvcoords[uvidx]) - face.mode = 0 - face.col = [Blender.NMesh.Col()]*4 - mesh.faces.append(face) - else: # Triangulate n-sided convex polygon. - a, b, c = 0, 1, 2 # Indices of first triangle. - for j in xrange(numfaceverts-2): # Number of triangles in polygon. - face = Blender.NMesh.Face() - face.v.append(mesh.verts[faces[i][a]]) - face.v.append(mesh.verts[faces[i][b]]) - face.v.append(mesh.verts[faces[i][c]]) - b = c; c += 1 - mesh.faces.append(face) - #face.smooth = 1 - -# =================================== -# === Append Verts to Vertex List === -# =================================== -def append_verts(mesh, verts, normals): - #print "Number of normals:", len(normals) - #print "Number of verts :", len(verts) - for i in xrange(len(verts)): - if not i%100 and show_progress: Blender.Window.DrawProgressBar(float(i)/len(verts), "Generating Verts") - x, y, z = verts[i] - mesh.verts.append(Blender.NMesh.Vert(x, y, z)) - if normals: - mesh.verts[i].no[0] = normals[i][0] - mesh.verts[i].no[1] = normals[i][1] - mesh.verts[i].no[2] = normals[i][2] - -# =========================== -# === Create Blender Mesh === -# =========================== -def create_mesh(verts, faces, objname, facesuv=[], uvcoords=[], normals=[]): - if normals: normal_flag = 0 - else: normal_flag = 1 - mesh = Blender.NMesh.GetRaw() - append_verts(mesh, verts, normals) - append_faces(mesh, faces, facesuv, uvcoords) - if not overwrite_mesh_name: - objname = versioned_name(objname) - ob= Blender.NMesh.PutRaw(mesh, objname, normal_flag) # Name the Mesh - ob.name= objname # Name the Object - Blender.Redraw() - -# ============================== -# === Increment Name Version === -# ============================== -def versioned_name(objname): - existing_names = [] - for object in Blender.Object.Get(): - existing_names.append(object.name) - existing_names.append(object.getData(name_only=1)) - if objname in existing_names: # don't over-write other names - try: - name, ext = objname.split('.') - except ValueError: - name, ext = objname, '' - try: - num = int(ext) - root = name - except ValueError: - root = objname - for i in xrange(1, 1000): - objname = "%s.%03d" % (root, i) - if objname not in existing_names: - break - return objname - -# =========================== -# === Print Text In A Box === -# =========================== -def print_boxed(text): - lines = text.splitlines() - maxlinelen = max(map(len, lines)) - if sys.platform[:3] == "win": - print chr(218)+chr(196) + chr(196)*maxlinelen + chr(196)+chr(191) - for line in lines: - print chr(179) + ' ' + line.ljust(maxlinelen) + ' ' + chr(179) - print chr(192)+chr(196) + chr(196)*maxlinelen + chr(196)+chr(217) - else: - print '+-' + '-'*maxlinelen + '-+' - for line in lines: print '| ' + line.ljust(maxlinelen) + ' |' - print '+-' + '-'*maxlinelen + '-+' - print '\a\r', # beep when done - -# =============================================== -# === Get euler angles from a rotation matrix === -# =============================================== -def mat2euler(mat): - angle_y = -math.asin(mat[0][2]) - c = math.cos(angle_y) - if math.fabs(c) > 0.005: - angle_x = math.atan2(mat[1][2]/c, mat[2][2]/c) - angle_z = math.atan2(mat[0][1]/c, mat[0][0]/c) - else: - angle_x = 0.0 - angle_z = -math.atan2(mat[1][0], mat[1][1]) - return (angle_x, angle_y, angle_z) - -# ========================== -# === Transpose A Matrix === -# ========================== -def transpose(A): - S = len(A) - T = len(A[0]) - B = [[None]*S for i in xrange(T)] - for i in xrange(T): - for j in xrange(S): - B[i][j] = A[j][i] - return B - -# ======================= -# === Apply Transform === -# ======================= -def apply_transform(vertex, matrix): - x, y, z = vertex - xloc, yloc, zloc = matrix[3][0], matrix[3][1], matrix[3][2] - xcomponent = x*matrix[0][0] + y*matrix[1][0] + z*matrix[2][0] + xloc - ycomponent = x*matrix[0][1] + y*matrix[1][1] + z*matrix[2][1] + yloc - zcomponent = x*matrix[0][2] + y*matrix[1][2] + z*matrix[2][2] + zloc - vertex = [xcomponent, ycomponent, zcomponent] - return vertex - -# ========================= -# === Has Vertex Colors === -# ========================= -def has_vertex_colors(mesh): - # My replacement/workaround for hasVertexColours() - # The docs say: - # "Warning: If a mesh has both vertex colours and textured faces, - # this function will return False. This is due to the way Blender - # deals internally with the vertex colours array (if there are - # textured faces, it is copied to the textured face structure and - # the original array is freed/deleted)." - try: - return mesh.faces[0].col[0] - except: - return 0 - -# =========================== -# === Generate Edge Table === -# =========================== -def generate_edgetable(mesh): - edge_table = {} - numfaces = len(mesh.faces) - - for i in xrange(numfaces): - if not i%100 and show_progress: - Blender.Window.DrawProgressBar(float(i)/numfaces, "Generating Edge Table") - if len(mesh.faces[i].v) == 4: # Process Quadrilaterals - generate_entry_from_quad(mesh, i, edge_table) - elif len(mesh.faces[i].v) == 3: # Process Triangles - generate_entry_from_tri(mesh, i, edge_table) - else: # Skip This Face - print "Face #", i, "was skipped." - - # === Sort Edge_Table Keys & Add Edge Indices === - i = 0 - keys = edge_table.keys() - keys.sort() - for key in keys: - edge_table[key][6] = i - i += 1 - - # === Replace Tuples With Indices === - for key in keys: - for i in [2,3,4,5]: - if edge_table.has_key(edge_table[key][i]): - edge_table[key][i] = edge_table[edge_table[key][i]][6] - else: - keyrev = (edge_table[key][i][1], edge_table[key][i][0]) - edge_table[key][i] = edge_table[keyrev][6] - - return edge_table - -# ================================ -# === Generate Entry From Quad === -# ================================ -def generate_entry_from_quad(mesh, i, edge_table): - vertex4, vertex3, vertex2, vertex1 = mesh.faces[i].v - - if has_vertex_colors(mesh): - vcolor4, vcolor3, vcolor2, vcolor1 = mesh.faces[i].col - Acol = (vcolor1.r/255.0, vcolor1.g/255.0, vcolor1.b/255.0) - Bcol = (vcolor2.r/255.0, vcolor2.g/255.0, vcolor2.b/255.0) - Ccol = (vcolor3.r/255.0, vcolor3.g/255.0, vcolor3.b/255.0) - Dcol = (vcolor4.r/255.0, vcolor4.g/255.0, vcolor4.b/255.0) - - # === verts are upper case, edges are lower case === - A, B, C, D = vertex1.index, vertex2.index, vertex3.index, vertex4.index - a, b, c, d = (A, B), (B, C), (C, D), (D, A) - - if edge_table.has_key((B, A)): - edge_table[(B, A)][1] = i - edge_table[(B, A)][4] = d - edge_table[(B, A)][5] = b - if has_vertex_colors(mesh): edge_table[(B, A)][8] = Bcol - else: - if has_vertex_colors(mesh): - edge_table[(A, B)] = [i, None, d, b, None, None, None, Bcol, None] - else: - edge_table[(A, B)] = [i, None, d, b, None, None, None] - - if edge_table.has_key((C, B)): - edge_table[(C, B)][1] = i - edge_table[(C, B)][4] = a - edge_table[(C, B)][5] = c - if has_vertex_colors(mesh): edge_table[(C, B)][8] = Ccol - else: - if has_vertex_colors(mesh): - edge_table[(B, C)] = [i, None, a, c, None, None, None, Ccol, None] - else: - edge_table[(B, C)] = [i, None, a, c, None, None, None] - - if edge_table.has_key((D, C)): - edge_table[(D, C)][1] = i - edge_table[(D, C)][4] = b - edge_table[(D, C)][5] = d - if has_vertex_colors(mesh): edge_table[(D, C)][8] = Dcol - else: - if has_vertex_colors(mesh): - edge_table[(C, D)] = [i, None, b, d, None, None, None, Dcol, None] - else: - edge_table[(C, D)] = [i, None, b, d, None, None, None] - - if edge_table.has_key((A, D)): - edge_table[(A, D)][1] = i - edge_table[(A, D)][4] = c - edge_table[(A, D)][5] = a - if has_vertex_colors(mesh): edge_table[(A, D)][8] = Acol - else: - if has_vertex_colors(mesh): - edge_table[(D, A)] = [i, None, c, a, None, None, None, Acol, None] - else: - edge_table[(D, A)] = [i, None, c, a, None, None, None] - -# ==================================== -# === Generate Entry From Triangle === -# ==================================== -def generate_entry_from_tri(mesh, i, edge_table): - vertex3, vertex2, vertex1 = mesh.faces[i].v - - if has_vertex_colors(mesh): - vcolor3, vcolor2, vcolor1, _vcolor4_ = mesh.faces[i].col - Acol = (vcolor1.r/255.0, vcolor1.g/255.0, vcolor1.b/255.0) - Bcol = (vcolor2.r/255.0, vcolor2.g/255.0, vcolor2.b/255.0) - Ccol = (vcolor3.r/255.0, vcolor3.g/255.0, vcolor3.b/255.0) - - # === verts are upper case, edges are lower case === - A, B, C = vertex1.index, vertex2.index, vertex3.index - a, b, c = (A, B), (B, C), (C, A) - - if edge_table.has_key((B, A)): - edge_table[(B, A)][1] = i - edge_table[(B, A)][4] = c - edge_table[(B, A)][5] = b - if has_vertex_colors(mesh): edge_table[(B, A)][8] = Bcol - else: - if has_vertex_colors(mesh): - edge_table[(A, B)] = [i, None, c, b, None, None, None, Bcol, None] - else: - edge_table[(A, B)] = [i, None, c, b, None, None, None] - - if edge_table.has_key((C, B)): - edge_table[(C, B)][1] = i - edge_table[(C, B)][4] = a - edge_table[(C, B)][5] = c - if has_vertex_colors(mesh): edge_table[(C, B)][8] = Ccol - else: - if has_vertex_colors(mesh): - edge_table[(B, C)] = [i, None, a, c, None, None, None, Ccol, None] - else: - edge_table[(B, C)] = [i, None, a, c, None, None, None] - - if edge_table.has_key((A, C)): - edge_table[(A, C)][1] = i - edge_table[(A, C)][4] = b - edge_table[(A, C)][5] = a - if has_vertex_colors(mesh): edge_table[(A, C)][8] = Acol - else: - if has_vertex_colors(mesh): - edge_table[(C, A)] = [i, None, b, a, None, None, None, Acol, None] - else: - edge_table[(C, A)] = [i, None, b, a, None, None, None] - diff --git a/release/scripts/bpymodules/paths_ai2obj.py b/release/scripts/bpymodules/paths_ai2obj.py deleted file mode 100644 index 6eb5023a8d4..00000000000 --- a/release/scripts/bpymodules/paths_ai2obj.py +++ /dev/null @@ -1,506 +0,0 @@ -# -*- coding: latin-1 -*- -""" -paths_ai2obj.py -# --------------------------------------------------------------- -Copyright (c) jm soler juillet/novembre 2004-april 2007, -# --------------------------------------------------------------- - released under GNU Licence - for the Blender 2.45 Python Scripts Bundle. -Ce programme est libre, vous pouvez le redistribuer et/ou -le modifier selon les termes de la Licence Publique Générale GNU -publiée par la Free Software Foundation (version 2 ou bien toute -autre version ultérieure choisie par vous). - -Ce programme est distribué car potentiellement utile, mais SANS -AUCUNE GARANTIE, ni explicite ni implicite, y compris les garanties -de commercialisation ou d'adaptation dans un but spécifique. -Reportez-vous à la Licence Publique Générale GNU pour plus de détails. - -Vous devez avoir reçu une copie de la Licence Publique Générale GNU -en même temps que ce programme ; si ce n'est pas le cas, écrivez à la -Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, -MA 02111-1307, États-Unis. - - -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 St, Fifth Floor, Boston, MA 02110-1301 USA -# --------------------------------------------------------------- -#---------------------------------------------- -# -# Page officielle : -# http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_import_ai_en.htm -# Communiquer les problemes et erreurs sur: -# http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender -#---------------------------------------------- - -#Changelog -#---------------------------------------------- -# 0.1.1 : 2004/08/03, bug in boundingbox reading when Value are negative -# 0.1.2 : 2005/06/12, gmove tranformation properties -# 0.1.3 : 2005/06/25, added a __name__ test to use the script alone -# 0.1.4 : 2005/06/25, closepath improvements -# 0.1.5 : 2005/06/25, ... -# 0.1.6 : 2005/06/26, warning for compacted file - compatibility increased up to AI 10.0 plain text -# 0.1.7 : 2005/06/25, two more closepath improvements -# -# 0.1.8 : 2006/07/03, two more closepath improvements -# 0.1.9 : 2007/05/06, modif on the method that gets the last object on - the list data -# 2008/03/12, Added character encoding line so french text -# does not break python interpreters. - -""" -SHARP_IMPORT=0 -SCALE=1 -NOTHING_TODO=1 -AI_VERSION='' - -GSTACK = [] -GSCALE = [] -GTRANSLATE = [] - -import sys -#oldpath=sys.path -import Blender -BLversion=Blender.Get('version') - -try: - import nt - os=nt - os.sep='\\' - -except: - import posix - os=posix - os.sep='/' - -def isdir(path): - try: - st = os.stat(path) - return 1 - except: - return 0 - -def split(pathname): - if pathname.find(os.sep)!=-1: - k0=pathname.split(os.sep) - else: - if os.sep=='/': - k0=pathname.split('\\') - else: - k0=pathname.split('/') - - directory=pathname.replace(k0[len(k0)-1],'') - Name=k0[len(k0)-1] - return directory, Name - -def join(l0,l1): - return l0+os.sep+l1 - -os.isdir=isdir -os.split=split -os.join=join - -def filtreFICHIER(nom): - f=open(nom,'rU') - t=f.readlines() - f.close() - - if len(t)>1 and t[0].find('EPSF')==-1: - return t - else: - name = "OK?%t| Not a valid file or an empty file ... " # if no %xN int is set, indices start from 1 - result = Blender.Draw.PupMenu(name) - - return 'false' - -#=============================== -# Data -#=============================== -#=============================== -# Blender Curve Data -#=============================== -objBEZIER=0 -objSURFACE=5 -typBEZIER3D=1 #3D -typBEZIER2D=9 #2D - -class Bez: - def __init__(self): - self.co=[] - self.ha=[0,0] - self.tag='' - -class ITEM: - def __init__(self): - self.type = typBEZIER3D, - self.pntsUV = [0,0] - self.resolUV = [32,0] - self.orderUV = [0,0] - self.flagUV = [0,0] - self.Origine = [0.0,0.0] - self.beziers_knot = [] - -class COURBE: - def __init__(self): - self.magic_number='3DG3' - self.type = objBEZIER - self.number_of_items = 0 - self.ext1_ext2 = [0,0] - self.matrix = """0.0 0.0 1.0 0.0 -0.0 1.0 0.0 0.0 -0.0 0.0 1.0 0.0 -0.0 0.0 0.0 1.0 """ - self.ITEM = {} - -courbes=COURBE() - -PATTERN={} - -BOUNDINGBOX={'rec':[],'coef':1.0} -npat=0 -#===================================================================== -#======== name of the curve in teh courbes dictionnary =============== -#===================================================================== -n0=0 - -#===================================================================== -#====================== current Point ================================ -#===================================================================== -CP=[0.0,0.0] #currentPoint - - -# modifs 12/06/2005 -#===================================================================== -#====================== current transform ============================ -#===================================================================== -class transform: - def __init__(self,matrix=[1,0,01],x=0.0,y=0.0): - self.matrix=matrix[:] - self.xy=[x,y] - -def G_move(l,a): - global GSCALE, GTRANSLATE, GSTACK - #print GSCALE, GTRANSLATE, GSTACK - return str((float(l)+GTRANSLATE[a]+GSTACK[-1].xy[a])*GSCALE[a]) -# modifs 12/06/2005 - - -#===================================================================== -#===== to compare last position to the original move to displacement = -#===== needed for cyclic efinition ================================= -#===================================================================== -def test_egalitedespositions(f1,f2): - if f1[0]==f2[0] and f1[1]==f2[1]: - return Blender.TRUE - else: - return Blender.FALSE - - -def Open_GEOfile(dir,nom): - if BLversion>=233: - in_editmode = Blender.Window.EditMode() - if in_editmode: Blender.Window.EditMode(0) - Blender.Load(dir+nom+'OOO.obj', 1) - BO=Blender.Scene.GetCurrent().objects.active - BO.RotY=0.0 - BO.RotX=1.57 - BO.makeDisplayList() - Blender.Window.RedrawAll() - else: - print "Not yet implemented" - -def create_GEOtext(courbes): - global SCALE, B, BOUNDINGBOX - r=BOUNDINGBOX['rec'] - - if SCALE==1: - SCALE=1.0 - elif SCALE==2: - SCALE=r[2]-r[0] - elif SCALE==3: - SCALE=r[3]-r[1] - - t=[] - t.append(courbes.magic_number+'\n') - t.append(str(courbes.type)+'\n') - t.append(str(courbes.number_of_items)+'\n') - t.append(str(courbes.ext1_ext2[0])+' '+str(courbes.ext1_ext2[1])+'\n') - t.append(courbes.matrix+'\n') - - for k in courbes.ITEM.keys(): - if len(courbes.ITEM[k].beziers_knot)>1 : - t.append("%s\n"%courbes.ITEM[k].type) - t.append("%s %s \n"%(courbes.ITEM[k].pntsUV[0],courbes.ITEM[k].pntsUV[1])) - t.append("%s %s \n"%(courbes.ITEM[k].resolUV[0],courbes.ITEM[k].resolUV[1])) - t.append("%s %s \n"%(courbes.ITEM[k].orderUV[0],courbes.ITEM[k].orderUV[1])) - t.append("%s %s \n"%(courbes.ITEM[k].flagUV[0],courbes.ITEM[k].flagUV[1])) - - flag =courbes.ITEM[k].flagUV[0] - - for k2 in range(len(courbes.ITEM[k].beziers_knot)): - #print k2 - k1 =courbes.ITEM[k].beziers_knot[k2] - t.append("%4f 0.0 %4f \n"%(float(k1.co[2])/SCALE,float(k1.co[3])/SCALE)) - t.append("%4f 0.0 %4f \n"%(float(k1.co[4])/SCALE,float(k1.co[5])/SCALE)) - t.append("%4f 0.0 %4f \n"%(float(k1.co[0])/SCALE,float(k1.co[1])/SCALE)) - - t.append(str(k1.ha[0])+' '+str(k1.ha[1])+'\n') - return t - -def save_GEOfile(dir,nom,t): - f=open(dir+nom+'OOO.obj','w') - f.writelines(t) - f.close() - #warning = "REMINDER : %t | Do not forget to rename your blender file NOW ! %x1" - #result = Blender.Draw.PupMenu(warning) - - -#===================================================================== -#===== AI format : DEBUT ========================= -#===================================================================== -def mouvement_vers(l,n0,CP): - if n0 in courbes.ITEM.keys(): - n0+=1 - - CP=[l[-3].replace('d',''),l[-2]] - courbes.ITEM[n0]=ITEM() - courbes.ITEM[n0].Origine=[l[-3].replace('d',''),l[-2]] - - B=Bez() - B.co=[CP[0],CP[1],CP[0],CP[1],CP[0],CP[1]] - B.ha=[0,0] - B.tag=l[-1] - - courbes.ITEM[n0].beziers_knot.append(B) - - return courbes,n0,CP - -def courbe_vers_c(l,l2, n0,CP): #c,C - - B=Bez() - B.co=[l[4],l[5],l[2],l[3],l[4],l[5]] - B.tag=l[-1] - B.ha=[0,0] - - BP=courbes.ITEM[n0].beziers_knot[-1] - - BP.co[0]=l[0] - BP.co[1]=l[1] - - courbes.ITEM[n0].beziers_knot.append(B) - - CP=[B.co[4],B.co[5]] - return courbes,n0,CP - - -def courbe_vers_v(l,n0,CP): #v-V - - B=Bez() - B.tag=l[-1] - B.co=[l[2],l[3],l[0],l[1],l[2],l[3]] - B.ha=[0,0] - - courbes.ITEM[n0].beziers_knot.append(B) - - CP=[B.co[4],B.co[5]] - return courbes,n0,CP - -def courbe_vers_y(l,n0,CP): #y - B=Bez() - B.tag=l[-1] - B.co=[l[2],l[3],l[2],l[3],l[2],l[3]] - B.ha=[0,0] - - BP=courbes.ITEM[n0].beziers_knot[-1] - BP.co[0]=l[0] - BP.co[1]=l[1] - - courbes.ITEM[n0].beziers_knot.append(B) - CP=[B.co[4],B.co[5]] - return courbes,n0,CP - - -def ligne_tracee_l(l,n0,CP): - B=Bez() - B.tag=l[-1] - B.co=[l[0],l[1],l[0],l[1],l[0],l[1]] - B.ha=[0,0] - - BP=courbes.ITEM[n0].beziers_knot[-1] - - courbes.ITEM[n0].beziers_knot.append(B) - CP=[B.co[4],B.co[5]] - return courbes,n0,CP - -def ligne_fermee(l,n0,CP): - courbes.ITEM[n0].flagUV[0]=1 - - if len(courbes.ITEM[n0].beziers_knot)>1: - BP=courbes.ITEM[n0].beziers_knot[-1] - BP0=courbes.ITEM[n0].beziers_knot[0] - - if BP.tag not in ['l','L']: - BP.co[0]=BP0.co[0] #4-5 point prec - BP.co[1]=BP0.co[1] - - del courbes.ITEM[n0].beziers_knot[0] - return courbes,n0,CP - -def passe(l,n0,CP): - return courbes,n0,CP - -Actions= { "C" : courbe_vers_c, - "c" : courbe_vers_c, - "V" : courbe_vers_v, - "v" : courbe_vers_v, - "Y" : courbe_vers_y, - "y" : courbe_vers_y, - "m" : mouvement_vers, - "l" : ligne_tracee_l, - "L" : ligne_tracee_l, - "F" : passe, - "f" : ligne_fermee, - "B" : passe, - "b" : ligne_fermee, - "S" : passe, - "s" : ligne_fermee, - "N" : ligne_fermee, - "n" : passe, - } - -TAGcourbe=Actions.keys() - -def pik_pattern(t,l): - global npat, PATTERN, BOUNDINGBOX, AI_VERSION - while t[l].find('%%EndSetup')!=0: - if t[l].find('%%Creator: Adobe Illustrator(R)')!=-1: - print t[l] - AI_VERSION=t[l].split()[-1] - print AI_VERSION - - if t[l].find('%%BoundingBox:')!=-1: - t[l]=t[l][t[l].find(':')+1:] - l0=t[l].split() - BOUNDINGBOX['rec']=[float(l0[-4]),float(l0[-3]),float(l0[-2]),float(l0[-1])] - r=BOUNDINGBOX['rec'] - BOUNDINGBOX['coef']=(r[3]-r[1])/(r[2]-r[0]) - #print l, - if t[l].find('BeginPattern')!=-1: - nomPattern=t[l][t[l].find('(')+1:t[l].find(')')] - PATTERN[nomPattern]={} - - if t[l].find('BeginPatternLayer')!=-1: - npat+=1 - PATTERN[nomPattern][npat]=[] - while t[l].find('EndPatternLayer')==-1: - #print t[l] - PATTERN[nomPattern][npat].append(l) - l+=1 - if l+1<len(t): - l=l+1 - else: - return 1,l - return 1,l - -def scan_FILE(nom): - global CP, courbes, SCALE, NOTHING_TODO - dir,name=split(nom) - name=name.split('.') - n0=0 - result=0 - t=filtreFICHIER(nom) - - if nom.upper().find('.AI')!=-1 and t!='false': - if not SHARP_IMPORT: - warning = "Select Size : %t| As is %x1 | Scale on Height %x2| Scale on Width %x3" - SCALE = Blender.Draw.PupMenu(warning) - - npat=0 - l=0 - do=0 - while l <len(t)-1 : - if not do: - do,l=pik_pattern(t,l) - #print 'len(t)',len(t) - t[l].replace('\n','') - if t[l].find('%%EOF')==0: - break - if t[l][0]!='%': - l0=t[l].split() - #print l0 - if l0[0][0] in ['F','f','N','n','B','b']: - l3=l0[0][0] - courbes,n0,CP=Actions[l3](l3,n0,CP) - l0[0]=l0[1:] - - if l0[-1] in TAGcourbe: - NOTHING_TODO=0 - if l0[-1] in ['C','c']: - l2=t[l+1].split() - courbes,n0,CP=Actions[l0[-1]](l0,l2,n0,CP) - else: - courbes,n0,CP=Actions[l0[-1]](l0,n0,CP) - l=l+1; #print l - t=[] - - - courbes.number_of_items=len(courbes.ITEM.keys()) - for k in courbes.ITEM.keys(): - courbes.ITEM[k].pntsUV[0] =len(courbes.ITEM[k].beziers_knot) - - - if courbes.number_of_items>0: - if len(PATTERN.keys() )>0: - #print len(PATTERN.keys() ) - warning = "Pattern list (for info not used): %t| " - p0=1 - for P in PATTERN.keys(): - warning+="%s %%x%s|"%(P,p0) - p0+=1 - Padd = Blender.Draw.PupMenu(warning) - - t=create_GEOtext(courbes) - save_GEOfile(dir,name[0],t) - - # 0.1.8 --------------------------------- - # [O.select(0) for O in Blender.Scene.getCurrent().getChildren()] - # 0.1.8 --------------------------------- - - Open_GEOfile(dir,name[0]) - - # 0.1.8 --------------------------------- - Blender.Object.Get()[-1].setName(name[0]) - # 0.1.8 --------------------------------- - - else: - pass -#===================================================================== -#====================== AI format mouvements ========================= -#===================================================================== -#========================================================= -# une sorte de contournement qui permet d'utiliser la fonction -# et de documenter les variables Window.FileSelector -#========================================================= -def fonctionSELECT(nom): - global NOTHING_TODO,AI_VERSION - scan_FILE(nom) - if NOTHING_TODO==1: - warning = "AI %s compatible file "%AI_VERSION+" but nothing to do ? %t| Perhaps a compacted file ... " - NOTHING = Blender.Draw.PupMenu(warning) - -if __name__=="__main__": - Blender.Window.FileSelector (fonctionSELECT, 'SELECT AI FILE') -#sys.path=oldpath diff --git a/release/scripts/bpymodules/paths_eps2obj.py b/release/scripts/bpymodules/paths_eps2obj.py deleted file mode 100644 index e1643c3bf40..00000000000 --- a/release/scripts/bpymodules/paths_eps2obj.py +++ /dev/null @@ -1,452 +0,0 @@ -#---------------------------------------------- -# (c) jm soler juillet 2004-juin 2005 , released under Blender Artistic Licence -# for the Blender 2.34-2.37 Python Scripts Bundle. -# -# last update: 06/05/2007 -#---------------------------------------------- -# Page officielle : -# http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_import_eps.htm -# Communiquer les problemes et erreurs sur: -# http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender -#---------------------------------------------- -SHARP_IMPORT = 0 -SCALE = 1.0 -scale = 1 - -import sys -#oldpath=sys.path - -import Blender -from Blender import Draw -BLversion=Blender.Get('version') - -try: - import nt - os=nt - os.sep='\\' - -except: - import posix - os=posix - os.sep='/' - -def isdir(path): - try: - st = os.stat(path) - return 1 - except: - return 0 - -def split(pathname): - if pathname.find(os.sep)!=-1: - k0=pathname.split(os.sep) - else: - if os.sep=='/': - k0=pathname.split('\\') - else: - k0=pathname.split('/') - - directory=pathname.replace(k0[len(k0)-1],'') - Name=k0[len(k0)-1] - return directory, Name - -def join(l0,l1): - return l0+os.sep+l1 - -os.isdir=isdir -os.split=split -os.join=join - -def filtreFICHIER(nom): - f=open(nom,'rU') - t=f.readlines() - f.close() - if len(t)==1 and t[0].find('\r'): - t=t[0].split('\r') - if len(t)>1 and t[0].find('PS-Adobe-3.0')==-1 and t[0].find('EPSF')==-1: - return t - else: - name = "OK?%t| Not a valid file or an empty file or... %x1| not a pure PS-Adobe-2.0 file %x2 " - result = Blender.Draw.PupMenu(name) - return 'false' - -#=============================== -# Data -#=============================== -#=============================== -# Blender Curve Data -#=============================== -objBEZIER=0 -objSURFACE=5 -typBEZIER3D=1 #3D -typBEZIER2D=9 #2D - -class Bez: - def __init__(self): - self.co=[] - self.ha=[0,0] - -class ITEM: - def __init__(self): - self.type = typBEZIER3D, - self.pntsUV = [0,0] - self.resolUV = [32,0] - self.orderUV = [0,0] - self.flagUV = [0,0] - self.Origine = [0.0,0.0] - self.beziers_knot = [] - -class COURBE: - def __init__(self): - self.magic_number='3DG3' - self.type = objBEZIER - self.number_of_items = 0 - self.ext1_ext2 = [0,0] - self.matrix = """0.0 0.0 1.0 0.0 -0.0 1.0 0.0 0.0 -0.0 0.0 1.0 0.0 -0.0 0.0 0.0 1.0 """ #- right-handed object matrix. Used to determine position, rotation and size - self.ITEM = {} - -courbes=COURBE() -PATTERN={} -BOUNDINGBOX={'rec':[],'coef':1.0} -npat=0 -#===================================================================== -#======== name of the curve in teh courbes dictionnary =============== -#===================================================================== -n0=0 - -#===================================================================== -#====================== current Point ================================ -#===================================================================== -CP=[0.0,0.0] #currentPoint - -# modifs 12/06/2005 -#===================================================================== -#====================== current transform ============================ -#===================================================================== -class transform: - def __init__(self,matrix=[1,0,01],x=0.0,y=0.0): - self.matrix=matrix[:] - self.xy=[x,y] - -GSTACK = [] -stack=transform() -GSTACK.append(stack) - -GSCALE = [1.0,1.0] -GTRANSLATE = [0.0,0.0] - -def G_move(l,a): - global GSCALE, GTRANSLATE, GSTACK - #print GSCALE, GTRANSLATE, GSTACK - return str((float(l)+GTRANSLATE[a]+GSTACK[-1].xy[a])*GSCALE[a]) -# modifs 12/06/2005 - -#===================================================================== -#===== to compare last position to the original move to displacement = -#===== needed for cyclic efinition ================================= -#===================================================================== -def test_egalitedespositions(f1,f2): - if f1[0]==f2[0] and f1[1]==f2[1]: - return Blender.TRUE - else: - return Blender.FALSE - - -def Open_GEOfile(dir,nom): - global SCALE,BOUNDINGBOX, scale - if BLversion>=233: - Blender.Load(dir+nom+'OOO.obj', 1) - BO=Blender.Scene.GetCurrent().objects.active - BO.RotY=3.1416 - BO.RotZ=3.1416 - BO.RotX=3.1416/2.0 - if scale==1: - BO.LocY+=BOUNDINGBOX['rec'][3] - else: - BO.LocY+=BOUNDINGBOX['rec'][3]/SCALE - - BO.makeDisplayList() - Blender.Window.RedrawAll() - else: - print "Not yet implemented" - -def create_GEOtext(courbes): - global SCALE, B, BOUNDINGBOX,scale - r=BOUNDINGBOX['rec'] - - if scale==1: - SCALE=1.0 - elif scale==2: - SCALE=r[2]-r[0] - elif scale==3: - SCALE=r[3]-r[1] - - t=[] - t.append(courbes.magic_number+'\n') - t.append(str(courbes.type)+'\n') - t.append(str(courbes.number_of_items)+'\n') - t.append(str(courbes.ext1_ext2[0])+' '+str(courbes.ext1_ext2[1])+'\n') - t.append(courbes.matrix+'\n') - - for k in courbes.ITEM.keys(): - t.append("%s\n"%courbes.ITEM[k].type) - t.append("%s %s \n"%(courbes.ITEM[k].pntsUV[0],courbes.ITEM[k].pntsUV[1])) - t.append("%s %s \n"%(courbes.ITEM[k].resolUV[0],courbes.ITEM[k].resolUV[1])) - t.append("%s %s \n"%(courbes.ITEM[k].orderUV[0],courbes.ITEM[k].orderUV[1])) - t.append("%s %s \n"%(courbes.ITEM[k].flagUV[0],courbes.ITEM[k].flagUV[1])) - - flag =courbes.ITEM[k].flagUV[0] - - for k2 in range(flag,len(courbes.ITEM[k].beziers_knot)): - k1 =courbes.ITEM[k].beziers_knot[k2] - t.append("%4f 0.0 %4f \n"%(float(k1.co[0])/SCALE,float(k1.co[1])/SCALE)) - t.append("%4f 0.0 %4f \n"%(float(k1.co[2])/SCALE,float(k1.co[3])/SCALE)) - t.append("%4f 0.0 %4f \n"%(float(k1.co[4])/SCALE,float(k1.co[5])/SCALE)) - t.append(str(k1.ha[0])+' '+str(k1.ha[1])+'\n') - return t - -def save_GEOfile(dir,nom,t): - f=open(dir+nom+'OOO.obj','w') - f.writelines(t) - f.close() - - #name = "REMINDER : %t | Do not forget to rename your blender file NOW ! %x1" - #result = Blender.Draw.PupMenu(name) - - -#===================================================================== -#===== EPS format : DEBUT ========================= -#===================================================================== -def mouvement_vers(l,n0,CP): - if n0 in courbes.ITEM.keys(): - #if test_egalitedespositions(courbes.ITEM[n0].Origine,CP): - # courbes.ITEM[n0].flagUV[0]=1 - n0+=1 - CP=[l[-3].replace('d',''),l[-2]] - else: - CP=[l[-3].replace('d',''),l[-2]] - #i= - courbes.ITEM[n0]=ITEM() - courbes.ITEM[n0].Origine=[l[-3].replace('d',''),l[-2]] - - B=Bez() - B.co=[G_move(CP[0],0), - G_move(CP[1],1), - G_move(CP[0],0), - G_move(CP[1],1), - G_move(CP[0],0), - G_move(CP[1],1)] - - B.ha=[0,0] - courbes.ITEM[n0].beziers_knot.append(B) - - return courbes,n0,CP - -def rmouvement_vers(l,n0,CP): - if n0 in courbes.ITEM.keys(): - #if test_egalitedespositions(courbes.ITEM[n0].Origine,CP): - # courbes.ITEM[n0].flagUV[0]=1 - n0+=1 - CP=["%4f"%(float(l[-3])+float(CP[0])),"%4f"%(float(l[-2])+float(CP[1]))] - else: - CP=["%4f"%(float(l[-3])+float(CP[0])),"%4f"%(float(l[-2])+float(CP[1]))] - #i= - courbes.ITEM[n0]=ITEM() - courbes.ITEM[n0].Origine=[l[-3].replace('d',''),l[-2]] - - B=Bez() - B.co=[CP[0],CP[1],CP[0],CP[1],CP[0],CP[1]] - B.ha=[0,0] - courbes.ITEM[n0].beziers_knot.append(B) - return courbes,n0,CP - -def courbe_vers_c(l, l2, n0,CP): #c,C - """ - B=Bez() - B.co=[l[0],l[1],l[2],l[3],l[4],l[5]] - B.ha=[0,0] - - courbes.ITEM[n0].beziers_knot.append(B) - """ - B=Bez() - B.co=[G_move(l[2],0), - G_move(l[3],1), - G_move(l[4],0), - G_move(l[5],1), - G_move(l[0],0), - G_move(l[1],1)] - if len(courbes.ITEM[n0].beziers_knot)==1: - CP=[l[0],l[1]] - courbes.ITEM[n0].Origine=[l[0],l[1]] - if l[-1]=='C': - B.ha=[2,2] - else: - B.ha=[0,0] - courbes.ITEM[n0].beziers_knot.append(B) - if len(l2)>1 and l2[-1] in Actions.keys(): - B.co[-2]=G_move(l2[0],0) - B.co[-1]=G_move(l2[1],1) - else: - B.co[-2]=G_move(CP[0],0) - B.co[-1]=G_move(CP[1],1) - return courbes,n0,CP - -def ligne_tracee_l(l,n0,CP): - B=Bez() - B.co=[G_move(l[0],0), - G_move(l[1],1), - G_move(l[0],0), - G_move(l[1],1), - G_move(l[0],0), - G_move(l[1],1)] - B.ha=[0,0] - courbes.ITEM[n0].beziers_knot.append(B) - CP=[l[0],l[1]] - return courbes,n0,CP - -def rligne_tracee_l(l,n0,CP): - B=Bez() - B.co=["%4f"%(float(l[0])+float(CP[0])), - "%4f"%(float(l[1])+float(CP[1])), - "%4f"%(float(l[0])+float(CP[0])), - "%4f"%(float(l[1])+float(CP[1])), - "%4f"%(float(l[0])+float(CP[0])), - "%4f"%(float(l[1])+float(CP[1]))] - B.ha=[0,0] - courbes.ITEM[n0].beziers_knot.append(B) - CP=[l[0],l[1]] - return courbes,n0,CP - -Actions= { "curveto" : courbe_vers_c, - "curveto" : courbe_vers_c, - "moveto" : mouvement_vers, - "rmoveto" : mouvement_vers, - "lineto" : ligne_tracee_l, - "rlineto" : rligne_tracee_l -} - -TAGcourbe=Actions.keys() - -""" -def pik_pattern(t,l): - global npat, PATTERN, BOUNDINGBOX - while t[l].find('%%EndSetup')!=0: - if t[l].find('%%BoundingBox:')!=-1: - l0=t[l].split() - BOUNDINGBOX['rec']=[float(l0[-4]),float(l0[-3]),float(l0[-2]),float(l0[-1])] - r=BOUNDINGBOX['rec'] - BOUNDINGBOX['coef']=(r[3]-r[1])/(r[2]-r[0]) - print l, - if t[l].find('BeginPatternLayer')!=-1: - npat+=1 - PATTERN[npat]=[] - while t[l].find('EndPatternLayer')==-1: - print t[l] - PATTERN[npat].append(l) - l+=1 - if l+1<len(t): - l=l+1 - else: - return 1,l - return 1,l -""" - -def scan_FILE(nom): - global CP, courbes, SCALE, scale, GSTACK, GSCALE, GTRANSLATE - dir,name=split(nom) - name=name.split('.') - n0=0 - result=0 - t=filtreFICHIER(nom) - #print t - if t!='false' and (nom.upper().find('.EPS')!=-1 or nom.upper().find('.PS')!=-1 ): - if not SHARP_IMPORT: - warning = "Select Size : %t| As is %x1 | Scale on Height %x2| Scale on Width %x3" - scale = Blender.Draw.PupMenu(warning) - npat=0 - l=0 - do=0 - while l <len(t)-1 : - if t[l].find('%%BoundingBox:')!=-1: - l0=t[l].split() - BOUNDINGBOX['rec']=[float(l0[-4]),float(l0[-3]),float(l0[-2]),float(l0[-1])] - r=BOUNDINGBOX['rec'] - BOUNDINGBOX['coef']=(r[3]-r[1])/(r[2]-r[0]) - """ - if not do: - do,l=pik_pattern(t,l) - """ - #print 'len(t)',len(t) - t[l].replace('\n','') - if t[l][0]!='%': - l0=t[l].split() - if l0!=[] and l0[-1] in TAGcourbe: - if l0[-1] in ['curveto']: - l2=t[l+1].split() - courbes,n0,CP=Actions[l0[-1]](l0,l2,n0,CP) - else: - courbes,n0,CP=Actions[l0[-1]](l0,n0,CP) - # modifs 10/06/2005 - elif l0!=[] and l0[-1] in ['scale']: - GSCALE=[float(l0[-3]),float(l0[-2])] - elif l0!=[] and l0[-1] in ['translate']: - GTRANSLATE=[float(l0[-3]),float(l0[-2])] - elif l0!=[] and l0[-1] in ['concat'] and l0[0] in ['gsave']: - l0[1]=l0[1].replace('[','') - l0[-2]=l0[-2].replace(']','') - stack=transform([float(l0[1]),float(l0[2]),float(l0[3]),float(l0[4])],float(l0[5]),float(l0[6])) - GSTACK.append(stack) - #print GSTACK - elif l0!=[] and l0[-1] in ['concat'] and l0[0] in ['grestore']: - del GSTACK[-1] - # modifs 12/06/2005 : end - - - l=l+1#; print l - t=[] - - if t!='false': - courbes.number_of_items=len(courbes.ITEM.keys()) - - for k in courbes.ITEM.keys(): - courbes.ITEM[k].pntsUV[0] =len(courbes.ITEM[k].beziers_knot) - - if test_egalitedespositions(courbes.ITEM[k].Origine, - [courbes.ITEM[k].beziers_knot[-1].co[-2], - courbes.ITEM[k].beziers_knot[-1].co[-1]]): - courbes.ITEM[k].flagUV[0]=1 - courbes.ITEM[k].pntsUV[0] -=1 - - if courbes.number_of_items>0: - if len(PATTERN.keys() )>0: - #print len(PATTERN.keys() ) - pass - t=create_GEOtext(courbes) - save_GEOfile(dir,name[0],t) - Open_GEOfile(dir,name[0]) - - # 03 juillet 2006 ---------------------- - Blender.Object.Get()[-1].setName(name[0]) - # 03 juillet 2006 ---------------------- - - else: - pass - - -#===================================================================== -#====================== EPS format mouvements ========================= -#===================================================================== -#========================================================= -# une sorte de contournement qui permet d'utiliser la fonction -# et de documenter les variables Window.FileSelector -#========================================================= -def fonctionSELECT(nom): - scan_FILE(nom) - -if __name__=="__main__": - Blender.Window.FileSelector (fonctionSELECT, 'SELECT EPS FILE') - - diff --git a/release/scripts/bpymodules/paths_gimp2obj.py b/release/scripts/bpymodules/paths_gimp2obj.py deleted file mode 100644 index c2ce9718c71..00000000000 --- a/release/scripts/bpymodules/paths_gimp2obj.py +++ /dev/null @@ -1,363 +0,0 @@ -# -*- coding: latin-1 -*- -""" -#---------------------------------------------- -# (c) jm soler juillet 2004, -#---------------------------------------------- - released under GNU Licence - for the Blender 2.45 Python Scripts Bundle. -Ce programme est libre, vous pouvez le redistribuer et/ou -le modifier selon les termes de la Licence Publique Générale GNU -publiée par la Free Software Foundation (version 2 ou bien toute -autre version ultérieure choisie par vous). - -Ce programme est distribué car potentiellement utile, mais SANS -AUCUNE GARANTIE, ni explicite ni implicite, y compris les garanties -de commercialisation ou d'adaptation dans un but spécifique. -Reportez-vous à la Licence Publique Générale GNU pour plus de détails. - -Vous devez avoir reçu une copie de la Licence Publique Générale GNU -en même temps que ce programme ; si ce n'est pas le cas, écrivez à la -Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, -MA 02111-1307, États-Unis. - - -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 St, Fifth Floor, Boston, MA 02110-1301 USA - -""" - -# --------------------------------------------------------------- -# last update : 07/05/2007 -#---------------------------------------------- -# Page officielle : -# http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_import_gimp.htm -# Communiquer les problemes et erreurs sur: -# http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender -# Modification History: -# 2008-03-12 Added character encoding line so french text does not break -# python interpreters. -#--------------------------------------------- - -SHARP_IMPORT=0 -SCALE=1 - -import sys -#oldpath=sys.path - -import Blender -BLversion=Blender.Get('version') - -try: - import nt - os=nt - os.sep='\\' - -except: - import posix - os=posix - os.sep='/' - -def isdir(path): - try: - st = os.stat(path) - return 1 - except: - return 0 - -def split(pathname): - if pathname.find(os.sep)!=-1: - k0=pathname.split(os.sep) - else: - if os.sep=='/': - k0=pathname.split('\\') - else: - k0=pathname.split('/') - - directory=pathname.replace(k0[len(k0)-1],'') - Name=k0[len(k0)-1] - return directory, Name - -def join(l0,l1): - return l0+os.sep+l1 - -os.isdir=isdir -os.split=split -os.join=join - -def filtreFICHIER(nom): - f=open(nom,'r') - t=f.readlines() - f.close() - if len(t)==1 and t[0].find('\r'): - t=t[0].split('\r') - if len(t)>1 and t[1].find('#POINTS:')==0: - return t - else: - warning = "OK?%t| Not a valid file or an empty file ... " # if no %xN int is set, indices start from 1 - result = Blender.Draw.PupMenu(warning) - return "false" - -#=============================== -# Data -#=============================== -#=============================== -# Blender Curve Data -#=============================== -objBEZIER=0 -objSURFACE=5 -typBEZIER3D=1 #3D -typBEZIER2D=9 #2D - -class Bez: - def __init__(self): - self.co=[] - self.ha=[0,0] - - def echo(self): - #print 'co = ', self.co - #print 'ha = ', self.ha - pass - -class ITEM: - def __init__(self): - self.type = typBEZIER3D, - self.pntsUV = [0,0] - self.resolUV = [32,0] - self.orderUV = [0,0] - self.flagUV = [0,0] - self.Origine = [0.0,0.0] - self.beziers_knot = [] - -class COURBE: - def __init__(self): - self.magic_number='3DG3' - self.type = objBEZIER - self.number_of_items = 0 - self.ext1_ext2 = [0,0] - self.matrix = """0.0 0.0 1.0 0.0 -0.0 1.0 0.0 0.0 -0.0 0.0 1.0 0.0 -0.0 0.0 0.0 1.0 """ #- right-handed object matrix. Used to determine position, rotation and size - self.ITEM = {} - -courbes=COURBE() -PATTERN={} -BOUNDINGBOX={'rec':[],'coef':1.0} -npat=0 -#===================================================================== -#======== name of the curve in the courbes dictionnary =============== -#===================================================================== -n0=0 - -#===================================================================== -#====================== current Point ================================ -#===================================================================== -CP=[0.0,0.0] #currentPoint - -def MINMAX(b): - global BOUNDINGBOX - r=BOUNDINGBOX['rec'] - for m in range(0,len(b)-2,2): - #print m, m+1 , len(b)-1 - #print b[m], r, r[0] - if float(b[m])<r[0]: - r[0]=float(b[m]) - - if float(b[m])>r[2]: r[2]=float(b[m]) - - if float(b[m+1])<r[1]: r[1]=float(b[m+1]) - if float(b[m+1])>r[3]: r[3]=float(b[m+1]) - -#===================================================================== -#===== to compare last position to the original move to displacement = -#===== needed for cyclic efinition ================================= -#===================================================================== -def test_egalitedespositions(f1,f2): - if f1[0]==f2[0] and f1[1]==f2[1]: - return Blender.TRUE - else: - return Blender.FALSE - - -def Open_GEOfile(dir,nom): - if BLversion>=233: - Blender.Load(dir+nom+'OOO.obj', 1) - BO=Blender.Scene.GetCurrent().objects.active - BO.LocZ=1.0 - BO.makeDisplayList() - Blender.Window.RedrawAll() - else: - print "Not yet implemented" - -def create_GEOtext(courbes): - global SCALE, B, BOUNDINGBOX - r=BOUNDINGBOX['rec'] - if SCALE==1: - SCALE=1.0 - elif SCALE==2: - SCALE=r[2]-r[0] - elif SCALE==3: - SCALE=r[3]-r[1] - - t=[] - t.append(courbes.magic_number+'\n') - t.append(str(courbes.type)+'\n') - t.append(str(courbes.number_of_items)+'\n') - t.append(str(courbes.ext1_ext2[0])+' '+str(courbes.ext1_ext2[1])+'\n') - t.append(courbes.matrix+'\n') - - for k in courbes.ITEM.keys(): - - t.append("%s\n"%courbes.ITEM[k].type) - - t.append("%s %s \n"%(courbes.ITEM[k].pntsUV[0],courbes.ITEM[k].pntsUV[1])) - t.append("%s %s \n"%(courbes.ITEM[k].resolUV[0],courbes.ITEM[k].resolUV[1])) - t.append("%s %s \n"%(courbes.ITEM[k].orderUV[0],courbes.ITEM[k].orderUV[1])) - t.append("%s %s \n"%(courbes.ITEM[k].flagUV[0],courbes.ITEM[k].flagUV[1])) - - flag =0#courbes.ITEM[k].flagUV[0] - - for k2 in range(flag,len(courbes.ITEM[k].beziers_knot)): - k1 =courbes.ITEM[k].beziers_knot[k2] - t.append("%4f 0.0 %4f \n"%(float(k1.co[0])/SCALE,float(k1.co[1])/SCALE)) - t.append("%4f 0.0 %4f \n"%(float(k1.co[4])/SCALE,float(k1.co[5])/SCALE)) - t.append("%4f 0.0 %4f \n"%(float(k1.co[2])/SCALE,float(k1.co[3])/SCALE)) - t.append(str(k1.ha[0])+' '+str(k1.ha[1])+'\n') - return t - -def save_GEOfile(dir,nom,t): - f=open(dir+nom+'OOO.obj','w') - f.writelines(t) - f.close() - #warning = "REMINDER : %t | Do not forget to rename your blender file NOW ! %x1" - #result = Blender.Draw.PupMenu(warning) - - -#===================================================================== -#===== GIMP format : DEBUT ========================= -#===================================================================== -CLOSED=0 - -def mouvement_vers(l,l1,l2,n0): - global BOUNDINGBOX, CP - if l[1] == '3' : - n0+=1 - courbes.ITEM[n0]=ITEM() - courbes.ITEM[n0].Origine=[l[-3],l[-1],] - courbes.ITEM[n0-1].beziers_knot[0].co[0]=CP[0] - courbes.ITEM[n0-1].beziers_knot[0].co[1]=CP[1] - CP=[l2[-3], l2[-1]] - - elif l[1]=='1' and (n0 not in courbes.ITEM.keys()): - courbes.ITEM[n0]=ITEM() - courbes.ITEM[n0].Origine=[l[-3],l[-1],] - CP=[l2[-3], l2[-1]] - - B=Bez() - B.co=[ CP[0],CP[1], - l1[-3], l1[-1], - l[-3], l[-1]] - - CP=[l2[-3], l2[-1]] - - if BOUNDINGBOX['rec']==[]: - BOUNDINGBOX['rec']=[float(l2[-3]), float(l2[-1]), float(l[-3]), float(l[-1])] - B.ha=[0,0] - - """ - if len( courbes.ITEM[n0].beziers_knot)>=1: - courbes.ITEM[n0].beziers_knot[-1].co[2]=l1[-3] - courbes.ITEM[n0].beziers_knot[-1].co[3]=l1[-1] - """ - - MINMAX(B.co) - courbes.ITEM[n0].beziers_knot.append(B) - return courbes,n0 - -Actions= { "1" : mouvement_vers, - "3" : mouvement_vers } - -TAGcourbe=Actions.keys() - -def scan_FILE(nom): - global CP, courbes, SCALE, MAX, MIN, CLOSED - dir,name=split(nom) - name=name.split('.') - #print name - n0=0 - result=0 - t=filtreFICHIER(nom) - if t!="false": - if not SHARP_IMPORT: - warning = "Select Size : %t| As is %x1 | Scale on Height %x2| Scale on Width %x3" - SCALE = Blender.Draw.PupMenu(warning) - npat=0 - l=0 - while l <len(t)-1 : - #print 'len(t)',len(t) - t[l].replace('\n','') - if t[l][0]!='%': - l0=t[l].split() - #print l0[0], l0[1] - if l0[0]=='TYPE:' and l0[1] in TAGcourbe: - #print l0[0], l0[1], - l1=t[l+1].split() - l2=t[l+2].split() - courbes,n0=Actions[l0[1]](l0,l1,l2,n0) - elif l0[0]=='#Point': - POINTS= int(l0[0]) - elif l0[0]=='CLOSED:' and l0[1]=='1': - CLOSED=1 - l=l+1; - - courbes.number_of_items=len(courbes.ITEM.keys()) - - courbes.ITEM[n0].beziers_knot[0].co[0]=CP[0] - courbes.ITEM[n0].beziers_knot[0].co[1]=CP[1] - - for k in courbes.ITEM.keys(): - #print k - if CLOSED == 1: - B=Bez() - B.co=courbes.ITEM[k].beziers_knot[0].co[:] - B.ha=courbes.ITEM[k].beziers_knot[0].ha[:] - B.echo() - courbes.ITEM[k].beziers_knot.append(B) - courbes.ITEM[k].flagUV[0]=1 - courbes.ITEM[k].pntsUV[0] =len(courbes.ITEM[k].beziers_knot) - - if courbes.number_of_items>0: - t=create_GEOtext(courbes) - save_GEOfile(dir,name[0],t) - Open_GEOfile(dir,name[0]) - # 0.1.8 --------------------------------- - Blender.Object.Get()[-1].setName(name[0]) - # 0.1.8 --------------------------------- - - else: - pass - -#===================================================================== -#====================== GIMP Path format mouvements ========================= -#===================================================================== -#========================================================= -# une sorte de contournement qui permet d'utiliser la fonction -# et de documenter les variables Window.FileSelector -#========================================================= -def fonctionSELECT(nom): - scan_FILE(nom) - -if __name__=="__main__": - Blender.Window.FileSelector (fonctionSELECT, 'SELECT GIMP FILE') - diff --git a/release/scripts/bpymodules/paths_svg2obj.py b/release/scripts/bpymodules/paths_svg2obj.py deleted file mode 100644 index 6bab6dcbfd8..00000000000 --- a/release/scripts/bpymodules/paths_svg2obj.py +++ /dev/null @@ -1,1651 +0,0 @@ -# -*- coding: latin-1 -*- -""" -SVG 2 OBJ translater, 0.5.9o -Copyright (c) jm soler juillet/novembre 2004-april 2009, -# --------------------------------------------------------------- - released under GNU Licence - for the Blender 2.42 Python Scripts Bundle. -Ce programme est libre, vous pouvez le redistribuer et/ou -le modifier selon les termes de la Licence Publique Générale GNU -publiée par la Free Software Foundation (version 2 ou bien toute -autre version ultérieure choisie par vous). - -Ce programme est distribué car potentiellement utile, mais SANS -AUCUNE GARANTIE, ni explicite ni implicite, y compris les garanties -de commercialisation ou d'adaptation dans un but spécifique. -Reportez-vous à la Licence Publique Générale GNU pour plus de détails. - -Vous devez avoir reçu une copie de la Licence Publique Générale GNU -en même temps que ce programme ; si ce n'est pas le cas, écrivez à la -Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, -MA 02111-1307, États-Unis. - -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 St, Fifth Floor, Boston, MA 02110-1301 USA -# --------------------------------------------------------------- -# -#--------------------------------------------------------------------------- -# Page officielle : -# http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_import_svg.htm -# http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_import_svg_en.htm -# Communiquer les problemes et erreurs sur: -# http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender -#--------------------------------------------------------------------------- - ---Old Concept : translate SVG file in GEO .obj file and try to load it. - was removed for the Blender 2.4x release. - .-- Curiousity : the original matrix must be : - | - | 0.0 0.0 1.0 0.0 - | 0.0 1.0 0.0 0.0 - | 0.0 0.0 1.0 0.0 - | 0.0 0.0 0.0 1.0 - | - | and not: - | 1.0 0.0 0.0 0.0 - | 0.0 1.0 0.0 0.0 - | 0.0 0.0 1.0 0.0 - | 0.0 0.0 0.0 1.0 - | - '-- Possible bug : sometime, the new curves object's RotY value - jumps to -90.0 degrees without any reason. - ---Options : - SHARP_IMPORT = 0 - choise between "As is", "Devide by height" and "Devide by width" - SHARP_IMPORT = 1 - no choise - - - -All commands are managed: - M : absolute move to - Z : close path - L : absolute line to - C : absolute curve to - S : absolute curve to with only one handle - H : absolute horizontal line to - V : absolute vertical line to - - l : relative line to 2004/08/03 - c : relative curve to 2004/08/03 - s : relative curve to with only one handle - h : relative horizontal line to - v : relative vertical line to - - A : curve_to_a, - V : draw_line_v, - H : draw_line_h, - Z : close_z, - Q : curve_to_q, - T : curve_to_t, - a : curve_to_a, - v : draw_line_v, - h : draw_line_h, - z : close_z, - q : curve_to_q, - - transfrom for <g> tag - transform for <path> tag - -The circle, rectangle closed or open polygons lines are managed too. - -Changelog: - 0.1.1 : - control file without extension - 0.2.0 : - improved reading of several data of the same type - following the same command (for gimp import) - 0.2.1 : - better choice for viewboxing ( takes the viewbox if found, - instead of x,y,width and height - 0.2.2 : - read compact path data from Illustrator 10 - 0.2.3 : - read a few new relative displacements - 0.2.4 : - better hash for command followed by a lone data - (h,v) or uncommun number (a) - 0.2.5 : - correction for gimp import - 0.2.6 : - correction for illustrator 10 SVG - 0.2.7 : - correction for inskape 0.40 cvs SVG - 0.2.8 : - correction for inskape plain SVG - 0.3 : - reading of the transform properties added : - translate - 0.3.1 : - compatibility restored with gimp - 0.3.2 : - transform properties added (june, 15-16): - scale, - rotate, - matrix, - skew - - added a test on __name__ to load the script - outside from the blender menu - 0.3.3 : - matrix transform content control - 0.3.4 : - paths data reading rewritten (19/06/05) - 0.3.5 : - test on empty curve (22/06/05) - - removed overlayed points - 0.3.6 : - rewriting of the bezier point contruction to correct - a problem in the connection between L type point and - C or S type point - 0.3.7 : - code correction for bezier knot in Curveto command when - the command close a path - 0.3.8 : - code was aded to manage quadratic bezier, - Q,q command and T,t commands, as a normal blender's bezier point - - The last modications does not work with gimp 2.0 svg export . - corrected too . - 0.3.9 : - Path's A,a command for ellipse's arc . - 0.4.0 : - To speed up the function filter_DATA was removed and text - variables are changed into numeric variables - 0.4.1 : - svg, groups and shapes hierarchy added - - now transform properties are computed using a stack with all - parented groups - - removed or replaced useless functions : - - skewY, skewX transforms - - radians in rotate transform - 0.4.2 : - Added functon to translate others shapes in path - rect, line, polyline, polygon - 0.4.3 : - various corrections - text font (id property exported by Adobe Illustrator are between coma) - function to code s tag has been rewritten - 0.4.4 : - various corrections - to oblige the script to understand a line feed just after - a tag . Rarely encountered problem, but it exits in a svg file - format exported by a outliner script for mesh . - 0.4.5 : - update for CVS only, at least blender 2.38 and upper - no BezTriple module in older version - added a createCURVES function to avoid to use - the OBJ format export/import . - Perhaps problems with cyclic curves . If a closed curve - does not appear closed in blender, enter edit mode select - all knot with Akey, do a Hkey to set handle type (without - this the knot are recalculated) , and finally use the Ckey - to close the curve . - Should work ... not guaranted . - 0.4.6 : - cyclic flag ... - 0.4.7 : - Management of the svgz files . the complete python or the - gzip.py file is needed . - Little improvement of the curve drawing using the createCURVES - function - 0.4.8 : - short modif for a fantasy font case in the OOo svg format - ('viewbox' is written 'viewBox', for instance) . - Note that (at this time, 2006/05/01, 1OOo exports in svg - but does not read its own export - 0.4.9 : - skipped version : private test - 0.5.0 : - the script worked perfectly with Blender 2.41 but in Blender - 2.42, use the original svg name file + 'OOO.obj' to - write a videoscape file made blender crash under window XP when - the script loaded it . Curiously, use a more simple - name with a sole 'O' solved this problem . - - script returned errors on open path : corrected - - in b2.42, several successive imports seem to be added to - the same original curve . So now the script automaticaly - renames the last group of imported curve with the original - name file . - 0.5.1 : - without join option in the internal curve creation function - 0.5.2 : - the createCURVES() function has been cleanded . Now it works - fine but all bezier curves are joined in the same curve object . - 0.5.3 : - removed two things : - 1/ the ajustement function to increase speed . 35 % faster : - 5690 curves and 30254 points in 11 seconds . User should do - a ctrl-a on the object . - 2/ the import method menu . No reason to choose between the - old extern curve creat and the new intern curve creation - this last one is largely faster . - 0.5.4 : - translation of the functions' name + improvment in the dict lookup . - Quite 15% faster . 9.75 seconds instead of 11 to load the file test . - A test was also added to find the fill style so now the script closes - these curves even if they are not defined as closed in the strict path - commands . - The old non used functions have been completely removed . - 0.5.5 : - Modifs for architect users . - 0.5.6 : - Exec was removed from the collect_ATTRIBUTS function . - Other uses was evaluated. - 0.5.7 : - Wash down of some handle problems. - - 0.5.8 : - 2007/3/9 - Wash down of the last exec and correction of a - problem with the curve's first beztriple handle - which was not recorded at first time . - - Added some units managements - - Correction of the rotate matrix - - Correction of the skew matrix - - change in the wash_DATA function suggested by cambo - - added __slot__ in class Bez, ITEM and CURVE suggested by cambo - - remove unused properties in class ITEM and CURVE - - 0.5.9 : - 2007/3/28 - - many improvements for faster and clearer code suggested by cambo and martin. - replacement of "%s" statement by str function. - - correction of an error in the scale transform management - - correction in the management of the stack transformation that rise an error - under python 2.5 but curiously not with python 2.4 - - 0.5.9a : - 2007/3/29 - - Again a lot of minors corrections - - Backward to 0.5.8 of the function that manages float numbers exported - by the Adobe Illustrator's SVG. After a lot of tests it seems that this oldest - version is also faster too . - - correction (bad) on handle management with V and H commands. - - 0.5.9b : - 2007/3/31 - - one or two minor corrections - - now the new object curve is added in the current layer. - - short modif in the scale menu... - - 0.5.9d : - 2007/4/5 - - when a svg file containts several curves they can be imported in - separate object. - - managment of paths' name when paths are imported as separate curves. - - a menu was added to select between separate or joined curves - - management of colors - - 0.5.9e : - 2007/4/7 - - corrected a scale problem that only appears when one uses beveldepth - - in separate curve option, name is also given to the curve data - - added the list of svg's color names (147) and modified the color's method - to work with. - - 0.5.9h : - 2007/5/2 - - script was updated with the modifs by cambo - - removed all debug statements - - correction of a zero division error in the calc_arc function. - - 0.5.9f: - 2007/15/7 - - Correction de plusieurs bugs sur l'attributions des couleurs et le nommage - des courbes - - 0.5.9i : - ??/??/?? - - Patch externe réalisé sur blender.org project. - - 0.5.9j : - 08/11/2008 - 0.5.9k : - 14/01/2009 - 0.5.9l : - 31/01/2009 - 0.5.9n : - 01/02/2009 - 0.5.9o : - 04/04/2009, remove pattern if it made with path. - - -================================================================================== -==================================================================================""" -SHARP_IMPORT=0 -SCALE=1 -scale_=1 -DEBUG = 0 -DEVELOPPEMENT=0 -TESTCOLOR=0 - -LAST_ID='' -LAST_COLOR=[0.0,0.0,0.0,0.0] -SEPARATE_CURVES=0 -USE_COLORS=0 -PATTERN=0 - -SVGCOLORNAMELIST={ 'aliceblue':[240, 248, 255] ,'antiquewhite':[250, 235, 215] -,'aqua':[ 0, 255, 255], 'aquamarine':[127, 255, 212] -,'azure':[240, 255, 255], 'beige':[245, 245, 220] -,'bisque':[255, 228, 196], 'black':[ 0, 0, 0] -,'blanchedalmond':[255, 235, 205] ,'blue':[ 0, 0, 255] -,'blueviolet':[138, 43, 226],'brown':[165, 42, 42] -,'burlywood':[222, 184, 135],'cadetblue':[ 95, 158, 160] -,'chartreuse':[127, 255, 0] ,'chocolate':[210, 105, 30] -,'coral':[255, 127, 80],'cornflowerblue':[100, 149, 237] -,'cornsilk':[255, 248, 220],'crimson':[220, 20, 60] -,'cyan':[ 0, 255, 255],'darkblue':[ 0, 0, 139] -,'darkcyan':[ 0, 139, 139],'darkgoldenrod':[184, 134, 11] -,'darkgray':[169, 169, 169],'darkgreen':[ 0, 100, 0] -,'darkgrey':[169, 169, 169],'darkkhaki':[189, 183, 107] -,'darkmagenta':[139, 0, 139],'darkolivegreen':[ 85, 107, 47] -,'darkorange':[255, 140, 0],'darkorchid':[153, 50, 204] -,'darkred':[139, 0, 0],'darksalmon':[233, 150, 122] -,'darkseagreen':[143, 188, 143],'darkslateblue':[ 72, 61, 139] -,'darkslategray':[ 47, 79, 79],'darkslategrey':[ 47, 79, 79] -,'darkturquoise':[ 0, 206, 209],'darkviolet':[148, 0, 211] -,'deeppink':[255, 20, 147],'deepskyblue':[ 0, 191, 255] -,'dimgray':[105, 105, 105],'dimgrey':[105, 105, 105] -,'dodgerblue':[ 30, 144, 255],'firebrick':[178, 34, 34] -,'floralwhite':[255, 250, 240],'forestgreen':[ 34, 139, 34] -,'fuchsia':[255, 0, 255],'gainsboro':[220, 220, 220] -,'ghostwhite':[248, 248, 255],'gold':[255, 215, 0] -,'goldenrod':[218, 165, 32],'gray':[128, 128, 128] -,'grey':[128, 128, 128],'green':[ 0, 128, 0] -,'greenyellow':[173, 255, 47],'honeydew':[240, 255, 240] -,'hotpink':[255, 105, 180],'indianred':[205, 92, 92] -,'indigo':[ 75, 0, 130],'ivory':[255, 255, 240] -,'khaki':[240, 230, 140],'lavender':[230, 230, 250] -,'lavenderblush':[255, 240, 245],'lawngreen':[124, 252, 0] -,'lemonchiffon':[255, 250, 205],'lightblue':[173, 216, 230] -,'lightcoral':[240, 128, 128],'lightcyan':[224, 255, 255] -,'lightgoldenrodyellow':[250, 250, 210],'lightgray':[211, 211, 211] -,'lightgreen':[144, 238, 144],'lightgrey':[211, 211, 211] -,'lightpink':[255, 182, 193],'lightsalmon':[255, 160, 122] -,'lightseagreen':[ 32, 178, 170],'lightskyblue':[135, 206, 250] -,'lightslategray':[119, 136, 153],'lightslategrey':[119, 136, 153] -,'lightsteelblue':[176, 196, 222],'lightyellow':[255, 255, 224] -,'lime':[ 0, 255, 0],'limegreen':[ 50, 205, 50] -,'linen':[250, 240, 230],'magenta':[255, 0, 255] -,'maroon':[128, 0, 0],'mediumaquamarine':[102, 205, 170] -,'mediumblue':[ 0, 0, 205],'mediumorchid':[186, 85, 211] -,'mediumpurple':[147, 112, 219],'mediumseagreen':[ 60, 179, 113] -,'mediumslateblue':[123, 104, 238],'mediumspringgreen':[ 0, 250, 154] -,'mediumturquoise':[ 72, 209, 204],'mediumvioletred':[199, 21, 133] -,'midnightblue':[ 25, 25, 112],'mintcream':[245, 255, 250] -,'mistyrose':[255, 228, 225],'moccasin':[255, 228, 181] -,'navajowhite':[255, 222, 173],'navy':[ 0, 0, 128] -,'oldlace':[253, 245, 230],'olive':[128, 128, 0] -,'olivedrab':[107, 142, 35],'orange':[255, 165, 0] -,'orangered':[255, 69, 0],'orchid':[218, 112, 214] -,'palegoldenrod':[238, 232, 170],'palegreen':[152, 251, 152] -,'paleturquoise':[175, 238, 238],'palevioletred':[219, 112, 147] -,'papayawhip':[255, 239, 213],'peachpuff':[255, 218, 185] -,'peru':[205, 133, 63],'pink':[255, 192, 203] -,'plum':[221, 160, 221],'powderblue':[176, 224, 230] -,'purple':[128, 0, 128],'red':[255, 0, 0] -,'rosybrown':[188, 143, 143],'royalblue':[ 65, 105, 225] -,'saddlebrown':[139, 69, 19],'salmon':[250, 128, 114] -,'sandybrown':[244, 164, 96],'seagreen':[ 46, 139, 87] -,'seashell':[255, 245, 238],'sienna':[160, 82, 45] -,'silver':[192, 192, 192],'skyblue':[135, 206, 235] -,'slateblue':[106, 90, 205],'slategray':[112, 128, 144] -,'slategrey':[112, 128, 144],'snow':[255, 250, 250] -,'springgreen':[ 0, 255, 127],'steelblue':[ 70, 130, 180] -,'tan':[210, 180, 140],'teal':[ 0, 128, 128] -,'thistle':[216, 191, 216],'tomato':[255, 99, 71] -,'turquoise':[ 64, 224, 208],'violet':[238, 130, 238] -,'wheat':[245, 222, 179],'white':[255, 255, 255] -,'whitesmoke':[245, 245, 245],'yellow':[255, 255, 0] -,'yellowgreen':[154, 205, 50]} - - -import sys -from math import cos,sin,tan, atan2, pi, ceil -PI=pi -import Blender -from Blender import Mathutils - -try: - import nt - os=nt - os.sep='\\' - -except: - import posix - os=posix - os.sep='/' - -def isdir(path): - try: - st = os.stat(path) - return 1 - except: - return 0 - -def split(pathname): - if os.sep in pathname: - k0=pathname.split(os.sep) - else: - if os.sep=='/': - k0=pathname.split('\\') - else: - k0=pathname.split('/') - directory=pathname.replace(k0[len(k0)-1],'') - Name=k0[len(k0)-1] - return directory, Name - -def join(l0,l1): - return l0+os.sep+l1 - -os.isdir=isdir -os.split=split -os.join=join - -def filterFILE(nom): - """ - Function filterFILE - - in : string nom , filename - out : string t , if correct filecontaint - - read the file's content and try to see if the format - is correct . - - Lit le contenu du fichier et en fait une pre-analyse - pour savoir s'il merite d'etre traite . - """ - # ---------- - # 0.4.7 - # ---------- - if nom.upper().endswith('.SVGZ'): - try : - import gzip - tz=gzip.GzipFile(nom) - t=tz.read() - except: - name = "ERROR: fail to import gzip module or gzip error ... " - result = Blender.Draw.PupMenu(name) - return "false" - else: - f=open(nom,'rU') - t=f.read() - f.close() - # ---------- - # 0.4.7 : end - # ---------- - # ----------------- - # pre-format ... - # ----------------- - # -------------------- - # 0.4.4 '\r','' --> '\r',' ' - # '\n','' --> '\n',' ' - #-------------------- - t=t.replace('\r',' ') - t=t.replace('\n',' ') - t=t.replace('svg:','') - #-------------------- - # may be needed in some import case when the - # file is saved from a mozilla display - #-------------------- - t=t.replace(chr(0),'') - if not '<SVG' in t.upper(): - name = "ERROR: invalid or empty file ... " # if no %xN int is set, indices start from 1 - result = Blender.Draw.PupMenu(name) - return "false" - else: - return t - -#=============================== -# Data -#=============================== -#=============================== -# Blender Curve Data -#=============================== -objBEZIER=0 -objSURFACE=5 -typBEZIER3D=1 #3D -typBEZIER2D=9 #2D - -class Bez(object): - __slots__ = 'co', 'ha', 'tag' # suggested by cambo, should save memory - def __init__(self): - self.co=[] - self.ha=['C','C'] - self.tag='' - -class ITEM(object): - __slots__ = 'type', 'pntsUV', 'flagUV', 'beziers_knot','fill','color','id','mat','matname' - def __init__(self): - self.type = typBEZIER3D - self.pntsUV = [0,0] - self.flagUV = [0,0] - self.beziers_knot = [] - self.fill=0 - self.color=[0.0,0.0,0.0,0.0] - self.id='' - self.mat=0 - self.matname='' - -class CURVE(object): - __slots__ = 'type','number_of_items','ITEM' - def __init__(self): - self.type = objBEZIER - self.number_of_items = 0 - self.ITEM = {} - -curves=CURVE() -PATTERN={} -BOUNDINGBOX={'rec':[],'coef':1.0} - -npat=0 -#===================================================================== -#======== name of the curve in the curves dictionnary =============== -#===================================================================== -n0=0 - -#===================================================================== -#====================== current Point ================================ -#===================================================================== -CP=[0.0,0.0] #currentPoint - - -#===================================================================== -#===== to compare last position to the original move to displacement = -#===== needed for cyclic definition in AI, EPS forma ================ -#===================================================================== -def test_samelocations(f1,f2): - EPSILON=0.0001 - if abs(f1[4])- abs(f2[4])< EPSILON and abs(f1[4])- abs(f2[4])>= 0.0\ - and abs(f1[5])-abs(f2[5])< EPSILON and abs(f1[5])-abs(f2[5])>= 0.0 : - return 1 - else: - return 0 - - -#-------------------- -# 0.4.5 : for blender cvs 2.38 .... -#-------------------- -def createCURVES(curves, name): - """ - internal curves creation - """ - global SCALE, B, BOUNDINGBOX,scale_, SEPARATE_CURVES - global USE_COLORS - from Blender import Curve, Object, Scene, BezTriple - HANDLE={'C':BezTriple.HandleTypes.FREE,'L':BezTriple.HandleTypes.VECT} - r=BOUNDINGBOX['rec'] - - if scale_==3: - SCALE=1.0 - elif scale_==1: - SCALE=r[2]-r[0] - elif scale_==2: - SCALE=r[3]-r[1] - - scene = Scene.GetCurrent() - scene.objects.selected = [] - - if not SEPARATE_CURVES: - c = Curve.New() - c.setResolu(24) - - MATNAME=[] - nloc=0.0 - - def new_MATERIAL(val): - # ----------------------- - # have to create a material - #------------------------ - if val.matname and val.matname in MATNAME: - mat = Blender.Material.Get(val.matname) - elif val.matname: - mat = Blender.Material.New(val.matname) - mat.rgbCol = [val.color[0]/255.0, val.color[1]/255.0, val.color[2]/255.0] - else: - mat = Blender.Material.New(val.id) - mat.rgbCol = [val.color[0]/255.0, val.color[1]/255.0, val.color[2]/255.0] - return [mat] - - for I,val in curves.ITEM.iteritems(): - if SEPARATE_CURVES: - c = Curve.New() - c.setResolu(24) - if USE_COLORS and val.mat: - c.materials=new_MATERIAL(val) - - bzn=0 - if val.beziers_knot[-1].tag in ['L','l','V','v','H','h'] and\ - test_samelocations(val.beziers_knot[-1].co,val.beziers_knot[0].co): - del val.beziers_knot[-1] - - for k2 in xrange(0,len(val.beziers_knot)): - bz= [co for co in val.beziers_knot[k2].co] - if bzn==0: - cp1 = bz[4]/SCALE, bz[5]/-SCALE,0.0, bz[0]/SCALE, bz[1]/-SCALE,0.0, bz[2]/SCALE,bz[3]/-SCALE,0.0, - beztriple1 = BezTriple.New(cp1) - bez = c.appendNurb(beztriple1) - bez[0].handleTypes=(HANDLE[val.beziers_knot[k2].ha[0]],HANDLE[val.beziers_knot[k2].ha[1]]) - bzn = 1 - else: - cp2 = bz[4]/SCALE,bz[5]/-SCALE,0.0 , bz[0]/SCALE, bz[1]/-SCALE,0.0, bz[2]/SCALE,bz[3]/-SCALE,0.0 - beztriple2 = BezTriple.New(cp2) - beztriple2.handleTypes= (HANDLE[val.beziers_knot[k2].ha[0]],HANDLE[val.beziers_knot[k2].ha[1]]) - bez.append(beztriple2) - - if val.flagUV[0]==1 or val.fill==1: - #-------------------- - # 0.4.6 : cyclic flag ... - #-------------------- - bez.flagU += 1 - - if SEPARATE_CURVES: - ob = scene.objects.new(c,val.id) - scene.objects.active = ob - ob.setLocation(0.0,0.0,nloc) - nloc+=0.0001 - c.update() - - if not SEPARATE_CURVES: - ob = scene.objects.new(c,name) - scene.objects.active = ob - c.update() - -#===================================================================== -#===== SVG format : DEBUT ========================= -#===================================================================== -#-------------------- -# 0.5.8, needed with the new -# tranform evaluation -#-------------------- -pxUNIT={'pt':1.25, - 'pc':15.0, - 'mm':3.543307, - 'cm':35.43307, - 'in':90.0, - 'em':1.0, # should be taken from font size - # but not currently managed - 'ex':1.0, # should be taken from font size - # but not currently managed - '%':1.0, - } - -#-------------------- -# 0.4.2 -# 0.5.8, to remove exec -#-------------------- -def rect(prp): - """ - build rectangle paths - """ - D=[] - if 'x' not in prp: x=0.0 - else : x=float(prp['x']) - if 'y' not in prp: y=0.0 - else : y=float(prp['y']) - #-------------------- - # 0.5.8 - #-------------------- - try: - height=float(prp['height']) - except: - pxUNIT['%']=(BOUNDINGBOX['rec'][3]-BOUNDINGBOX['rec'][1])/100.0 - for key in pxUNIT:#.keys(): - if key in prp['height']: - height=float(prp['height'].replace(key,''))*pxUNIT[key] - try: - width=float(prp['width']) - except: - pxUNIT['%']=(BOUNDINGBOX['rec'][2]-BOUNDINGBOX['rec'][0])/100.0 - for key in pxUNIT:#.keys(): - if key in prp['width']: - width=float(prp['width'].replace(key,''))*pxUNIT[key] - #-------------------- - # 0.5.8, end - #-------------------- - """ - normal rect - x,y - h1 - *----------* - | | - | | - | | - *----------* v1 - h2 - """ - if 'rx' not in prp or 'rx' not in prp: - D=['M',str(x),str(y),'h',str(width),'v',str(height),'h',str(-width),'z'] - else : - rx=float(prp['rx']) - if 'ry' not in prp : - ry=float(prp['rx']) - else : ry=float(prp['ry']) - if 'rx' in prp and prp['rx']<0.0: rx*=-1 - if 'ry' in prp and prp['ry']<0.0: ry*=-1 - """ - rounded corner - - x,y M h1 - ---*----------* - / \ - / \ - v2 * * c1 - | | - | | - | | - c3 * * v2 - \ / - \ / - *----------* - h2 c2 - """ - - D=['M',str(x+rx),str(y), - 'h',str(width-2*rx), - 'c',str(rx),'0.0',str(rx),str(ry),str(rx),str(ry), - 'v',str(height-ry), - 'c','0.0',str(ry),str(-rx),str(ry),str(-rx),str(ry), - 'h',str(-width+2*rx), - 'c',str(-rx),'0.0',str(-rx),str(-ry),str(-rx),str(-ry), - 'v',str(-height+ry), - 'c','0.0','0.0','0.0',str(-ry),str(rx),str(-ry), - 'z'] - - return D - -#-------------------- -# 0.4.2 -# 0.5.8, to remove exec -#-------------------- -def circle(prp): - if 'cx' not in prp: cx=0.0 - else : cx =float(prp['cx']) - if 'cy' not in prp: cy=0.0 - else : cy =float(prp['cy']) - r = float(prp['r']) - D=['M',str(cx),str(cy+r), - 'C',str(cx-r), str(cy+r*0.552),str(cx-0.552*r),str(cy+r), str(cx),str(cy+r), - 'C',str(cx+r*0.552), str(cy+r), str(cx+r), str(cy+r*0.552), str(cx+r),str(cy), - 'C',str(cx+r), str(cy-r*0.552),str(cx+r*0.552),str(cy-r),str(cx), str(cy-r), - 'C',str(cx-r*0.552), str(cy-r), str(cx-r), str(cy-r*0.552),str(cx-r),str(cy), - 'Z'] - return D - -#-------------------- -# 0.4.2 -# 0.5.8, to remove exec -#-------------------- -def ellipse(prp): - if 'cx' not in prp: cx=0.0 - else : cx =float(prp['cx']) - if 'cy' not in prp: cy=0.0 - else : cy =float(prp['cy']) - ry = float(prp['rx']) - rx = float(prp['ry']) - D=['M',str(cx),str(cy+rx), - 'C',str(cx-ry),str(cy+rx*0.552),str(cx-0.552*ry),str(cy+rx),str(cx),str(cy+rx), - 'C',str(cx+ry*0.552),str(cy+rx),str(cx+ry),str(cy+rx*0.552),str(cx+ry),str(cy), - 'C',str(cx+ry),str(cy-rx*0.552),str(cx+ry*0.552),str(cy-rx),str(cx),str(cy-rx), - 'C',str(cx-ry*0.552),str(cy-rx),str(cx-ry),str(cy-rx*0.552),str(cx-ry),str(cy), - 'z'] - return D - -#-------------------- -# 0.4.2 -# 0.5.8, to remove exec -#-------------------- -def line(prp): - D=['M',str(prp['x1']),str(prp['y1']), - 'L',str(prp['x2']),str(prp['y2'])] - return D - -#-------------------- -# 0.4.2 -# 0.5.8, to remove exec -#-------------------- -def polyline(prp): - if 'points' in prp: - points=prp['points'].split(' ') - np=0 - for p in points: - if p!='': - p=p.split(',') - if np==0: - D=['M',str(p[0]),str(p[1])] - np+=1 - else: - D.append('L'); D.append(str(p[0])); D.append(str(p[1])) - return D - else: - return [] - -#-------------------- -# 0.4.2 -# 0.5.8, to remove exec -#-------------------- -def polygon(prp): - D=polyline(prp) - if D!=[]: - D.append('Z') - return D - - -#-------------------- -# 0.5.8, to remove exec -#-------------------- -OTHERSSHAPES={ 'rect' : rect, - 'line' : line, - 'polyline': polyline, - 'polygon' : polygon, - 'circle' : circle, - 'ellipse' : ellipse} - -#-------------------- -# 0.3.9 -#-------------------- -def calc_arc (cpx,cpy, rx, ry, ang, fa , fs , x, y) : - """ - Calc arc paths - """ - rx=abs(rx) - ry=abs(ry) - px=abs((cos(ang)*(cpx-x)+sin(ang)*(cpy-y))*0.5)**2.0 - py=abs((cos(ang)*(cpy-y)-sin(ang)*(cpx-x))*0.5)**2.0 - rpx=rpy=0.0 - if abs(rx)>0.0: rpx=px/(rx**2.0) - if abs(ry)>0.0: rpy=py/(ry**2.0) - pl=rpx+rpy - if pl>1.0: - pl=pl**0.5;rx*=pl;ry*=pl - carx=sarx=cary=sary=0.0 - if abs(rx)>0.0: - carx=cos(ang)/rx;sarx=sin(ang)/rx - if abs(ry)>0.0: - cary=cos(ang)/ry;sary=sin(ang)/ry - x0=(carx)*cpx+(sarx)*cpy - y0=(-sary)*cpx+(cary)*cpy - x1=(carx)*x+(sarx)*y - y1=(-sary)*x+(cary)*y - d=(x1-x0)*(x1-x0)+(y1-y0)*(y1-y0) - if abs(d)>0.0 :sq=1.0/d-0.25 - else: sq=-0.25 - if sq<0.0 :sq=0.0 - sf=sq**0.5 - if fs==fa :sf=-sf - xc=0.5*(x0+x1)-sf*(y1-y0) - yc=0.5*(y0+y1)+sf*(x1-x0) - ang_0=atan2(y0-yc,x0-xc) - ang_1=atan2(y1-yc,x1-xc) - ang_arc=ang_1-ang_0; - if (ang_arc < 0.0 and fs==1) : - ang_arc += 2.0 * PI - elif (ang_arc>0.0 and fs==0) : - ang_arc-=2.0*PI - n_segs=int(ceil(abs(ang_arc*2.0/(PI*0.5+0.001)))) - P=[] - for i in xrange(n_segs): - ang0=ang_0+i*ang_arc/n_segs - ang1=ang_0+(i+1)*ang_arc/n_segs - ang_demi=0.25*(ang1-ang0) - t=2.66666*sin(ang_demi)*sin(ang_demi)/sin(ang_demi*2.0) - x1=xc+cos(ang0)-t*sin(ang0) - y1=yc+sin(ang0)+t*cos(ang0) - x2=xc+cos(ang1) - y2=yc+sin(ang1) - x3=x2+t*sin(ang1) - y3=y2-t*cos(ang1) - P.append([[(cos(ang)*rx)*x1+(-sin(ang)*ry)*y1, - (sin(ang)*rx)*x1+(cos(ang)*ry)*y1], - [(cos(ang)*rx)*x3+(-sin(ang)*ry)*y3, - (sin(ang)*rx)*x3+(cos(ang)*ry)*y3], - [(cos(ang)*rx)*x2+(-sin(ang)*ry)*y2, - (sin(ang)*rx)*x2+(cos(ang)*ry)*y2]]) - return P - -#-------------------- -# 0.3.9 -#-------------------- -def curve_to_a(curves, c,D,n0,CP): #A,a - global SCALE - l=[float(D[c[1]+1]),float(D[c[1]+2]),float(D[c[1]+3]), - int(D[c[1]+4]),int(D[c[1]+5]),float(D[c[1]+6]),float(D[c[1]+7])] - if c[0]=='a': - l[5]=l[5] + CP[0] - l[6]=l[6] + CP[1] - B=Bez() - B.co=[ CP[0], CP[1], CP[0], CP[1], CP[0], CP[1] ] - B.ha=['C','C'] - B.tag=c[0] - POINTS= calc_arc (CP[0],CP[1], - l[0], l[1], l[2]*(PI / 180.0), - l[3], l[4], - l[5], l[6] ) - for p in POINTS : - B=Bez() - B.co=[ p[2][0],p[2][1], p[0][0],p[0][1], p[1][0],p[1][1]] - B.ha=['C','C'] - B.tag='C' - BP=curves.ITEM[n0].beziers_knot[-1] - BP.co[2]=B.co[2] - BP.co[3]=B.co[3] - curves.ITEM[n0].beziers_knot.append(B) - BP=curves.ITEM[n0].beziers_knot[-1] - BP.co[2]=BP.co[0] - BP.co[3]=BP.co[1] - CP=[l[5], l[6]] - #---------- 059m------------ - if len(D)>c[1]+7 and D[c[1]+8] not in TAGcourbe : - c[1]+=7 - curves,n0,CP=curve_to_a(curves, c, D, n0,CP) - #---------- 059m------------ - return curves,n0,CP - -def move_to(curves, c, D, n0,CP, proprietes): - global DEBUG,TAGcourbe, LAST_ID - global USE_COLORS - - l=[float(D[c[1]+1]),float(D[c[1]+2])] - - if c[0]=='m': - l=[l[0]+CP[0], - l[1] + CP[1]] - - if n0 in curves.ITEM: - n0+=1 - CP=[l[0],l[1]] - curves.ITEM[n0]=ITEM() - - if 'id' in proprietes: - curves.ITEM[n0].id=proprietes['id'] - else: - curves.ITEM[n0].id=LAST_ID - - proprietes['n'].append(n0) - if USE_COLORS: - pr= proprietes.get('fill') # None or the property - if pr != None: - if '#' in pr: - i=1 - curves.ITEM[n0].color=[int(pr[i:i+2],16),int(pr[i+2:i+4],16),int(pr[i+4:i+6],16)] - curves.ITEM[n0].mat=1 - elif pr in SVGCOLORNAMELIST: - Courbe[n].color=SVGCOLORNAMELIST[pr] - Courbe[n].mat=1 - - B=Bez() - B.co=[CP[0],CP[1],CP[0],CP[1],CP[0],CP[1]] - B.ha=['L','C'] - B.tag=c[0] - curves.ITEM[n0].beziers_knot.append(B) - return curves,n0,CP - -def close_z(curves, c,D,n0,CP): #Z,z - curves.ITEM[n0].flagUV[0]=1 - if len(curves.ITEM[n0].beziers_knot)>1: - BP=curves.ITEM[n0].beziers_knot[-1] - BP0=curves.ITEM[n0].beziers_knot[0] - if BP.tag in ['c','C','s','S',]: - BP.co[2]=BP0.co[2] #4-5 point prec - BP.co[3]=BP0.co[3] - del curves.ITEM[n0].beziers_knot[0] - else: - del curves.ITEM[n0] - n0-=1 - return curves,n0,CP - -def curve_to_q(curves, c,D,n0,CP): #Q,q - l=[float(D[c[1]+1]),float(D[c[1]+2]),float(D[c[1]+3]),float(D[c[1]+4])] - if c[0]=='q': - l=[l[0]+CP[0], l[1]+CP[1], l[2]+CP[0], l[3]+CP[1]] - B=Bez() - B.co=[l[2], l[3], l[2], l[3], l[0], l[1]] #plus toucher au 2-3 - B.ha=['C','C'] - B.tag=c[0] - BP=curves.ITEM[n0].beziers_knot[-1] - BP.co[2]=BP.co[0] - BP.co[3]=BP.co[1] - curves.ITEM[n0].beziers_knot.append(B) - CP=[l[2],l[3]] - #if DEBUG==1: pass - if len(D)>c[1]+5 and D[c[1]+5] not in TAGcourbe : - c[1]+=4 - curves,n0,CP=curve_to_q(curves, c, D, n0,CP) - return curves,n0,CP - -def curve_to_t(curves, c,D,n0,CP): #T,t - l=[float(D[c[1]+1]),float(D[c[1]+2])] - if c[0]=='t': - l=[l[0]+CP[0], l[1]+CP[1]] - B=Bez() - B.co=[l[0], l[1], l[0], l[1], l[0], l[1]] #plus toucher au 2-3 - B.ha=['C','C'] - B.tag=c[0] - BP=curves.ITEM[n0].beziers_knot[-1] - l0=build_SYMETRIC([BP.co[0],BP.co[1],BP.co[4],BP.co[5]]) - if BP.tag in ['q','Q','t','T','m','M']: - BP.co[2]=l0[2] - BP.co[3]=l0[3] - curves.ITEM[n0].beziers_knot.append(B) - CP=[l[0],l[1]] - if len(D)>c[1]+3 and D[c[1]+3] not in TAGcourbe : - c[1]+=4 - curves,n0,CP=curve_to_t(curves, c, D, n0,CP) - return curves,n0,CP - -#-------------------- -# 0.4.3 : rewritten -#-------------------- -def build_SYMETRIC(l): - X=l[2]-(l[0]-l[2]) - Y=l[3]-(l[1]-l[3]) - return X,Y - -def curve_to_s(curves, c,D,n0,CP): #S,s - l=[float(D[c[1]+1]), - float(D[c[1]+2]), - float(D[c[1]+3]), - float(D[c[1]+4])] - if c[0]=='s': - l=[l[0]+CP[0], l[1]+CP[1], - l[2]+CP[0], l[3]+CP[1]] - B=Bez() - B.co=[l[2],l[3],l[2],l[3],l[0],l[1]] #plus toucher au 2-3 - B.ha=['C','C'] - B.tag=c[0] - BP=curves.ITEM[n0].beziers_knot[-1] - #-------------------- - # 0.4.3 - #-------------------- - BP.co[2],BP.co[3]=build_SYMETRIC([BP.co[4],BP.co[5],BP.co[0],BP.co[1]]) - curves.ITEM[n0].beziers_knot.append(B) - #-------------------- - # 0.4.3 - #-------------------- - CP=[l[2],l[3]] - if len(D)>c[1]+5 and D[c[1]+5] not in TAGcourbe : - c[1]+=4 - curves,n0,CP=curve_to_c(curves, c, D, n0,CP) - return curves,n0,CP - -def curve_to_c(curves, c, D, n0,CP): #c,C - l=[float(D[c[1]+1]),float(D[c[1]+2]),float(D[c[1]+3]), - float(D[c[1]+4]),float(D[c[1]+5]),float(D[c[1]+6])] - if c[0]=='c': - l=[l[0]+CP[0], - l[1]+CP[1], - l[2]+CP[0], - l[3]+CP[1], - l[4]+CP[0], - l[5]+CP[1]] - B=Bez() - B.co=[l[4], - l[5], - l[4], - l[5], - l[2], - l[3]] #plus toucher au 2-3 - - - B.ha=['C','C'] - B.tag=c[0] - BP=curves.ITEM[n0].beziers_knot[-1] - BP.co[2]=l[0] - BP.co[3]=l[1] - BP.ha[1]='C' - curves.ITEM[n0].beziers_knot.append(B) - CP=[l[4],l[5]] - if len(D)>c[1]+7 and D[c[1]+7] not in TAGcourbe : - c[1]+=6 - curves,n0,CP=curve_to_c(curves, c, D, n0,CP) - return curves,n0,CP - -def draw_line_l(curves, c, D, n0,CP): #L,l - - l=[float(D[c[1]+1]),float(D[c[1]+2])] - if c[0]=='l': - l=[l[0]+CP[0], - l[1]+CP[1]] - B=Bez() - B.co=[l[0],l[1], - l[0],l[1], - l[0],l[1]] - - B.ha=['L','L'] - B.tag=c[0] - BP=curves.ITEM[n0].beziers_knot[-1] - BP.ha[1]='L' - - curves.ITEM[n0].beziers_knot.append(B) - CP=[B.co[4],B.co[5]] - - if len(D)>c[1]+3 and D[c[1]+3] not in TAGcourbe : - c[1]+=2 - curves,n0,CP=draw_line_l(curves, c, D, n0,CP) #L - - return curves,n0,CP - -def draw_line_h(curves, c,D,n0,CP): #H,h - if c[0]=='h': - l=[float(D[c[1]+1])+float(CP[0]),CP[1]] - else: - l=[float(D[c[1]+1]),CP[1]] - B=Bez() - B.co=[l[0],l[1],l[0],l[1],l[0],l[1]] - B.ha=['L','L'] - B.tag=c[0] - #BP=curves.ITEM[n0].beziers_knot[-1] - #BP.ha[0]='L' - curves.ITEM[n0].beziers_knot.append(B) - CP=[l[0],l[1]] - return curves,n0,CP - -def draw_line_v(curves, c,D,n0,CP): #V, v - if c[0]=='v': - l=[CP[0], float(D[c[1]+1])+CP[1]] - else: - l=[CP[0], float(D[c[1]+1])] - - B=Bez() - B.co=[l[0],l[1],l[0],l[1],l[0],l[1]] - B.ha=['L','L'] - B.tag=c[0] - #BP=curves.ITEM[n0].beziers_knot[-1] - #BP.ha[0]='L' - curves.ITEM[n0].beziers_knot.append(B) - CP=[l[0],l[1]] - return curves,n0,CP - -Actions= { "C" : curve_to_c, - "A" : curve_to_a, - "S" : curve_to_s, - "M" : move_to, - "V" : draw_line_v, - "L" : draw_line_l, - "H" : draw_line_h, - "Z" : close_z, - "Q" : curve_to_q, - "T" : curve_to_t, - - "c" : curve_to_c, - "a" : curve_to_a, - "s" : curve_to_s, - "m" : move_to, - "v" : draw_line_v, - "l" : draw_line_l, - "h" : draw_line_h, - "z" : close_z, - "q" : curve_to_q, - "T" : curve_to_t -} - -TAGcourbe=Actions.keys() -TAGtransform=['M','L','C','S','H','V','T','Q'] -tagTRANSFORM=0 - -def wash_DATA(ndata): - if ndata: - ndata = ndata.strip() - - if ndata[0]==',':ndata=ndata[1:] - if ndata[-1]==',':ndata=ndata[:-1] - - #-------------------- - # 0.4.0 : 'e' - #-------------------- - ni=0 - i = ndata.find('-',ni) - if i != -1: - while i>-1 : - i = ndata.find('-',ni) - # 059l ------ - if i>0 : - if ndata[i-1] not in [' ',',','e']: - ndata=ndata[:i]+','+ndata[i:] - ni=i+2 - else: - ni=i+1 - elif i>-1: - ni=1 - # 059l ------ - - ndata=ndata.replace(',,',',') - ndata=ndata.replace(' ',',') - ndata=ndata.split(',') - ndata=[i for i in ndata if i] #059a - - return ndata - -#-------------------- -# 0.3.4 : - read data rewrittten -#-------------------- -def list_DATA(DATA): - """ - This function translate a text in a list of - correct commandswith the right number of waited - values for each of them . For example : - d="'M0,14.0 z" becomes ['M','0.0','14.0','z'] - """ - # ---------------------------------------- - # borner les differents segments qui devront etre - # traites - # pour cela construire une liste avec chaque - # position de chaque emplacement tag de type - # commande path... - # ---------------------------------------- - tagplace=[] - for d in Actions: - b1=0 - while True: - i = DATA.find(d,b1) - if i==-1: break - tagplace.append(i) - b1=i+1 - #------------------------------------------ - # cette liste doit etre traites dans l'ordre - # d'apparition des tags - #------------------------------------------ - tagplace.sort() - - tpn=range(len(tagplace)) - - - #-------------------- - # 0.3.5 :: short data, only one tag - #-------------------- - if len(tagplace)-1>0: - DATA2=[] - for t in tpn[:-1]: - DATA2.append(DATA[tagplace[t]:tagplace[t]+1]) - ndata=DATA[tagplace[t]+1:tagplace[t+1]] - - if DATA2[-1] not in ['z','Z'] : - ndata=wash_DATA(ndata) - DATA2.extend(ndata) - - DATA2.append(DATA[tagplace[t+1]:tagplace[t+1]+1]) - - if DATA2[-1] not in ['z','Z'] and len(DATA)-1>=tagplace[t+1]+1: - ndata=DATA[tagplace[t+1]+1:] - ndata=wash_DATA(ndata) - DATA2.extend(ndata) #059a - - else: - #-------------------- - # 0.3.5 : short data,only one tag - #-------------------- - DATA2=[] - DATA2.append(DATA[tagplace[0]:tagplace[0]+1]) - ndata=DATA[tagplace[0]+1:] - ndata=wash_DATA(ndata) - DATA2.extend(ndata) - return DATA2 - -#---------------------------------------------- -# 0.3 -# 0.5.8, to remove exec -#---------------------------------------------- -def translate(t): - tx=t[0] - ty=t[1] - return [1, 0, tx], [0, 1, ty],[0,0,1] - -#---------------------------------------------- -# 0.3.2 -# 0.5.8, to remove exec -#---------------------------------------------- -def scale(s): - sx=s[0] - if len(s)>1: sy=s[1] - else: sy=sx - return [sx, 0, 0], [0, sy, 0],[0,0,1] - -#---------------------------------------------- -# 0.4.1 : transslate a in radians -# 0.5.8, to remove exec -#---------------------------------------------- -def rotate(t): - a=t[0] - return [cos(a*3.1416/180.0), -sin(a*3.1416/180.0), 0], [sin(a*3.1416/180.0), cos(a*3.1416/180.0),0],[0,0,1] - -#---------------------------------------------- -# 0.3.2 -# 0.5.8, to remove exec -#---------------------------------------------- -def skewx(t): - a=t[0] - return [1, tan(a*3.1416/180.0), 0], [0, 1, 0],[0,0,1] - -#---------------------------------------------- -# 0.4.1 -# 0.5.8, to remove exec -#---------------------------------------------- -def skewy(t): - a=t[0] - return [1, 0, 0], [tan(a*3.1416/180.0), 1 , 0],[0,0,1] - -#---------------------------------------------- -# 0.3.2 -# 0.5.8, to remove exec -#---------------------------------------------- -def matrix(t): - a,b,c,d,e,f=t - return [a,c,e],[b,d,f],[0,0,1] - -#-------------------- -# 0.5.8, to remove exec -#-------------------- -matrixTRANSFORM={ 'translate':translate, - 'scale':scale, - 'rotate':rotate, - 'skewx':skewx, - 'skewy':skewy, - 'matrix':matrix - } - -#---------------------------------------------- -# 0.4.2 : rewritten -# 0.5.8 : to remove exec uses. -#---------------------------------------------- -def control_CONTAINT(txt): - """ - the transforms' descriptions can be sole or several - and separators might be forgotten - """ - t0=0 - tlist=[] - while txt.count(')',t0)>0: - t1=txt.find(')',t0) - nt0=txt[t0:t1+1] - t2=nt0[nt0.find('(')+1:-1] - val=nt0[:nt0.find('(')] - - while t2.find(' ')!=-1: - t2=t2.replace(' ',' ') - while t2.find(', ')!=-1: #059l - t2=t2.replace(', ',',') #059l - - t2=t2.replace(' ',',') - t2=[float(t) for t in t2.split(',')] - - if val=='rotate' : - t3=t2 - if len(t3)==3: - tlist.append(['translate',[t3[1],t3[2]]]) - tlist.append(['rotate',[t3[0]/180.0*3.1416]]) - tlist.append(['translate',[-t3[1],-t3[2]]]) - else: - tlist.append(['rotate',[t3[0]]]) - else: - tlist.append([val,t2]) - t0=t1+1 - return tlist - - -def curve_FILL(Courbe,proprietes): - global USE_COLORS - for n in proprietes['n']: - pr = proprietes['style'] - if n in Courbe and 'fill:' in pr: - if not 'fill:none' in pr: - Courbe[n].fill=1 - if USE_COLORS: - i= pr.find('fill:#') - if i != -1: - i= i+6 - Courbe[n].color=[int(pr[i:i+2],16),int(pr[i+2:i+4],16),int(pr[i+4:i+6],16)] - Courbe[n].mat=1 - elif ';fill-opacity' in pr: - if pr.find('fill:url')==-1: - i= pr.find('fill:')+5 - i2= pr.find(';',i) - COLORNAME= pr[i:i2] - Courbe[n].color=SVGCOLORNAMELIST[COLORNAME] - Courbe[n].mat=1 - elif 'color:' in pr: - i= pr.find('color:')+6 - i2= pr.find(';',i) - COLORNAME= pr[i:i2] - Courbe[n].color=SVGCOLORNAMELIST[COLORNAME] - Courbe[n].mat=1 - else : - COLORNAME= 'white' - Courbe[n].color=SVGCOLORNAMELIST[COLORNAME] - Courbe[n].mat=1 - -#---------------------------------------------- -# 0.4.1 : apply transform stack -#---------------------------------------------- -def curve_TRANSFORM(Courbe,proprietes): - # 1/ unpack the STACK - # create a matrix for each transform - ST=[] - for st in proprietes['stack'] : - if st and type(st)==list: - for t in st: - code = control_CONTAINT(t) - a,b,c=matrixTRANSFORM[code[0][0]](code[0][1][:]) - T=Mathutils.Matrix(a,b,c) - ST.append(T) - elif st : - code = control_CONTAINT(st) - a,b,c=matrixTRANSFORM[code[0][0]](code[0][1][:]) - T=Mathutils.Matrix(a,b,c) - ST.append(T) - if 'transform' in proprietes: - for trans in control_CONTAINT(proprietes['transform']): - #-------------------- - # 0.5.8, to remove exec - #-------------------- - a,b,c=matrixTRANSFORM[trans[0].strip()](trans[1][:]) #059 - T=Mathutils.Matrix(a,b,c) - ST.append(T) - ST.reverse() - for n in proprietes['n']: - if n in Courbe: - for bez0 in Courbe[n].beziers_knot: - bez=bez0.co - for b in [0,2,4]: - for t in ST: - v=t * Mathutils.Vector([bez[b],bez[b+1],1.0]) #059a - bez[b]=v[0] - bez[b+1]=v[1] - -def filter(d): - for nn in d: - if nn not in '0123456789.': #059a - d=d.replace(nn,"") - return d - -def get_BOUNDBOX(BOUNDINGBOX,SVG): - if 'viewbox' not in SVG: - h=float(filter(SVG['height'])) - - w=float(filter(SVG['width'])) - BOUNDINGBOX['rec']=[0.0,0.0,w,h] - r=BOUNDINGBOX['rec'] - BOUNDINGBOX['coef']=w/h - else: - viewbox=SVG['viewbox'].split() - BOUNDINGBOX['rec']=[float(viewbox[0]),float(viewbox[1]),float(viewbox[2]),float(viewbox[3])] - r=BOUNDINGBOX['rec'] - BOUNDINGBOX['coef']=(r[2]-r[0])/(r[3]-r[1]) - return BOUNDINGBOX - -#---------------------------------------------- -# 0.4.1 : attributs ex : 'id=', 'transform=', 'd=' ... -#---------------------------------------------- -def collect_ATTRIBUTS(data): - #---------------------------------------------- - # 0.4.8 : short modif for a fantasy font case - # in the OOo svg format ('viewbox' is - # written 'viewBox', for instance) - #---------------------------------------------- - data=data.replace(' ',' ').lower() - ELEM={'TYPE':data[1:data.find(' ')]} - t1=len(data) - t2=0 - ct=data.count('="') - while ct>0: - t0=data.find('="',t2) - t2=data.find(' ',t2)+1 - id=data[t2:t0] - t2=data.find('"',t0+2) - if id!='d': - ELEM[id]=data[t0+2:t2].replace('\\','/') - else: - ELEM[id]=[] - ELEM[id].append(t0+2) - ELEM[id].append(t2) - ct=data.count('="',t2) - return ELEM - -# -------------------------------------------- -# 0.4.1 : to avoid to use sax and ths xml -# tools of the complete python -# -------------------------------------------- -def build_HIERARCHY(t): - global CP, curves, SCALE, DEBUG, BOUNDINGBOX, scale_, tagTRANSFORM - global LAST_ID, PATTERN - TRANSFORM=0 - t=t.replace('\t',' ') - while t.find(' ')!=-1: t=t.replace(' ',' ') - n0=0 - t0=t1=0 - #baliste=[] - balisetype=['?','?','/','/','!','!'] - BALISES=['D', #DECL_TEXTE', - 'D', #DECL_TEXTE', - 'F', #FERMANTE', - 'E', #ELEM_VIDE', - 'd', #DOC', - 'R', #REMARQUES', - 'C', #CONTENU', - 'O' #OUVRANTE' - ] - STACK=[] - while t1<len(t) and t0>-1: - t0=t.find('<',t0) - t1=t.find('>',t0) - ouvrante=0 - #-------------------- - # 0.4.4 , add 'else:' and 'break' to the 'if' statement - #-------------------- - if t0>-1 and t1>-1: - if t[t0+1] in balisetype: - b=balisetype.index(t[t0+1]) - - if t[t0+2]=='-': - b=balisetype.index(t[t0+1])+1 - - balise=BALISES[b] - - if b==2: - parent=STACK.pop(-1) - if parent!=None and TRANSFORM>0: - TRANSFORM-=1 - - elif t[t1-1] in balisetype: - balise=BALISES[balisetype.index(t[t1-1])+1] - - else: - t2=t.find(' ',t0) - if t2>t1: t2=t1 - ouvrante=1 - NOM=t[t0+1:t2] - - - if '</'+NOM in t: #.find('</'+NOM)>-1: - balise=BALISES[-1] - if NOM=='pattern' and not PATTERN: - t1=t.find('</'+NOM+'>',t0)+len('</'+NOM+'>') - balise=BALISES[-3] - else: - balise=BALISES[-2] - - if balise=='E' or balise=='O': - - proprietes=collect_ATTRIBUTS(t[t0:t1+ouvrante]) - - if 'id' in proprietes: - LAST_ID=proprietes['id'] - - if balise=='O' and 'transform' in proprietes: - STACK.append(proprietes['transform']) - TRANSFORM+=1 - elif balise=='O' : - STACK.append(None) - - proprietes['stack']=STACK[:] - D=[] - - if proprietes['TYPE'] in ['path'] and (proprietes['d'][1]-proprietes['d'][0]>1): - D=list_DATA(t[proprietes['d'][0]+t0:proprietes['d'][1]+t0]) - - elif proprietes['TYPE'] in OTHERSSHAPES: - #-------------------- - # 0.5.8, to remove exec - #-------------------- - D=OTHERSSHAPES[proprietes['TYPE']](proprietes) - - #elif proprietes['TYPE'] in ['pattern']: - # print 'pattern' - # D='' - - CP=[0.0,0.0] - if len(D)>0: - cursor=0 - proprietes['n']=[] - for cell in D: - - if len(cell)>=1 and cell[0] in TAGcourbe: - #-------------------- - # 0.5.8, to remove exec - #-------------------- - if cell[0] in ['m','M']: - curves,n0,CP=Actions[cell](curves, [cell,cursor], D, n0,CP,proprietes) - else: - curves,n0,CP=Actions[cell](curves, [cell,cursor], D, n0,CP) - - cursor+=1 - if TRANSFORM>0 or 'transform' in proprietes : - curve_TRANSFORM(curves.ITEM,proprietes) - - if 'style' in proprietes : - curve_FILL(curves.ITEM,proprietes) - - - elif proprietes['TYPE'] == 'svg': - BOUNDINGBOX = get_BOUNDBOX(BOUNDINGBOX,proprietes) - else: - #-------------------- - # 0.4.4 - #-------------------- - break - t1+=1 - t0=t1 - -def scan_FILE(nom): - global CP, curves, SCALE, DEBUG, BOUNDINGBOX, scale_, tagTRANSFORM - global SEPARATE_CURVES, USE_COLORS, PATTERN - - dir,name=split(nom) - name=name.split('.') - result=0 - #Choise=1 - t1=Blender.sys.time() - t=filterFILE(nom) - if t!='false': - Blender.Window.EditMode(0) - if not SHARP_IMPORT: - togH = Blender.Draw.Create(1) - togW = Blender.Draw.Create(0) - togAS = Blender.Draw.Create(0) - togSP = Blender.Draw.Create(0) - togCOL = Blender.Draw.Create(0) - Pattern= Blender.Draw.Create(0) - block=[\ - ("Clamp Width 1", togW, "Rescale the import with a Width of one unit"),\ - ("Clamp Height 1", togH, "Rescale the import with a Heightof one unit"),\ - ("No Rescaling", togAS, "No rescaling, the result can be very large"),\ - ("Separate Curves", togSP, "Create an object for each curve, Slower. May manage colors"),\ - ("Import Colors", togCOL, "try to import color if the path is set as 'fill'. Only With separate option"),\ - ("Import Patterns", Pattern, "import pattern content if it is made with paths.")] - retval = Blender.Draw.PupBlock("Import Options", block) - if togW.val: scale_=1 - elif togH.val: scale_=2 - elif togAS.val: scale_=3 - - if togSP.val: SEPARATE_CURVES=1 - - if togCOL.val and SEPARATE_CURVES : USE_COLORS=1 - - if Pattern.val : PATTERN =1 - - t1=Blender.sys.time() - # 0.4.1 : to avoid to use sax and the xml - # tools of the complete python - build_HIERARCHY(t) - r=BOUNDINGBOX['rec'] - curves.number_of_items=len(curves.ITEM) - for k, val in curves.ITEM.iteritems(): - val.pntsUV[0] =len(val.beziers_knot) - if curves.number_of_items>0 : #and Choise==1 : - #-------------------- - # 0.4.5 and 0.4.9 - #-------------------- - createCURVES(curves, name[0]) - else: - pass - print ' elapsed time : ',Blender.sys.time()-t1 - Blender.Redraw() - -#===================================================================== -#====================== SVG format mouvements ======================== -#===================================================================== -def functionSELECT(nom): - scan_FILE(nom) - - -if __name__=='__main__': - Blender.Window.FileSelector (functionSELECT, 'SELECT an .SVG FILE', '*.svg')
\ No newline at end of file diff --git a/release/scripts/bvh_import.py b/release/scripts/bvh_import.py deleted file mode 100644 index 4134503c511..00000000000 --- a/release/scripts/bvh_import.py +++ /dev/null @@ -1,757 +0,0 @@ -#!BPY - -""" -Name: 'Motion Capture (.bvh)...' -Blender: 242 -Group: 'Import' -Tip: 'Import a (.bvh) motion capture file' -""" - -__author__ = "Campbell Barton" -__url__ = ("blender.org", "blenderartists.org") -__version__ = "1.90 06/08/01" - -__bpydoc__ = """\ -This script imports BVH motion capture data to Blender. -as empties or armatures. -""" - -# -------------------------------------------------------------------------- -# BVH Import v2.0 by Campbell Barton (AKA Ideasman) -# -------------------------------------------------------------------------- -# ***** 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 ***** -# -------------------------------------------------------------------------- - -import Blender -import bpy -import BPyMessages -Vector= Blender.Mathutils.Vector -Euler= Blender.Mathutils.Euler -Matrix= Blender.Mathutils.Matrix -RotationMatrix = Blender.Mathutils.RotationMatrix -TranslationMatrix= Blender.Mathutils.TranslationMatrix - -DEG2RAD = 0.017453292519943295 - -class bvh_node_class(object): - __slots__=(\ - 'name',# bvh joint name - 'parent',# bvh_node_class type or None for no parent - 'children',# a list of children of this type. - 'rest_head_world',# worldspace rest location for the head of this node - 'rest_head_local',# localspace rest location for the head of this node - 'rest_tail_world',# # worldspace rest location for the tail of this node - 'rest_tail_local',# # worldspace rest location for the tail of this node - 'channels',# list of 6 ints, -1 for an unused channel, otherwise an index for the BVH motion data lines, lock triple then rot triple - 'rot_order',# a triple of indicies as to the order rotation is applied. [0,1,2] is x/y/z - [None, None, None] if no rotation. - 'anim_data',# a list one tuple's one for each frame. (locx, locy, locz, rotx, roty, rotz) - 'has_loc',# Conveinience function, bool, same as (channels[0]!=-1 or channels[1]!=-1 channels[2]!=-1) - 'has_rot',# Conveinience function, bool, same as (channels[3]!=-1 or channels[4]!=-1 channels[5]!=-1) - 'temp')# use this for whatever you want - - def __init__(self, name, rest_head_world, rest_head_local, parent, channels, rot_order): - self.name= name - self.rest_head_world= rest_head_world - self.rest_head_local= rest_head_local - self.rest_tail_world= None - self.rest_tail_local= None - self.parent= parent - self.channels= channels - self.rot_order= rot_order - - # convenience functions - self.has_loc= channels[0] != -1 or channels[1] != -1 or channels[2] != -1 - self.has_rot= channels[3] != -1 or channels[4] != -1 or channels[5] != -1 - - - self.children= [] - - # list of 6 length tuples: (lx,ly,lz, rx,ry,rz) - # even if the channels arnt used they will just be zero - # - self.anim_data= [(0,0,0,0,0,0)] - - - def __repr__(self): - return 'BVH name:"%s", rest_loc:(%.3f,%.3f,%.3f), rest_tail:(%.3f,%.3f,%.3f)' %\ - (self.name,\ - self.rest_head_world.x, self.rest_head_world.y, self.rest_head_world.z,\ - self.rest_head_world.x, self.rest_head_world.y, self.rest_head_world.z) - - - -# Change the order rotation is applied. -MATRIX_IDENTITY_3x3 = Matrix([1,0,0],[0,1,0],[0,0,1]) -MATRIX_IDENTITY_4x4 = Matrix([1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]) - -def eulerRotate(x,y,z, rot_order): - # Clamp all values between 0 and 360, values outside this raise an error. - mats=[RotationMatrix(x%360,3,'x'), RotationMatrix(y%360,3,'y'), RotationMatrix(z%360,3,'z')] - # print rot_order - # Standard BVH multiplication order, apply the rotation in the order Z,X,Y - return (mats[rot_order[2]]*(mats[rot_order[1]]* (mats[rot_order[0]]* MATRIX_IDENTITY_3x3))).toEuler() - -def read_bvh(file_path, GLOBAL_SCALE=1.0): - # File loading stuff - # Open the file for importing - file = open(file_path, 'rU') - - # Seperate into a list of lists, each line a list of words. - file_lines = file.readlines() - # Non standard carrage returns? - if len(file_lines) == 1: - file_lines = file_lines[0].split('\r') - - # Split by whitespace. - file_lines =[ll for ll in [ l.split() for l in file_lines] if ll] - - - # Create Hirachy as empties - - if file_lines[0][0].lower() == 'hierarchy': - #print 'Importing the BVH Hierarchy for:', file_path - pass - else: - raise 'ERROR: This is not a BVH file' - - bvh_nodes= {None:None} - bvh_nodes_serial = [None] - - channelIndex = -1 - - - lineIdx = 0 # An index for the file. - while lineIdx < len(file_lines) -1: - #... - if file_lines[lineIdx][0].lower() == 'root' or file_lines[lineIdx][0].lower() == 'joint': - - # Join spaces into 1 word with underscores joining it. - if len(file_lines[lineIdx]) > 2: - file_lines[lineIdx][1] = '_'.join(file_lines[lineIdx][1:]) - file_lines[lineIdx] = file_lines[lineIdx][:2] - - # MAY NEED TO SUPPORT MULTIPLE ROOT's HERE!!!, Still unsure weather multiple roots are possible.?? - - # Make sure the names are unique- Object names will match joint names exactly and both will be unique. - name = file_lines[lineIdx][1] - - #print '%snode: %s, parent: %s' % (len(bvh_nodes_serial) * ' ', name, bvh_nodes_serial[-1]) - - lineIdx += 2 # Incriment to the next line (Offset) - rest_head_local = Vector( GLOBAL_SCALE*float(file_lines[lineIdx][1]), GLOBAL_SCALE*float(file_lines[lineIdx][2]), GLOBAL_SCALE*float(file_lines[lineIdx][3]) ) - lineIdx += 1 # Incriment to the next line (Channels) - - # newChannel[Xposition, Yposition, Zposition, Xrotation, Yrotation, Zrotation] - # newChannel references indecies to the motiondata, - # if not assigned then -1 refers to the last value that will be added on loading at a value of zero, this is appended - # We'll add a zero value onto the end of the MotionDATA so this is always refers to a value. - my_channel = [-1, -1, -1, -1, -1, -1] - my_rot_order= [None, None, None] - rot_count= 0 - for channel in file_lines[lineIdx][2:]: - channel= channel.lower() - channelIndex += 1 # So the index points to the right channel - if channel == 'xposition': my_channel[0] = channelIndex - elif channel == 'yposition': my_channel[1] = channelIndex - elif channel == 'zposition': my_channel[2] = channelIndex - - elif channel == 'xrotation': - my_channel[3] = channelIndex - my_rot_order[rot_count]= 0 - rot_count+=1 - elif channel == 'yrotation': - my_channel[4] = channelIndex - my_rot_order[rot_count]= 1 - rot_count+=1 - elif channel == 'zrotation': - my_channel[5] = channelIndex - my_rot_order[rot_count]= 2 - rot_count+=1 - - channels = file_lines[lineIdx][2:] - - my_parent= bvh_nodes_serial[-1] # account for none - - - # Apply the parents offset accumletivly - if my_parent==None: - rest_head_world= Vector(rest_head_local) - else: - rest_head_world= my_parent.rest_head_world + rest_head_local - - bvh_node= bvh_nodes[name]= bvh_node_class(name, rest_head_world, rest_head_local, my_parent, my_channel, my_rot_order) - - # If we have another child then we can call ourselves a parent, else - bvh_nodes_serial.append(bvh_node) - - # Account for an end node - if file_lines[lineIdx][0].lower() == 'end' and file_lines[lineIdx][1].lower() == 'site': # There is somtimes a name after 'End Site' but we will ignore it. - lineIdx += 2 # Incriment to the next line (Offset) - rest_tail = Vector( GLOBAL_SCALE*float(file_lines[lineIdx][1]), GLOBAL_SCALE*float(file_lines[lineIdx][2]), GLOBAL_SCALE*float(file_lines[lineIdx][3]) ) - - bvh_nodes_serial[-1].rest_tail_world= bvh_nodes_serial[-1].rest_head_world + rest_tail - bvh_nodes_serial[-1].rest_tail_local= rest_tail - - - # Just so we can remove the Parents in a uniform way- End end never has kids - # so this is a placeholder - bvh_nodes_serial.append(None) - - if len(file_lines[lineIdx]) == 1 and file_lines[lineIdx][0] == '}': # == ['}'] - bvh_nodes_serial.pop() # Remove the last item - - if len(file_lines[lineIdx]) == 1 and file_lines[lineIdx][0].lower() == 'motion': - #print '\nImporting motion data' - lineIdx += 3 # Set the cursor to the first frame - break - - lineIdx += 1 - - - # Remove the None value used for easy parent reference - del bvh_nodes[None] - # Dont use anymore - del bvh_nodes_serial - - bvh_nodes_list= bvh_nodes.values() - - while lineIdx < len(file_lines): - line= file_lines[lineIdx] - for bvh_node in bvh_nodes_list: - #for bvh_node in bvh_nodes_serial: - lx= ly= lz= rx= ry= rz= 0.0 - channels= bvh_node.channels - anim_data= bvh_node.anim_data - if channels[0] != -1: - lx= GLOBAL_SCALE * float( line[channels[0]] ) - - if channels[1] != -1: - ly= GLOBAL_SCALE * float( line[channels[1]] ) - - if channels[2] != -1: - lz= GLOBAL_SCALE * float( line[channels[2]] ) - - if channels[3] != -1 or channels[4] != -1 or channels[5] != -1: - rx, ry, rz = eulerRotate(float( line[channels[3]] ), float( line[channels[4]] ), float( line[channels[5]] ), bvh_node.rot_order) - #x,y,z = x/10.0, y/10.0, z/10.0 # For IPO's 36 is 360d - - # Make interpolation not cross between 180d, thjis fixes sub frame interpolation and time scaling. - # Will go from (355d to 365d) rather then to (355d to 5d) - inbetween these 2 there will now be a correct interpolation. - - while anim_data[-1][3] - rx > 180: rx+=360 - while anim_data[-1][3] - rx < -180: rx-=360 - - while anim_data[-1][4] - ry > 180: ry+=360 - while anim_data[-1][4] - ry < -180: ry-=360 - - while anim_data[-1][5] - rz > 180: rz+=360 - while anim_data[-1][5] - rz < -180: rz-=360 - - # Done importing motion data # - anim_data.append( (lx, ly, lz, rx, ry, rz) ) - lineIdx += 1 - - # Assign children - for bvh_node in bvh_nodes.itervalues(): - bvh_node_parent= bvh_node.parent - if bvh_node_parent: - bvh_node_parent.children.append(bvh_node) - - # Now set the tip of each bvh_node - for bvh_node in bvh_nodes.itervalues(): - - if not bvh_node.rest_tail_world: - if len(bvh_node.children)==0: - # could just fail here, but rare BVH files have childless nodes - bvh_node.rest_tail_world = Vector(bvh_node.rest_head_world) - bvh_node.rest_tail_local = Vector(bvh_node.rest_head_local) - elif len(bvh_node.children)==1: - bvh_node.rest_tail_world= Vector(bvh_node.children[0].rest_head_world) - bvh_node.rest_tail_local= Vector(bvh_node.children[0].rest_head_local) - else: - # allow this, see above - #if not bvh_node.children: - # raise 'error, bvh node has no end and no children. bad file' - - # Removed temp for now - rest_tail_world= Vector(0,0,0) - rest_tail_local= Vector(0,0,0) - for bvh_node_child in bvh_node.children: - rest_tail_world += bvh_node_child.rest_head_world - rest_tail_local += bvh_node_child.rest_head_local - - bvh_node.rest_tail_world= rest_tail_world * (1.0/len(bvh_node.children)) - bvh_node.rest_tail_local= rest_tail_local * (1.0/len(bvh_node.children)) - - # Make sure tail isnt the same location as the head. - if (bvh_node.rest_tail_local-bvh_node.rest_head_local).length <= 0.001*GLOBAL_SCALE: - - bvh_node.rest_tail_local.y= bvh_node.rest_tail_local.y + GLOBAL_SCALE/10 - bvh_node.rest_tail_world.y= bvh_node.rest_tail_world.y + GLOBAL_SCALE/10 - - - - return bvh_nodes - - - -def bvh_node_dict2objects(bvh_nodes, IMPORT_START_FRAME= 1, IMPORT_LOOP= False): - - if IMPORT_START_FRAME<1: - IMPORT_START_FRAME= 1 - - scn= bpy.data.scenes.active - scn.objects.selected = [] - - objects= [] - - def add_ob(name): - ob = scn.objects.new('Empty') - objects.append(ob) - return ob - - # Add objects - for name, bvh_node in bvh_nodes.iteritems(): - bvh_node.temp= add_ob(name) - - # Parent the objects - for bvh_node in bvh_nodes.itervalues(): - bvh_node.temp.makeParent([ bvh_node_child.temp for bvh_node_child in bvh_node.children ], 1, 0) # ojbs, noninverse, 1 = not fast. - - # Offset - for bvh_node in bvh_nodes.itervalues(): - # Make relative to parents offset - bvh_node.temp.loc= bvh_node.rest_head_local - - # Add tail objects - for name, bvh_node in bvh_nodes.iteritems(): - if not bvh_node.children: - ob_end= add_ob(name + '_end') - bvh_node.temp.makeParent([ob_end], 1, 0) # ojbs, noninverse, 1 = not fast. - ob_end.loc= bvh_node.rest_tail_local - - - # Animate the data, the last used bvh_node will do since they all have the same number of frames - for current_frame in xrange(len(bvh_node.anim_data)): - Blender.Set('curframe', current_frame+IMPORT_START_FRAME) - - for bvh_node in bvh_nodes.itervalues(): - lx,ly,lz,rx,ry,rz= bvh_node.anim_data[current_frame] - - rest_head_local= bvh_node.rest_head_local - bvh_node.temp.loc= rest_head_local.x+lx, rest_head_local.y+ly, rest_head_local.z+lz - - bvh_node.temp.rot= rx*DEG2RAD,ry*DEG2RAD,rz*DEG2RAD - - bvh_node.temp.insertIpoKey(Blender.Object.IpoKeyTypes.LOCROT) - - scn.update(1) - return objects - - - -def bvh_node_dict2armature(bvh_nodes, IMPORT_START_FRAME= 1, IMPORT_LOOP= False): - - if IMPORT_START_FRAME<1: - IMPORT_START_FRAME= 1 - - - # Add the new armature, - scn = bpy.data.scenes.active - scn.objects.selected = [] - - arm_data= bpy.data.armatures.new() - arm_ob = scn.objects.new(arm_data) - scn.objects.context = [arm_ob] - scn.objects.active = arm_ob - - # Put us into editmode - arm_data.makeEditable() - - # Get the average bone length for zero length bones, we may not use this. - average_bone_length= 0.0 - nonzero_count= 0 - for bvh_node in bvh_nodes.itervalues(): - l= (bvh_node.rest_head_local-bvh_node.rest_tail_local).length - if l: - average_bone_length+= l - nonzero_count+=1 - - # Very rare cases all bones couldbe zero length??? - if not average_bone_length: - average_bone_length = 0.1 - else: - # Normal operation - average_bone_length = average_bone_length/nonzero_count - - - - ZERO_AREA_BONES= [] - for name, bvh_node in bvh_nodes.iteritems(): - # New editbone - bone= bvh_node.temp= Blender.Armature.Editbone() - - bone.name= name - arm_data.bones[name]= bone - - bone.head= bvh_node.rest_head_world - bone.tail= bvh_node.rest_tail_world - - # ZERO AREA BONES. - if (bone.head-bone.tail).length < 0.001: - if bvh_node.parent: - ofs= bvh_node.parent.rest_head_local- bvh_node.parent.rest_tail_local - if ofs.length: # is our parent zero length also?? unlikely - bone.tail= bone.tail+ofs - else: - bone.tail.y= bone.tail.y+average_bone_length - else: - bone.tail.y= bone.tail.y+average_bone_length - - ZERO_AREA_BONES.append(bone.name) - - - for bvh_node in bvh_nodes.itervalues(): - if bvh_node.parent: - # bvh_node.temp is the Editbone - - # Set the bone parent - bvh_node.temp.parent= bvh_node.parent.temp - - # Set the connection state - if not bvh_node.has_loc and\ - bvh_node.parent and\ - bvh_node.parent.temp.name not in ZERO_AREA_BONES and\ - bvh_node.parent.rest_tail_local == bvh_node.rest_head_local: - bvh_node.temp.options= [Blender.Armature.CONNECTED] - - # Replace the editbone with the editbone name, - # to avoid memory errors accessing the editbone outside editmode - for bvh_node in bvh_nodes.itervalues(): - bvh_node.temp= bvh_node.temp.name - - arm_data.update() - - # Now Apply the animation to the armature - - # Get armature animation data - pose= arm_ob.getPose() - pose_bones= pose.bones - - action = Blender.Armature.NLA.NewAction("Action") - action.setActive(arm_ob) - #xformConstants= [ Blender.Object.Pose.LOC, Blender.Object.Pose.ROT ] - - # Replace the bvh_node.temp (currently an editbone) - # With a tuple (pose_bone, armature_bone, bone_rest_matrix, bone_rest_matrix_inv) - for bvh_node in bvh_nodes.itervalues(): - bone_name= bvh_node.temp # may not be the same name as the bvh_node, could have been shortened. - pose_bone= pose_bones[bone_name] - rest_bone= arm_data.bones[bone_name] - bone_rest_matrix = rest_bone.matrix['ARMATURESPACE'].rotationPart() - - bone_rest_matrix_inv= Matrix(bone_rest_matrix) - bone_rest_matrix_inv.invert() - - bone_rest_matrix_inv.resize4x4() - bone_rest_matrix.resize4x4() - bvh_node.temp= (pose_bone, bone, bone_rest_matrix, bone_rest_matrix_inv) - - - # Make a dict for fast access without rebuilding a list all the time. - xformConstants_dict={ - (True,True): [Blender.Object.Pose.LOC, Blender.Object.Pose.ROT],\ - (False,True): [Blender.Object.Pose.ROT],\ - (True,False): [Blender.Object.Pose.LOC],\ - (False,False): [],\ - } - - - # KEYFRAME METHOD, SLOW, USE IPOS DIRECT - - # Animate the data, the last used bvh_node will do since they all have the same number of frames - for current_frame in xrange(len(bvh_node.anim_data)-1): # skip the first frame (rest frame) - # print current_frame - - #if current_frame==40: # debugging - # break - - # Dont neet to set the current frame - for bvh_node in bvh_nodes.itervalues(): - pose_bone, bone, bone_rest_matrix, bone_rest_matrix_inv= bvh_node.temp - lx,ly,lz,rx,ry,rz= bvh_node.anim_data[current_frame+1] - - if bvh_node.has_rot: - # Set the rotation, not so simple - bone_rotation_matrix= Euler(rx,ry,rz).toMatrix() - bone_rotation_matrix.resize4x4() - pose_bone.quat= (bone_rest_matrix * bone_rotation_matrix * bone_rest_matrix_inv).toQuat() - - if bvh_node.has_loc: - # Set the Location, simple too - pose_bone.loc= (\ - TranslationMatrix(Vector(lx, ly, lz) - bvh_node.rest_head_local ) *\ - bone_rest_matrix_inv).translationPart() # WHY * 10? - just how pose works - - # Get the transform - xformConstants= xformConstants_dict[bvh_node.has_loc, bvh_node.has_rot] - - - if xformConstants: - # Insert the keyframe from the loc/quat - pose_bone.insertKey(arm_ob, current_frame+IMPORT_START_FRAME, xformConstants, True ) - - # First time, set the IPO's to linear - if current_frame==0: - for ipo in action.getAllChannelIpos().itervalues(): - if ipo: - for cur in ipo: - cur.interpolation = Blender.IpoCurve.InterpTypes.LINEAR - if IMPORT_LOOP: - cur.extend = Blender.IpoCurve.ExtendTypes.CYCLIC - - - - - # END KEYFRAME METHOD - - - """ - # IPO KEYFRAME SETTING - # Add in the IPOs by adding keyframes, AFAIK theres no way to add IPOs to an action so I do this :/ - for bvh_node in bvh_nodes.itervalues(): - pose_bone, bone, bone_rest_matrix, bone_rest_matrix_inv= bvh_node.temp - - # Get the transform - xformConstants= xformConstants_dict[bvh_node.has_loc, bvh_node.has_rot] - if xformConstants: - pose_bone.loc[:]= 0,0,0 - pose_bone.quat[:]= 0,0,1,0 - # Insert the keyframe from the loc/quat - pose_bone.insertKey(arm_ob, IMPORT_START_FRAME, xformConstants) - - - action_ipos= action.getAllChannelIpos() - - - for bvh_node in bvh_nodes.itervalues(): - has_loc= bvh_node.has_loc - has_rot= bvh_node.has_rot - - if not has_rot and not has_loc: - # No animation data - continue - - ipo= action_ipos[bvh_node.temp[0].name] # posebones name as key - - if has_loc: - curve_xloc= ipo[Blender.Ipo.PO_LOCX] - curve_yloc= ipo[Blender.Ipo.PO_LOCY] - curve_zloc= ipo[Blender.Ipo.PO_LOCZ] - - curve_xloc.interpolation= \ - curve_yloc.interpolation= \ - curve_zloc.interpolation= \ - Blender.IpoCurve.InterpTypes.LINEAR - - - if has_rot: - curve_wquat= ipo[Blender.Ipo.PO_QUATW] - curve_xquat= ipo[Blender.Ipo.PO_QUATX] - curve_yquat= ipo[Blender.Ipo.PO_QUATY] - curve_zquat= ipo[Blender.Ipo.PO_QUATZ] - - curve_wquat.interpolation= \ - curve_xquat.interpolation= \ - curve_yquat.interpolation= \ - curve_zquat.interpolation= \ - Blender.IpoCurve.InterpTypes.LINEAR - - # Get the bone - pose_bone, bone, bone_rest_matrix, bone_rest_matrix_inv= bvh_node.temp - - - def pose_rot(anim_data): - bone_rotation_matrix= Euler(anim_data[3], anim_data[4], anim_data[5]).toMatrix() - bone_rotation_matrix.resize4x4() - return tuple((bone_rest_matrix * bone_rotation_matrix * bone_rest_matrix_inv).toQuat()) # qw,qx,qy,qz - - def pose_loc(anim_data): - return tuple((TranslationMatrix(Vector(anim_data[0], anim_data[1], anim_data[2])) * bone_rest_matrix_inv).translationPart()) - - - last_frame= len(bvh_node.anim_data)+IMPORT_START_FRAME-1 - - if has_loc: - pose_locations= [pose_loc(anim_key) for anim_key in bvh_node.anim_data] - - # Add the start at the end, we know the start is just 0,0,0 anyway - curve_xloc.append((last_frame, pose_locations[-1][0])) - curve_yloc.append((last_frame, pose_locations[-1][1])) - curve_zloc.append((last_frame, pose_locations[-1][2])) - - if len(pose_locations) > 1: - ox,oy,oz= pose_locations[0] - x,y,z= pose_locations[1] - - for i in xrange(1, len(pose_locations)-1): # from second frame to second last frame - - nx,ny,nz= pose_locations[i+1] - xset= yset= zset= True # we set all these by default - if abs((ox+nx)/2 - x) < 0.00001: xset= False - if abs((oy+ny)/2 - y) < 0.00001: yset= False - if abs((oz+nz)/2 - z) < 0.00001: zset= False - - if xset: curve_xloc.append((i+IMPORT_START_FRAME, x)) - if yset: curve_yloc.append((i+IMPORT_START_FRAME, y)) - if zset: curve_zloc.append((i+IMPORT_START_FRAME, z)) - - # Set the old and use the new - ox,oy,oz= x,y,z - x,y,z= nx,ny,nz - - - if has_rot: - pose_rotations= [pose_rot(anim_key) for anim_key in bvh_node.anim_data] - - # Add the start at the end, we know the start is just 0,0,0 anyway - curve_wquat.append((last_frame, pose_rotations[-1][0])) - curve_xquat.append((last_frame, pose_rotations[-1][1])) - curve_yquat.append((last_frame, pose_rotations[-1][2])) - curve_zquat.append((last_frame, pose_rotations[-1][3])) - - - if len(pose_rotations) > 1: - ow,ox,oy,oz= pose_rotations[0] - w,x,y,z= pose_rotations[1] - - for i in xrange(1, len(pose_rotations)-1): # from second frame to second last frame - - nw, nx,ny,nz= pose_rotations[i+1] - wset= xset= yset= zset= True # we set all these by default - if abs((ow+nw)/2 - w) < 0.00001: wset= False - if abs((ox+nx)/2 - x) < 0.00001: xset= False - if abs((oy+ny)/2 - y) < 0.00001: yset= False - if abs((oz+nz)/2 - z) < 0.00001: zset= False - - if wset: curve_wquat.append((i+IMPORT_START_FRAME, w)) - if xset: curve_xquat.append((i+IMPORT_START_FRAME, x)) - if yset: curve_yquat.append((i+IMPORT_START_FRAME, y)) - if zset: curve_zquat.append((i+IMPORT_START_FRAME, z)) - - # Set the old and use the new - ow,ox,oy,oz= w,x,y,z - w,x,y,z= nw,nx,ny,nz - - # IPO KEYFRAME SETTING - """ - pose.update() - return arm_ob - - -#=============# -# TESTING # -#=============# - -#('/metavr/mocap/bvh/boxer.bvh') -#('/d/staggered_walk.bvh') -#('/metavr/mocap/bvh/dg-306-g.bvh') # Incompleate EOF -#('/metavr/mocap/bvh/wa8lk.bvh') # duplicate joint names, \r line endings. -#('/metavr/mocap/bvh/walk4.bvh') # 0 channels - -''' -import os -DIR = '/metavr/mocap/bvh/' -for f in ('/d/staggered_walk.bvh',): - #for f in os.listdir(DIR)[5:6]: - #for f in os.listdir(DIR): - if f.endswith('.bvh'): - s = Blender.Scene.New(f) - s.makeCurrent() - #file= DIR + f - file= f - print f - bvh_nodes= read_bvh(file, 1.0) - bvh_node_dict2armature(bvh_nodes, 1) -''' - -def load_bvh_ui(file, PREF_UI= True): - - if BPyMessages.Error_NoFile(file): - return - - Draw= Blender.Draw - - IMPORT_SCALE = Draw.Create(0.1) - IMPORT_START_FRAME = Draw.Create(1) - IMPORT_AS_ARMATURE = Draw.Create(1) - IMPORT_AS_EMPTIES = Draw.Create(0) - IMPORT_LOOP = Draw.Create(0) - - # Get USER Options - if PREF_UI: - pup_block = [\ - ('As Armature', IMPORT_AS_ARMATURE, 'Imports the BVH as an armature'),\ - ('As Empties', IMPORT_AS_EMPTIES, 'Imports the BVH as empties'),\ - ('Scale: ', IMPORT_SCALE, 0.001, 100.0, 'Scale the BVH, Use 0.01 when 1.0 is 1 metre'),\ - ('Start Frame: ', IMPORT_START_FRAME, 1, 30000, 'Frame to start BVH motion'),\ - ('Loop Animation', IMPORT_LOOP, 'Enable cyclic IPOs'),\ - ] - - if not Draw.PupBlock('BVH Import...', pup_block): - return - - print 'Attempting import BVH', file - - IMPORT_SCALE = IMPORT_SCALE.val - IMPORT_START_FRAME = IMPORT_START_FRAME.val - IMPORT_AS_ARMATURE = IMPORT_AS_ARMATURE.val - IMPORT_AS_EMPTIES = IMPORT_AS_EMPTIES.val - IMPORT_LOOP = IMPORT_LOOP.val - - if not IMPORT_AS_ARMATURE and not IMPORT_AS_EMPTIES: - Blender.Draw.PupMenu('No import option selected') - return - Blender.Window.WaitCursor(1) - # Get the BVH data and act on it. - t1= Blender.sys.time() - print '\tparsing bvh...', - bvh_nodes= read_bvh(file, IMPORT_SCALE) - print '%.4f' % (Blender.sys.time()-t1) - t1= Blender.sys.time() - print '\timporting to blender...', - if IMPORT_AS_ARMATURE: bvh_node_dict2armature(bvh_nodes, IMPORT_START_FRAME, IMPORT_LOOP) - if IMPORT_AS_EMPTIES: bvh_node_dict2objects(bvh_nodes, IMPORT_START_FRAME, IMPORT_LOOP) - - print 'Done in %.4f\n' % (Blender.sys.time()-t1) - Blender.Window.WaitCursor(0) - -def main(): - Blender.Window.FileSelector(load_bvh_ui, 'Import BVH', '*.bvh') - -if __name__ == '__main__': - #def foo(): - main() - ''' - scn = bpy.data.scenes.active - for ob in list(scn.objects): - if ob.name!='arm__': - scn.objects.unlink(ob) - load_bvh_ui('/test.bvh', False) - '''
\ No newline at end of file diff --git a/release/scripts/c3d_import.py b/release/scripts/c3d_import.py deleted file mode 100644 index 98f643cbab9..00000000000 --- a/release/scripts/c3d_import.py +++ /dev/null @@ -1,1244 +0,0 @@ -#!BPY -# -*- coding: latin-1 -*- -""" -Name: 'Motion Capture (.c3d)...' -Blender: 246 -Group: 'Import' -Tooltip: 'Import a C3D Motion Capture file' -""" -__script__ = "C3D Motion Capture file import" -__author__ = " Jean-Baptiste PERIN, Roger D. Wickes (rogerwickes@yahoo.com)" -__version__ = "0.9" -__url__ = ["Communicate problems and errors, BlenderArtists.org, Python forum"] -__email__= ["rogerwickes@yahoo.com", "c3d script"] -__bpydoc__ = """\ -c3d_import.py v0.8 - -Script loading Graphics Lab Motion Capture file, -Usage:<br> - - Run the script <br> - - Choose the file to open<br> - - Press Import C3D button<br> - -Version History: - 0.4: PERIN Released under Blender Artistic Licence - 0.5: WICKES used marker names, fixed 2.45 depricated call - 0.6: WICKES creates armature for each subject - 0.7: WICKES constrains armature to follow the empties (markers). Verified for shake hands s - 0.8: WICKES resolved DEC support issue - 0.9: BARTON removed scene name change, whitespace edits. WICKES added IK layers -""" - -#---------------------------------------------- -# (c) Jean-Baptiste PERIN december 2005, released under Blender Artistic Licence -# for the Blender 2.40 Python Scripts Bundle. -#---------------------------------------------- - -###################################################### -# This script imports a C3D file into blender. -# Loader is based on MATLAB C3D loader from -# Alan Morris, Toronto, October 1998 -# Jaap Harlaar, Amsterdam, april 2002 -###################################################### - -import string -import Blender -from Blender import * -import bpy -import struct -import BPyMessages -Vector= Blender.Mathutils.Vector -Euler= Blender.Mathutils.Euler -Matrix= Blender.Mathutils.Matrix -RotationMatrix = Blender.Mathutils.RotationMatrix -TranslationMatrix= Blender.Mathutils.TranslationMatrix - -#================= -# Global Variables, Constants, Defaults, and Shorthand References -#================= -# set senstitivity for displaying debug/console messages. 0=few, 100=max, including clicks at major steps -# debug(num,string) to conditionally display status/info in console window -DEBUG=Blender.Get('rt') - -# marker sets known in the world -HUMAN_CMU= "HumanRTKm.mkr" # The Human Real-Time capture marker set used by CMU -HUMAN_CMU2="HumanRT.mkr" # found in another file, seems same as others in that series -MARKER_SETS = [ HUMAN_CMU, HUMAN_CMU2 ] # marker sets that this program supports (can make an armature for) -XYZ_LIMIT= 10000 #max value for coordinates if in integer format - -# what layers to put stuff on in scene. 1 is selected, so everything goes there -# selecting only layer 2 shows only the armature moving, 12 shows only the empties -LAYERS_ARMOB= [1,2] -LAYERS_MARKER=[1,12] -LAYERS_IK=[1,11] -IK_PREFIX="ik_" # prefix in empty name: ik_prefix+subject prefix+bone name - -CLEAN=True # Should program ignore markers at (0,0,0) and beyond the outer limits? - -scn = Blender.Scene.GetCurrent() - -BCS=Blender.Constraint.Settings # shorthand dictionary - define with brace, reference with bracket -trackto={"+x":BCS.TRACKX, "+y":BCS.TRACKY, "+z":BCS.TRACKZ, "-x":BCS.TRACKNEGX, "-y":BCS.TRACKNEGY, "-z":BCS.TRACKNEGZ} -trackup={"x":BCS.UPX, "y":BCS.UPY, "z":BCS.UPZ} - -#=============================# -# Classes -#=============================# -class Marker: - def __init__(self, x, y, z): - self.x=0.0 - self.y=0.0 - self.z=0.0 - - def __repr__(self): #report on self, as in if just printed - return str("[x = "+str(self.x) +" y = " + str(self.y)+" z = "+ str(self.z)+"]") - -class ParameterGroup: - def __init__(self, nom, description, parameter): - self.name = nom - self.description = description - self.parameter = parameter - - def __repr__(self): - return self.name, " ", self.description, " ", self.parameter - -class Parameter: - def __init__(self, name, datatype, dim, data, description): - self.name = name - self.datatype = datatype - self.dim = dim - self.data = data - self.description = description - - def __repr__(self): - return self.name, " ", self.description, " ", self.dim - -class MyVector: - def __init__(self, fx,fy,fz): - self.x=fx - self.y=fy - self.z=fz - -class Mybone: - "information structure for bone generation and posing" - def __init__(self, name,vec,par,head,tail,const): - self.name=name # name of this bone. must be unique within armature - self.vec=vec # edit bone vector it points - self.parent=par # name of parent bone to locate head and form a chain - self.headMark=head # list of 0+ markers where the head of this non-parented bone should be placed - self.tailMark=tail # list of 0+ markers where the tip should be placed - self.const=const # list of 0+ constraint tuples to control posing - self.head=MyVector(0,0,0) #T-pose location - self.tail=MyVector(0,0,0) - def __repr__(self): - return '[Mybone "%s"]' % self.name - - -#=============================# -# functions/modules -#=============================# -def error(str): - Draw.PupMenu('ERROR%t|'+str) - return -def status(str): - Draw.PupMenu('STATUS%t|'+str+"|Continue?") - return -def debug(num,msg): #use log4j or just console here. - if DEBUG >= num: - print 'debug:', (' '*num), msg - #TODO: if level 0, make a text file in Blender file to record major stuff - return - -def names(ob): return ob.name - - -######### -# Cette fonction renvoie la liste des empties -# in : -# out : emp_list (List of Object) la liste des objets de type "Empty" -######### -def getEmpty(name): - obs = [ob for ob in scn.objects if ob.type=="Empty" and ob.name==name] - if len(obs)==0: - return None - elif len(obs)==1: - return obs[0] - else: - error("FATAL ERROR: %i empties %s in file" % (len(obs),ob[0])) -######### -# Cette fonction renvoie un empty -# in : objname : le nom de l'empty recherche -# out : myobj : l'empty cree ou retrouve -######### -def getOrCreateEmpty(objname): - myobj= getEmpty(objname) - if myobj==None: - myobj = scn.objects.new("Empty",objname) - debug(50,'Marker/Empty created %s' % myobj) - return myobj - -def getOrCreateCurve(ipo, curvename): - """ - Retrieve or create a Blender Ipo Curve named C{curvename} in the C{ipo} Ipo - - >>> import mylib - - >>> lIpo = GetOrCreateIPO("Une IPO") - >>> laCurve = getOrCreateCurve(lIpo, "RotX") - - Either an ipo curve named C{curvename} exists before the call then this curve is returned, - Or such a curve doesn't exist before the call .. then it is created into the c{ipo} Ipo and returned - - @type ipo: Blender Ipo - @param ipo: the Ipo in which the curve must be retrieved or created. - @type curvename: string - @param curvename: name of the IPO. - @rtype: Blender Curve - @return: a Blender Curve named C{curvename} in the C{ipo} Ipo - """ - try: - mycurve = ipo.getCurve(curvename) - if mycurve != None: - pass - else: - mycurve = ipo.addCurve(curvename) - except: - mycurve = ipo.addCurve(curvename) - return mycurve - -def eraseIPO (objectname): - object = Blender.Object.Get(objectname) - lIpo = object.getIpo() - if lIpo != None: - nbCurves = lIpo.getNcurves() - for i in range(nbCurves): - nbBezPoints = lIpo.getNBezPoints(i) - for j in range(nbBezPoints): - lIpo.delBezPoint(i) - -def comp_loc(emptyNameList): - myloc=Vector(0,0,0) - for emName in emptyNameList: - myobj = Blender.Object.Get(emName) - for i in range(3): - myloc[i]= myloc[i]+(myobj.loc[i]/len(emptyNameList)) #take the average loc of all marks - return myloc - -def comp_len(head, tail): # computes the length of a bone - headvec=comp_loc(head) - tailvec=comp_loc(tail) - netvec=headvec-tailvec - return netvec.length - -def createHumanCMU(): # human bone structure, makes a node set for CMU MoCap Lab - # order of bones: "spine","chest","neck","head",...face toward you in front view - # pose constraints are tuples of (type,target,influence,other-as-needed) - # constraint stack order is important. for proper bone pointing and orinetation: - # IK, then TT +YZ in world space. then LR XZ to 0 in world space, this points the bone, twists it, but then - # limits the rotation to the sidebar enpty with the Z facing it, and Y pointing along the bone. - nodes=[] # bonename, vector, parent, head targets, tail targets, constraint list - for i in range(23): nodes.append(Mybone("name","vec","par",[],[],[])) - nodes[0]= Mybone("root", "-Y","",["RBWT", "LBWT"],["RFWT", "LFWT", "RBWT", "LBWT"],[("LOC","RBWT",1.0),("LOC","LBWT",0.5),("IK","RFWT",1.0),("IK","LFWT",0.5),("TT","RBWT",1,"+YZ"),("LR","XZ",1)]) - nodes[1]= Mybone("spine","+Z","root",[],["STRN","T10"],[("IK","STRN",1.0),("IK","T10",0.5),("TT","STRN",1,"+YZ"),("LR","XZ",1)]) - nodes[2]= Mybone("chest","+Z","spine",[],["CLAV","C7"],[("IK","CLAV",1.0),("IK","C7",0.5),("TT","CLAV",1,"+YZ"),("LR","XZ",1)]) - nodes[3]= Mybone("neck", "+Z","chest",[],["RBHD","LBHD"],[("IK","RBHD",1.0),("IK","LBHD",0.5),("TT","LBHD",1,"+YZ"),("LR","XZ",1)]) - nodes[4]= Mybone("head" ,"-Y","neck",[],["RFHD","LFHD"],[("IK","RFHD",1.0),("IK","LFHD",0.5),("TT","LFHD",1,"+YZ"),("LR","XZ",1)]) - - nodes[5]= Mybone("shoulder.R","-X","chest",[],["RSHO"],[("IK","RSHO",1.0)]) - nodes[6]= Mybone("toparm.R", "-X","shoulder.R",[],["RELB"],[("IK","RELB",1.0),("TT","RUPA",1,"+YZ"),("LR","XZ",1)]) - nodes[7]= Mybone("lowarm.R", "-X","toparm.R",[],["RWRA","RWRB"],[("IK","RWRA",1.0),("IK","RWRB",0.5),("TT","RFRM",1,"+YZ"),("LR","XZ",1)]) - nodes[8]= Mybone("hand.R", "-X","lowarm.R",[],["RFIN"],[("IK","RFIN",1.0),("TT","RWRA",1,"+YZ"),("LR","XZ",1)]) #missing ,"RTHM" - - nodes[9]= Mybone("hip.R", "-X","root",[],["RFWT","RBWT"],[("IK","RFWT",1.0),("IK","RBWT",0.5)]) - nodes[10]=Mybone("topleg.R","-Z","hip.R",[],["RKNE"],[("IK","RKNE",1),("TT","RTHI",1,"+YZ"),("LR","XZ",1)]) - nodes[11]=Mybone("lowleg.R","-Z","topleg.R",[],["RANK","RHEE"],[("IK","RHEE",1.0),("TT","RSHN",1,"+YZ"),("LR","XZ",1)]) - nodes[12]=Mybone("foot.R", "-Y","lowleg.R",[],["RTOE","RMT5"],[("IK","RTOE",1.0),("IK","RMT5",0.2),("TT","RMT5",1,"+YZ")]) - nodes[13]=Mybone("toes.R", "-Y","foot.R",[],["RTOE"],[("IK","RTOE",1.0)]) - - nodes[14]=Mybone("shoulder.L","+X","chest",[],["LSHO"],[("IK","LSHO",1.0)]) - nodes[15]=Mybone("toparm.L", "+X","shoulder.L",[],["LELB"],[("IK","LELB",1.0),("TT","LUPA",1,"+YZ"),("LR","XZ",1)]) - nodes[16]=Mybone("lowarm.L", "+X","toparm.L",[],["LWRA","LWRB"],[("IK","LWRA",1.0),("IK","LWRB",0.5),("TT","LFRM",1,"+YZ"),("LR","XZ",1)]) - nodes[17]=Mybone("hand.L", "+X","lowarm.L",[],["LFIN"],[("IK","LFIN",1.0),("TT","RWRA",1,"+YZ"),("LR","XZ",1)]) #missing ,"LTHM" - - nodes[18]=Mybone("hip.L", "+X","root",[],["LFWT","LBWT"],[("IK","LFWT",1.0),("IK","LBWT",0.5)]) - nodes[19]=Mybone("topleg.L","-Z","hip.L",[],["LKNE"],[("IK","LKNE",1),("TT","LTHI",1,"+YZ"),("LR","XZ",1)]) - nodes[20]=Mybone("lowleg.L","-Z","topleg.L",[],["LANK","LHEE"],[("IK","LHEE",1.0),("TT","LSHN",1,"+YZ"),("LR","XZ",1)]) - nodes[21]=Mybone("foot.L", "-Y","lowleg.L",[],["LTOE","LMT5"],[("IK","LTOE",1.0),("IK","LMT5",0.2),("TT","LMT5",1,"+YZ"),("LR","XZ",1)]) - nodes[22]=Mybone("toes.L", "-Y","foot.L",[],["LTOE"],[("IK","LTOE",1.0)]) - return nodes - -def createNodes(marker_set): # make a list of bone name, parent, edit head loc, edit tail loc, pose constraints - #ultimately, I want to read in an XML file here that specifies the node trees for various marker sets - if marker_set==HUMAN_CMU: nodes= createHumanCMU() #load up and verify the file has the CMU marker set - elif marker_set==HUMAN_CMU2: nodes= createHumanCMU() - else: nodes=[] - return nodes -def findEntry(item,list): - for i in range(len(list)): - if item==list[i]: break - debug(100,"findEtnry %s is %i in list of %i items" % (item,i,len(list))) - return i -def makeNodes(prefix, markerList, empties, marker_set): #make sure the file has the nodes selected - nodes= createNodes(marker_set) # list has generic marker names; replace them with the actual object names created - #each entry in markerlist has a corresponding entry in empties in the same order - errList=[] - for i in range(len(nodes)): - node= nodes[i] - debug(60,"Adapting node %s to prefix %s" % (node,prefix)) - - #replace generic head markers with actual empty names - for im in range(len(node.headMark)): - marker= node.headMark[im] - mark= prefix+marker - imn= findEntry(mark,markerList) - if imn < len(markerList): - debug(90,"Adapating head marker %s to %s" % (marker,empties[imn].name)) - nodes[i].headMark[im]= empties[imn].name - else: errList.append([node.name,"head location",mark,node,2]) - - #replace generic tail markers with actual empty names - for im in range(len(node.tailMark)): - marker= node.tailMark[im] - mark= prefix+marker - imn= findEntry(mark,markerList) - if imn < len(markerList): - debug(90,"Adapating marker %s to %s" % (marker,empties[imn].name)) - nodes[i].tailMark[im]= empties[imn].name - else: errList.append([node.name,"tail location",mark,node,2]) - - #replace generic constraint markers (if the constraint references a marker) with empty name - for im in range(len(node.const)): - const=node.const[im] - if const[0] in ("LOC","IK","TT"): - marker=const[1] - mark= prefix+marker - imn= findEntry(mark,markerList) - if imn < len(markerList): - debug(90,"Adapating %s constraint marker %s to %s" % (const[0],marker,empties[imn].name)) - if const[0] in ("IK","LR","LOC"): - nodes[i].const[im]=(const[0], empties[imn].name, const[2]) - else: nodes[i].const[im]=(const[0], empties[imn].name, const[2], const[3]) - else: errList.append([node.name,const[0]+" constraint",mark,node,4]) - - if errList!=[]: #we have issues. - for err in errList: - debug(0,"Bone "+err[0]+" specifies "+err[2]+" as "+err[1]+"which was not specified in file.") - #need a popup here to ignore/cleanup node tree, or add the marker(?) or abort - usrOption= 1 - if usrOption==0: #ignore this marker (remove it) - for node in nodes: #find the bone in error - if node.name==err[0]: - print "Before",node - if err[3] in range(2,3): - node[err[3]].remove(err[2]) #find the marker in error and remove it - elif err[3]==4: #find the constraint and remove it - for const in node.const: - if const[1]==err[2]: node.const.remove(const) - print "After",node - elif usrOption==1: #add these markers as static empties, and user will automate them later - #and the bones will be keyed to them, so it will all be good. - #file may have just mis-named the empty, or the location can be derived based on other markers - em= getOrCreateEmpty(err[2]) - em.layers= LAYERS_MARKER - else: abort() #abend - if DEBUG==100: status("Nodes Updated") - return nodes #nodes may be updated - -def makeBones(arm,nodes): - debug(20,"Making %i edit bones" % len(nodes)) - for node in nodes: - bone= Blender.Armature.Editbone() - bone.name= node.name - arm.bones[bone.name]= bone #add it to the armature - debug(50,"Bone added: %s" % bone) - if bone.name <> node.name: - debug(0,"ERROR: duplicate node % name specified" % node.name) - node.name= bone.name #you may not get what you asked for - if node.parent!="": #parent - debug(60,"Bone parent: %s"%node.parent) - bone.parent= arm.bones[node.parent] - bone.options = [Armature.CONNECTED] - #compute head = average of the reference empties - if node.headMark==[]: # no head explicitly stated, must be tail of parent - for parnode in nodes: - if node.parent==parnode.name: break - node.headMark= parnode.tailMark - node.head= parnode.tail - else: node.head= comp_loc(node.headMark) #node head is specified, probably only for root. - - bone.head= node.head - debug(60,"%s bone head: (%0.2f, %0.2f, %0.2f)" % (bone.name,bone.head.x, bone.head.y, bone.head.z)) - mylen=comp_len(node.headMark,node.tailMark) # length of the bone as it was recorded for that person - # for our T position, compute the bone length, add it to the head vector component to get the tail - if node.vec[0]=="-": mylen=-mylen - debug(80,"Bone vector %s length %0.2f" %(node.vec,mylen)) - node.tail= Vector(node.head) - myvec=node.vec[1].lower() - if myvec=="x": node.tail.x+=mylen - elif myvec=="y": node.tail.y+=mylen - elif myvec=="z": node.tail.z+=mylen - else: - debug(0,"%s %s %s %s" % (node.vec,myvec,node.vec[0],node.vec[1])) - error("ERROR IN BONE SPEC ") - bone.tail= node.tail - debug(60,"Bone tail: (%i,%i,%i)" %(bone.tail.x, bone.tail.y, bone.tail.z)) - #Armature created in the T postion, but with bone lengths to match the marker set and subject - #when this is constrained to the markers, the recorded action will be relative to a know Rotation - #so that all recorded actions should be interchangeable. wooot! - #Only have to adjust starting object loc when matching up actions. - return #arm #updated - -def makeConstLoc(pbone,const): - const_new= pbone.constraints.append(Constraint.Type.COPYLOC) - const_new.name = const[0]+"-"+const[1] - const_target=Blender.Object.Get(const[1]) - const_new[BCS.TARGET]= const_target - const_new.influence = const[2] - return - -def makeConstLimRot(pbone,const): - const_new= pbone.constraints.append(Constraint.Type.LIMITROT) - const_new.name = const[0]+"-"+const[1] - for axis in const[1]: - if axis.lower()=="x": const_new[BCS.LIMIT] |= BCS.LIMIT_XROT #set - if axis.lower()=="y": const_new[BCS.LIMIT] |= BCS.LIMIT_YROT #set - if axis.lower()=="z": const_new[BCS.LIMIT] |= BCS.LIMIT_ZROT #set - const_new[BCS.OWNERSPACE]= BCS.SPACE_LOCAL - const_new.influence = const[2] - # fyi, const[Constraint.Settings.LIMIT] &= ~Constraint.Settings.LIMIT_XROT #reset - return - -def makeConstIK(prefix,pbone,const): - #Blender 246 only supports one IK Solver per bone, but we might want many, - # so we need to create a reference empty named after the bone - # that floats between the markers, so the bone can point to it as a singularity - myob= getOrCreateEmpty(IK_PREFIX+prefix+pbone.name) - myob.layers= LAYERS_IK - # note that this empty gets all the IK constraints added on as location constraints - myconst= myob.constraints.append(Constraint.Type.COPYLOC) - myconst.name=const[0]+"-"+const[1] - myconst[Constraint.Settings.TARGET]= Blender.Object.Get(const[1]) - myconst.influence = const[2] - - #point the bone once to the empty via IK - success=False - for myconst in pbone.constraints: - if myconst.type == Constraint.Type.IKSOLVER: success=True - if not(success): #add an IK constraint to the bone to point to the empty - #print pbone - myconst= pbone.constraints.append(Constraint.Type.IKSOLVER) - myconst.name = const[1] - myconst[BCS.TARGET]= myob - myconst.influence = const[2] - #const_new[Constraint.Settings.BONE]= ? - myconst[BCS.CHAINLEN]= 1 - myconst[BCS.USETIP]= True - myconst[BCS.STRETCH]= False - return - -def makeConstTT(pbone,const): - myconst= pbone.constraints.append(Constraint.Type.TRACKTO) - myconst.name=const[0]+"-"+const[1] - debug(70,"%s %s" % (myconst,const[3])) - myob= getEmpty(const[1]) - if myob!= None: - myconst[BCS.TARGET]= myob - myconst.influence = const[2] - #const[3] is the Track and the thrird char is the Up indicator - myconst[BCS.TRACK]= trackto[const[3][0:2].lower()] - myconst[BCS.UP]=trackup[const[3][2].lower()]#up direction - myconst[BCS.OWNERSPACE]= BCS.SPACE_LOCAL - myconst[BCS.TARGETSPACE]= [BCS.SPACE_LOCAL] - if const[3][1]==const[3][2]: debug(0,"WARNING: Track To axis and up axis should not be the same. Constraint is INACTIVE") - else: #marker not found. could be missing from this file, or an error in node spec - error("TrackTo Constraint for %s |specifies unknown marker %s" % (pbone.name,const[1])) - return - -def makePoses(prefix,arm_ob,nodes): # pose this armature object based on node requirements - #this is constraint-based posing, not hard-keyed posing. - #we do constraint-based first so that user can adjust the constraints, possibly smooth/tweak motion - # add additional bones or referneces/constraints, before baking to hard keyframes - - pose= arm_ob.getPose() - debug(0,"Posing %s %s" % (arm_ob, pose)) - for node in nodes: - debug(30, "examining %s" %node) - if len(node.const)>0: #constraints for this bone are desired - pbone = pose.bones[node.name] - debug(40,"Posing bone %s" %pbone) - for const in node.const: - debug(50,"Constraining %s by %s" %(pbone,const)) - if const[0]=="LOC":makeConstLoc(pbone,const) - elif const[0]=="IK": makeConstIK(prefix,pbone,const) - elif const[0]=="LR": makeConstLimRot(pbone,const) - elif const[0]=="TT": makeConstTT(pbone,const) - else: - error("FATAL: constraint %s not supported" %const[0]) - break - debug(10, "Posing complete. Cycling pose and edit mode") - pose.update() - return - -def make_arm(subject,prefix,markerList, emptyList,marker_set): - debug(10,"**************************") - debug(00, "**** Making Armature for %s..." % subject) - debug(10, "**************************") - # copied from bvh import bvh_node_dict2armature; trying to use similar process for further integtration down the road - # Add the new armature, - - nodes= makeNodes(prefix, markerList, emptyList, marker_set) #assume everyone in file uses the same mocap suit - # each person in the file may be different height, so each needs their own new armature to match marker location - -## obs= Blender.Object.Get() -## success=False -## for ob in obs: -## if ob.name==subject: -## success=True -## if success: -## menu="Human Armature already exists for this subject." -## menu+="%t|Create another in this scene" -## menu+="%l|Start a new scene" -## menu+="%l|Use this armature" -## menusel= Draw.PupMenu(menu) - - arm= Blender.Armature.New(subject) #make an armature. - debug(10,"Created Armature %s" % arm) - # Put us into editmode - arm.makeEditable() - arm.drawType = Armature.OCTAHEDRON - makeBones(arm,nodes) - scn = Blender.Scene.GetCurrent() #add it to the current scene. could create new scenes here as yaf - arm_ob= scn.objects.new(arm) #instance it in the scene. this is the new way for 2.46 to instance objects - arm_ob.name= subject #name it something like the person it represents - arm_ob.layers= LAYERS_ARMOB - debug(20,"Instanced Armature %s" % arm_ob) - arm.update() #exit editmode. Arm must be instanced as an object before you can save changes or pose it - Blender.Redraw() # show the world - if DEBUG==100: status("T-Bones made.") - - makePoses(prefix,arm_ob,nodes) #constrain arm_ob with these markers - - scn.update(1) #make everyone behave themselves in the scene, and respect the new constraints - return arm_ob - -def setupAnim(StartFrame, EndFrame, VideoFrameRate): - debug(100, 'VideoFrameRate is %i' %VideoFrameRate) - if VideoFrameRate<1: VideoFrameRate=1 - if VideoFrameRate>120: VideoFrameRate=120 - # set up anim panel for them - context=scn.getRenderingContext() - context.sFrame=StartFrame - context.eFrame=EndFrame - context.fps=int(VideoFrameRate) - - Blender.Set("curframe",StartFrame) - Blender.Redraw() - return - -def makeCloud(Nmarkers,markerList,StartFrame,EndFrame,Markers): - debug(10, "**************************") - debug(00, "*** Making Cloud Formation") - debug(10, "**************************") - empties=[] - ipos=[] - curvesX=[] - curvesY=[] - curvesZ=[] - debug(0, "%i Markers (empty cloud) will be put on layers %s" % (Nmarkers,LAYERS_MARKER)) - # Empty Cloud formation - for i in range(Nmarkers): - debug(100,"%i marker %s"%(i, markerList[i])) - emptyname = markerList[i] # rdw: to use meaningful names from Points parameter - em= getOrCreateEmpty(emptyname) #in this scene - em.layers= LAYERS_MARKER - #make a list of the actual empty - empties.append(em) - #assign it an ipo with the loc xyz curves - lipo = Ipo.New("Object",em.name) - ipos.append(lipo) - curvesX.append(getOrCreateCurve(ipos[i],'LocX')) - curvesY.append(getOrCreateCurve(ipos[i],'LocY')) - curvesZ.append(getOrCreateCurve(ipos[i],'LocZ')) - empties[i].setIpo(ipos[i]) - debug(30,"Cloud of %i empties created." % len(empties)) - NvideoFrames= EndFrame-StartFrame+1 - debug(10, "**************************") - debug(00, "**** Calculating Marker Ipo Curves over %i Frames ..." % NvideoFrames) - debug(10, "**************************") - err= index=0 #number of errors, logical frame - for frame in range(StartFrame,EndFrame+1): - if index==0: start=sys.time() - elif index==100: - tmp=(NvideoFrames-100)*(sys.time()-start)/6000 - debug(0,"%i minutes process time estimated" % tmp) - elif index >100: print index*100/(NvideoFrames-1),"% complete\r", - for i in range(Nmarkers): - if Markers[index][i].z < 0: Markers[index][i].z= -Markers[index][i].z - success=True - if CLEAN: #check for good data - # C3D marker decoding may have coordinates negative (improper sign bit decoding?) - myX= abs(Markers[index][i].x) - myY= abs(Markers[index][i].y) - myZ= Markers[index][i].z - if myX > 10000 or myY > 10000 or myZ > 10000: success=False - if myX <.01 and myY <.01 and myZ <.01: success=False # discontinuity in marker tracking (lost marker) - - if success: - curvesX[i].append((frame, Markers[index][i].x)) #2.46 knot method - curvesY[i].append((frame, Markers[index][i].y)) - curvesZ[i].append((frame, Markers[index][i].z)) - if frame==StartFrame: debug(40, "%s loc frame %i: (%0.2f, %0.2f, %0.2f)" % (markerList[i],frame,Markers[index][i].x,Markers[index][i].y,Markers[index][i].z)) - else: - err+=1 # some files have thousands... - #debug(30,"Point ignored for marker:%s frame %i: (%i, %i, %i)" % (markerList[i],frame,Markers[index][i].x,Markers[index][i].y,Markers[index][i].z)) - index += 1 - debug(70, "%i points ignored across all markers and frames. Recalculating..." % err) - - for i in range(Nmarkers): - curvesX[i].Recalc() - curvesY[i].Recalc() - curvesZ[i].Recalc() - Blender.Set('curframe', StartFrame) - Blender.Redraw() - if DEBUG==100: status("Clound formed") - return empties - -def getNumber(str, length): - if length==2: # unsigned short - return struct.unpack('H',str[0:2])[0], str[2:] - sum = 0 - for i in range(length): - #sum = (sum << 8) + ord(str[i]) for big endian - sum = sum + ord(str[i])*(2**(8*i)) - return sum, str[length:] -def unpackFloat(chunk,proctype): - #print proctype - myvar=chunk[0:4] - if proctype==2: #DEC-VAX - myvar=chunk[2:4]+chunk[0:2] #swap lo=hi word order pair - return struct.unpack('f',myvar[0:4])[0] - -def getFloat(chunk,proctype): - return unpackFloat(chunk, proctype), chunk[4:] -def parseFloat(chunk,ptr,proctype): - return unpackFloat(chunk[ptr:ptr+4], proctype), ptr+4 - - -def load_c3d(FullFileName): -# Input: FullFileName - file (including path) to be read -# -# Variable: -# Markers 3D-marker data [Nmarkers x NvideoFrames x Ndim(=3)] -# VideoFrameRate Frames/sec -# AnalogSignals Analog signals [Nsignals x NanalogSamples ] -# AnalogFrameRate Samples/sec -# Event Event(Nevents).time ..value ..name -# ParameterGroup ParameterGroup(Ngroups).Parameters(Nparameters).data ..etc. -# CameraInfo MarkerRelated CameraInfo [Nmarkers x NvideoFrames] -# ResidualError MarkerRelated ErrorInfo [Nmarkers x NvideoFrames] - - Markers=[]; - VideoFrameRate=120; - AnalogSignals=[]; - AnalogFrameRate=0; - Event=[]; - ParameterGroups=[]; - CameraInfo=[]; - ResidualError=[]; - - debug(10, "*********************") - debug(10, "**** Opening File ***") - debug(10, "*********************") - - #ind=findstr(FullFileName,'\'); - #if ind>0, FileName=FullFileName(ind(length(ind))+1:length(FullFileName)); else FileName=FullFileName; end - debug(0, "FileName = " + FullFileName) - fid=open(FullFileName,'rb'); # native format (PC-intel). ideasman says maybe rU - content = fid.read(); - content_memory = content - #Header section - NrecordFirstParameterblock, content = getNumber(content,1) # Reading record number of parameter section - - key, content = getNumber(content,1) - if key!=80: - error('File: does not comply to the C3D format') - fid.close() - return - #Paramter section - content = content[512*(NrecordFirstParameterblock-1)+1:] # first word ignored - #file format spec says that 3rd byte=NumberofParmaterRecords... but is ignored here. - proctype,content =getNumber(content,1) - proctype = proctype-83 - proctypes= ["unknown","(INTEL-PC)","(DEC-VAX)","(MIPS-SUN/SGI)"] - - if proctype in (1,2): debug(0, "Processor coding %s"%proctypes[proctype]) - elif proctype==3: debug(0,"Program untested with %s"%proctypes[proctype]) - else: - debug(0, "INVALID processor type %i"%proctype) - proctype=1 - debug(0,"OVERRIDE processor type %i"%proctype) - - #if proctype==2, - # fclose(fid); - # fid=fopen(FullFileName,'r','d'); % DEC VAX D floating point and VAX ordering - #end - debug(10, "***********************") - debug(00, "**** Reading Header ***") - debug(10, "***********************") - - # ############################################### - # ## ## - # ## read header ## - # ## ## - # ############################################### - - #%NrecordFirstParameterblock=fread(fid,1,'int8'); % Reading record number of parameter section - #%key1=fread(fid,1,'int8'); % key = 80; - - content = content_memory - #fseek(fid,2,'bof'); - content = content[2:] - - # - Nmarkers, content=getNumber(content, 2) - NanalogSamplesPerVideoFrame, content = getNumber(content, 2) - StartFrame, content = getNumber(content, 2) - EndFrame, content = getNumber(content, 2) - MaxInterpolationGap, content = getNumber(content, 2) - - Scale, content = getFloat(content,proctype) - - NrecordDataBlock, content = getNumber(content, 2) - NanalogFramesPerVideoFrame, content = getNumber(content, 2) - - if NanalogFramesPerVideoFrame > 0: - NanalogChannels=NanalogSamplesPerVideoFrame/NanalogFramesPerVideoFrame - else: - NanalogChannels=0 - - VideoFrameRate, content = getFloat(content,proctype) - - AnalogFrameRate=VideoFrameRate*NanalogFramesPerVideoFrame - NvideoFrames = EndFrame - StartFrame + 1 - - debug(0, "Scale= %0.2f" %Scale) - debug(0, "NanalogFramesPerVideoFrame= %i" %NanalogFramesPerVideoFrame) - debug(0, "Video Frame Rate= %i" %VideoFrameRate) - debug(0, "AnalogFrame Rate= %i"%AnalogFrameRate) - debug(0, "# markers= %i" %Nmarkers) - debug(0, "StartFrame= %i" %StartFrame) - debug(0, "EndFrame= %i" %EndFrame) - debug(0, "# Video Frames= %i" %NvideoFrames) - - if Scale>0: - debug(0, "Marker data is in integer format") - if Scale>(XYZ_LIMIT/32767): - Scale=XYZ_LIMIT/32767.0 - debug(0, "OVERRIDE: Max coordinate is %i, Scale changed to %0.2f" % (XYZ_LIMIT,Scale)) - else: debug(0, "Marker data is in floating point format") - if VideoFrameRate<1 or VideoFrameRate>120: - VideoFrameRate= 120 - debug(0, "OVERRIDE Video Frame Rate= %i" %VideoFrameRate) - if proctype not in (1,2): # Intel, DEC are known good - debug(0, "OVERRIDE|Program not tested with this encoding. Set to Intel") - proctype= 1 - - debug(10, "***********************") - debug(10, "**** Reading Events ...") - debug(10, "***********************") - - content = content_memory - content = content[298:] #bizarre .. ce devrait être 150 selon la doc rdw skips first 299 bytes? - - EventIndicator, content = getNumber(content, 2) - EventTime=[] - EventValue=[] - EventName=[] - - debug(0, "Event Indicator = %i" %EventIndicator) - if EventIndicator==12345: #rdw: somehow, this original code seems fishy, but I cannot deny it. - Nevents, content = getNumber(content, 2) - debug(0, "Nevents= %i" %Nevents) - content = content[2:] - if Nevents>0: - for i in range(Nevents): - letime, content = getFloat(content,proctype) - EventTime.append(letime) - content = content_memory - content = content[188*2:] - for i in range(Nevents): - lavalue, content = getNumber(content, 1) - EventValue.append(lavalue) - content = content_memory - content = content[198*2:] - for i in range(Nevents): - lenom = content[0:4] - content = content[4:] - EventName.append(lenom) - - debug(00, "***************************") - debug(00, "**** Reading Parameters ...") - debug(10, "***************************") - subjects=[] # a name would be nice, but human will do - prefixes=[] # added on to mocap marker names, one for each subject - marker_subjects = [] # hopefully will be specified in the file and known to this program - markerList=[] - ParameterGroups = [] - ParameterNumberIndex = [] - - content = content_memory - content = content[512*(NrecordFirstParameterblock-1):] - - dat1, content = getNumber(content, 1) - key2, content = getNumber(content, 1) - - NparameterRecords, content = getNumber(content, 1) - debug(100, "NparameterRecords=%i"%NparameterRecords) - proctype,content =getNumber(content,1) - proctype = proctype-83 # proctype: 1(INTEL-PC); 2(DEC-VAX); 3(MIPS-SUN/SGI) - - for i in range(NparameterRecords): - leparam = ParameterGroup(None, None, []) - ParameterGroups.append(leparam) - ParameterNumberIndex.append(0) - # - Ncharacters, content = getNumber(content, 1) - if Ncharacters>=128: - Ncharacters = -(2**8)+(Ncharacters) - GroupNumber, content = getNumber(content, 1) - if GroupNumber>=128: - GroupNumber = -(2**8)+(GroupNumber) - debug(80,"GroupNumber = %i, Nchar=%i" %(GroupNumber,Ncharacters)) - - while Ncharacters > 0: - if GroupNumber<0: - GroupNumber=abs(GroupNumber) - GroupName = content[0:Ncharacters] - content = content[Ncharacters:] - #print "Group Number = ", GroupNumber - ParameterGroups[GroupNumber].name = GroupName - #print "ParameterGroupName =", GroupName - offset, content = getNumber(content, 2) - deschars, content = getNumber(content, 1) - GroupDescription = content[0:deschars] - content = content[deschars:] - ParameterGroups[GroupNumber].description = GroupDescription - # - ParameterNumberIndex[GroupNumber]=0 - content = content[offset-3-deschars:] - else: - - ParameterNumberIndex[GroupNumber]=ParameterNumberIndex[GroupNumber]+1 - ParameterNumber=ParameterNumberIndex[GroupNumber] - #print "ParameterNumber=", ParameterNumber - ParameterGroups[GroupNumber].parameter.append(Parameter(None, None, [], [], None)) - ParameterName = content[0:Ncharacters] - content = content[Ncharacters:] - #print "ParameterName = ",ParameterName - if len(ParameterName)>0: - ParameterGroups[GroupNumber].parameter[ParameterNumber-1].name=ParameterName - offset, content = getNumber(content, 2) - filepos = len(content_memory)-len(content) - nextrec = filepos+offset-2 - - type, content=getNumber(content, 1) - if type>=128: - type = -(2**8)+type - ParameterGroups[GroupNumber].parameter[ParameterNumber-1].type=type - - dimnum, content=getNumber(content, 1) - if dimnum == 0: - datalength = abs(type) - else: - mult=1 - dimension=[] - for j in range (dimnum): - ladim, content = getNumber(content, 1) - dimension.append(ladim) - mult=mult*dimension[j] - ParameterGroups[GroupNumber].parameter[ParameterNumber-1].dim.append(dimension[j]) - datalength = abs(type)*mult - - #print "ParameterNumber = ", ParameterNumber, " Group Number = ", GroupNumber - - if type==-1: - data = "" - wordlength=dimension[0] - if dimnum==2 and datalength>0: - for j in range(dimension[1]): - data=string.rstrip(content[0:wordlength]) - content = content[wordlength:] - ParameterGroups[GroupNumber].parameter[ParameterNumber-1].data.append(data) - elif dimnum==1 and datalength>0: - data=content[0:wordlength] - ParameterGroups[GroupNumber].parameter[ParameterNumber-1].data.append(data) # ??? - - myParam=string.rstrip(ParameterName) - myGroup=string.rstrip(GroupName) - msg= "-%s-%s-" % (myGroup,myParam) - if myGroup == "POINT": - if myParam== "LABELS": - # named in form of subject:marker. - # the list "empties" is a corresponding list of actual empty object names that make up the cloud - markerList= ParameterGroups[GroupNumber].parameter[ParameterNumber-1].data - debug(0, "%sLABELS = %i %s" %(msg, len(markerList),markerList)) #list of logical markers from 0 to n corresponding to points - elif myParam== "LABELS2": #more labels - # named in form of subject:marker. - # the list "empties" is a corresponding list of actual empty object names that make up the cloud - momarkList= ParameterGroups[GroupNumber].parameter[ParameterNumber-1].data - markerList+=momarkList - debug(0, "%sLABELS2 = %i %s" %(msg, len(momarkList),momarkList)) #list of logical markers from 0 to n corresponding to points - else: debug(70, "%s UNUSED = %s" %(msg,ParameterGroups[GroupNumber].parameter[ParameterNumber-1].data)) - elif myGroup in ["SUBJECT", "SUBJECTS"]: #info about the actor - if myParam in ["NAME", "NAMES"]: - subjects= ParameterGroups[GroupNumber].parameter[ParameterNumber-1].data - debug(0, "%sNames of Subjects = %s" %(msg, subjects)) # might be useful in naming armatures - for i in range(len(subjects)): - subjects[i]=subjects[i].rstrip() - if subjects[i]=="": subjects[i]="Human" - elif myParam == "LABEL_PREFIXES": - prefixes = ParameterGroups[GroupNumber].parameter[ParameterNumber-1].data - debug(0, "%sMarker Prefixes = %s" %(msg, prefixes)) # to xlate marker name to that in file - for i in range(len(prefixes)): - prefixes[i]=prefixes[i].rstrip() - elif myParam== "MARKER_SETS": - marker_subjects= ParameterGroups[GroupNumber].parameter[ParameterNumber-1].data - debug(0, "%sMarker Set = %s"%(msg, marker_subjects)) # marker set that each subject was wearing - elif myParam== "MODEL_PARAM": - action= ParameterGroups[GroupNumber].parameter[ParameterNumber-1].data - debug(0, "%sModel Paramter = %s"%(msg,action)) # might be a good name for the blender scene - elif myParam== "LABELS": - # named in form of subject:marker. - # the list "empties" is a corresponding list of actual empty object names that make up the cloud - markerList= ParameterGroups[GroupNumber].parameter[ParameterNumber-1].data - debug(0, "%sLABELS = %i %s"%(msg, len(markerList),markerList)) #list of logical markers from 0 to n corresponding to points - else: debug(70, "%sUNUSED = %s"%(msg, ParameterGroups[GroupNumber].parameter[ParameterNumber-1].data)) - else: - debug(70, "%sUNUSED = %s"%(msg, ParameterGroups[GroupNumber].parameter[ParameterNumber-1].data)) - elif type == 1: - debug(100,"Block type %i is largely unsupported and untested."%type) - data = [] - Nparameters=datalength/abs(type) - debug(100, "Nparameters=%i"%Nparameters) - for i in range(Nparameters): - ladata,content = getNumber(content, 1) - data.append(ladata) - ParameterGroups[GroupNumber].parameter[ParameterNumber-1].data=data - #print ParameterGroups[GroupNumber].parameter[ParameterNumber-1].data - - #print "type boolean" - elif type == 2 and datalength>0: - debug(100,"Block type %i is largely unsupported and untested."%type) - data = [] - Nparameters=datalength/abs(type) - debug(100, "Nparameters=%i"%Nparameters) - for i in range(Nparameters): - ladata,content = getNumber(content, 2) - data.append(ladata) - #ParameterGroups[GroupNumber].parameter[ParameterNumber-1].data=data - if dimnum>1: - #???? print "arg je comprends pas" - ParameterGroups[GroupNumber].parameter[ParameterNumber-1].data=data - #???ParameterGroups[GroupNumber].parameter[ParameterNumber-1].data=reshape(data,dimension) - else: - ParameterGroups[GroupNumber].parameter[ParameterNumber-1].data=data - #print ParameterGroups[GroupNumber].parameter[ParameterNumber-1].data - #pass - #print "type integer" - elif type == 4 and datalength>0: - debug(100,"Block type %i is largely unsupported and untested."%type) - data = [] - Nparameters=datalength/abs(type) - debug(100, "Nparameters=%i"%Nparameters) - for i in range(Nparameters): - ladata,content = getFloat(content,proctype) - data.append(ladata) - if dimnum>1: - ParameterGroups[GroupNumber].parameter[ParameterNumber-1].data=data - #print "arg je comprends pas" - #???ParameterGroups[GroupNumber].parameter[ParameterNumber-1].data=reshape(data,dimension) - else: - ParameterGroups[GroupNumber].parameter[ParameterNumber-1].data=data - #print ParameterGroups[GroupNumber].parameter[ParameterNumber-1].data - else: - debug(100,"Block type %i is largely unsupported and untested."%type) - #print "error" - pass - deschars, content= getNumber(content, 1) - if deschars>0: - description = content[0:deschars] - content = content[deschars:] - ParameterGroups[GroupNumber].parameter[ParameterNumber-1].description=description - - content = content_memory - content = content[nextrec:] - - Ncharacters,content = getNumber(content, 1) - if Ncharacters>=128: - Ncharacters = -(2**8)+(Ncharacters) - GroupNumber,content = getNumber(content, 1) - if GroupNumber>=128: - GroupNumber = -(2**8)+(GroupNumber) - debug(80,"GroupNumber = %i, Nchar=%i" %(GroupNumber,Ncharacters)) - - debug(00, "***************************") - debug(00, "**** Examining Parameters ...") - debug(10, "***************************") - - if len(subjects)==0: subjects=["Test"] #well, somebody got mocapped! - for i in range(0, len(subjects)-len(prefixes)): prefixes.append("") - for i in range(0, len(subjects)-len(marker_subjects)): marker_subjects.append(subjects[i]) - - #make a markerlist if they didn't - debug(0, "%i Markers specified, %i marker names supplied" %(Nmarkers,len(markerList))) - if len(markerList)==0: - debug(0, "File missing any POINT LABELS marker list. Making defaults") - #I guess just make cloud of empty.xxx - if len(markerList)<Nmarkers: - for i in range(len(markerList),Nmarkers): markerList.append("mark."+str(i)) - #note that they may supply more markers than Nmarkers, extras are usually null or ignored - #an idea here to winnow down the marker List is to go through the nodes and see if there are markers - # in the list that are not used in constraining the armature, and discard them or set them debug(0, - # so that later on in processing we don't bother saving their location, possibly speeding up processing - # because we can just skip over their data block. - # put this on TODO list since it gets pretty complicated going throuch each marker set and all constraints etc. - - ## ############################################### - ## ## ## - ## ## Initalize Arrays and Allocate Memory - ## ## ## - ## ############################################### - ## Get the coordinate and analog data - # - - content = content_memory - content = content[(NrecordDataBlock-1)*512:] - debug(20,"Allocating memory for %i floats" %NvideoFrames*(Nmarkers*3+2)) - for i in range (NvideoFrames): - Markers.append([]) - ResidualError.append([]) - CameraInfo.append([]) - for j in range (Nmarkers): - Markers[i].append(Marker(0.0,0.0,0.0)) - ResidualError[i].append(0) - CameraInfo[i].append(0) - - #print Markers - # - #if Scale < 0 - # for i=1:NvideoFrames - # for j=1:Nmarkers - # Markers(i,j,1:3)=fread(fid,3,'float32')'; - # a=fix(fread(fid,1,'float32')); - # highbyte=fix(a/256); - # lowbyte=a-highbyte*256; - # CameraInfo(i,j)=highbyte; - # ResidualError(i,j)=lowbyte*abs(Scale); - # end - # waitbar(i/NvideoFrames) - # for j=1:NanalogFramesPerVideoFrame, - # AnalogSignals(j+NanalogFramesPerVideoFrame*(i-1),1:NanalogChannels)=... - # fread(fid,NanalogChannels,'int16')'; - # end - # end - - debug(10, "***************************") - debug(00, "**** Reading DataBlock of %i Frames...." % NvideoFrames) - debug(10, "***************************") - residuals= NanalogFramesPerVideoFrame*NanalogChannels*2 - err=0 #keep track of errors or serious data issues - ptr_read = 0 - - if Scale < 0.0: # 3D Data - 4-byte Floating-point Format - for i in range (NvideoFrames): - if i==0: start=sys.time() - elif i==10: - tmp=(sys.time()-start)*NvideoFrames/600 - debug(0,"%i minutes remaining..." % tmp) - else: print "%i percent complete. On Frame %i Points procesed: %i\r" % (i*100/NvideoFrames,i,i*Nmarkers), - for j in range (Nmarkers): - - x,ptr_read = parseFloat(content, ptr_read, proctype) - y,ptr_read = parseFloat(content, ptr_read, proctype) - z,ptr_read = parseFloat(content, ptr_read, proctype) - myx= x * -Scale - myy= y * -Scale - myz= z * -Scale - - if abs(myx)>XYZ_LIMIT or abs(myy)>XYZ_LIMIT or abs(myz)>XYZ_LIMIT: - err+=1 - if err>100: - debug(0, "Warning: 100 data points for markers seem way out there") - debug(0, "data read: (%i, %i, %i)" %(x,y,z)) - debug(0, "Consider revising Scale %0.2f" % Scale) - debug(0, "which now givs coordinates: (%i, %i, %i)" %(x*Scale,y*Scale,z*Scale)) - err=-0 - if abs(myx)>XYZ_LIMIT: myx= XYZ_LIMIT*myx/abs(myx) #preserve sign - if abs(myy)>XYZ_LIMIT: myy= XYZ_LIMIT*myy/abs(myy) #preserve sign - if abs(myz)>XYZ_LIMIT: myz= XYZ_LIMIT*myz/abs(myz) #preserve sign - Markers[i][j].x = myx - Markers[i][j].y = myy - Markers[i][j].z = myz - - a,ptr_read = parseFloat(content, ptr_read, proctype) - a = int(a) - highbyte = int(a/256) - lowbyte=a-highbyte*256 - CameraInfo[i][j] = highbyte - ResidualError[i][j] = lowbyte*abs(Scale) - #Monitor marker location to ensure data block is being parsed properly - if j==0: debug(90,"Frame %i loc of %s: (%i, %i, %i)" % (i,markerList[j],myx,myy,myz)) - if i==0: debug(50, "Initial loc of %s: (%i, %i, %i)" % (markerList[j],myx,myy,myz)) - - ptr_read+=residuals #skip over the following - #for j in range (NanalogFramesPerVideoFrame): - # for k in range(NanalogChannels): - # val, content = getNumber(content, 2) - # AnalogSignals[j+NanalogFramesPerVideoFrame*(i)][k]=val #??? i-1 - #else - # for i=1:NvideoFrames - # for j=1:Nmarkers - # Markers(i,j,1:3)=fread(fid,3,'int16')'.*Scale; - # ResidualError(i,j)=fread(fid,1,'int8'); - # CameraInfo(i,j)=fread(fid,1,'int8'); - # end - # waitbar(i/NvideoFrames) - # for j=1:NanalogFramesPerVideoFrame, - # AnalogSignals(j+NanalogFramesPerVideoFrame*(i-1),1:NanalogChannels)=... - # fread(fid,NanalogChannels,'int16')'; - # end - # end - #end - - else: #Scale is positive, but should be <1 to scale down, like 0.05 - two16= -2**16 - if len(content) < NvideoFrames*(Nmarkers*(6+2)+residuals): - error("%i bytes is not enough data for |%i frames|%i markers|%i residual" %(len(content),NvideoFrames,Nmarkers,residuals)) - #Note: I really tried to optimize this loop, since it was taking hours to process - for i in range(NvideoFrames): - if i==0: start=sys.time() - elif i==10: - tmp=(sys.time()-start)*NvideoFrames/600 - debug(0,"%i minutes remaining..." % tmp) - else: print "%i percent complete. On Frame %i Points procesed: %i\r" % (i*100/NvideoFrames,i,i*Nmarkers), - - for j in range(Nmarkers): - #x, content = getNumber(content,2) - # this is old skool signed int, not but not a short. - x = ord(content[ptr_read+0]) + (ord(content[ptr_read+1])<<8) - if x>32768: x+=two16 - y = ord(content[ptr_read+2]) + (ord(content[ptr_read+3])<<8) - if y>32768: y+=two16 - z = ord(content[ptr_read+4]) + (ord(content[ptr_read+5])<<8) - if z>32768: z+=two16 - -## -## x = ord(content[ptr_read]) + ord(content[ptr_read+1])*(2**8) -## ptr_read+=2 -## if x > 32768: -## x=-(2**16)+(x) -## #y, content = getNumber(content,2) -## y = ord(content[ptr_read]) + ord(content[ptr_read+1])*(2**8) -## ptr_read+=2 -## if y > 32768: -## y=-(2**16)+(y) -## #z, content = getNumber(content,2) -## z = ord(content[ptr_read]) + ord(content[ptr_read+1])*(2**8) -## ptr_read+=2 -## if z > 32768: -## z=-(2**16)+(z) -## -## print "(%i=%i, %i=%i, %i=%i)" %(x,myx,y,myy,z,myz) - - # for integers, I changed Scale above to avoid getting impossible numbers - Markers[i][j].x = x*Scale - Markers[i][j].y = y*Scale - Markers[i][j].z = z*Scale - -## ResidualError[i][j], content = getNumber(content, 1) -## CameraInfo[i][j], content = getNumber(content, 1) - #try to improve performance by: - ResidualError[i][j]= ord(content[ptr_read+6]) - CameraInfo[i][j]= ord(content[ptr_read+7]) - - content= content[ptr_read+8:] - ptr_read=0 - - if j==0: debug(100,"Frame %i loc of %s: %s" % (i,markerList[j],Markers[i][j])) - if i==0: debug(50, "Initial loc of %s: (%s)" % (markerList[j],Markers[i][j])) - - #for j in range (NanalogFramesPerVideoFrame): - # for k in range(NanalogChannels): - # val, content = getNumber(content, 2) - #AnalogSignals(j+NanalogFramesPerVideoFrame*(i-1),1:NanalogChannels)=val - ptr_read= residuals # skip over the above - print "\ndone with file." - fid.close() - - cloud= makeCloud(Nmarkers,markerList,StartFrame,EndFrame,Markers) - - setupAnim(StartFrame, EndFrame,VideoFrameRate) - - debug(10, "**************************") - debug(00, "**** Making %i Armatures" % len(subjects)) - debug(10, "**************************") - for i in range(len(subjects)): - marker_set= marker_subjects[i] - success=False - if len(marker_set)>0: - for trymark in MARKER_SETS: - if trymark[0:len(marker_set)]==marker_set: - marker_set=trymark - success=True - if success: - debug(0, "Armature for %s will be put on layers %s" % (subjects[i],LAYERS_ARMOB)) - debug(0, " based on an markers beginning with %s" % prefixes[i]) - ob= make_arm(subjects[i],prefixes[i],markerList,cloud,marker_set) - else: - debug(00, "Presently, this program can automatically create a constrained armature for marker sets %s" % MARKER_SETS) - debug(00, "%s uses an unknown marker set %s" % (subjects[i],marker_set)) - debug(10, "Have a nice day! If you figure out an armature node system for this cloud, please add it to the program.") - - debug(10, "**************************") - debug(00, "**** Conclusion") - minmax=[0,0,0,0,0,0] - for i in range(NvideoFrames): - for j in range(Nmarkers): - if minmax[0]>Markers[i][j].x: minmax[0]=Markers[i][j].x - if minmax[1]>Markers[i][j].y: minmax[1]=Markers[i][j].y - if minmax[2]>Markers[i][j].z: minmax[2]=Markers[i][j].z - if minmax[3]<Markers[i][j].x: minmax[3]=Markers[i][j].x - if minmax[4]<Markers[i][j].y: minmax[4]=Markers[i][j].y - if minmax[5]<Markers[i][j].z: minmax[5]=Markers[i][j].z - debug(0,"Markers move in 3D space from (%i,%i,%i) to (%i,%i,%i). "%(minmax[0],minmax[1],minmax[2],minmax[3],minmax[4],minmax[5])) - debug(0,"Set your 3D View Properties Clip End and zoom out your display.") -def my_callback(filename): - # processing options UI goes here, eventually - Window.WaitCursor(1) - t = sys.time() - load_c3d(filename) - # Timing the script is a good way to be aware on any speed hits when scripting - debug(0, '%s file processed in %.2f sec.' % (filename,sys.time()-t)) - Window.WaitCursor(0) - -def processFile(): - # select file and pass a handle to the processor - Blender.Window.FileSelector(my_callback, "Import C3D") # makes a window a file selector and processes it - #processing contiues while file is being worked - -def main(): - # Display the GUI - - # Run the function - processFile() - - #Close files, display stats, cleanup, advice on next steps - -# This lets you import the script without running it -if __name__ == '__main__': - debug(00, "------------------------------------") - debug(00, '%s %s script began at %.0f' % (__script__,__version__,sys.time())) - main() - - - diff --git a/release/scripts/camera_changer.py b/release/scripts/camera_changer.py deleted file mode 100644 index 7ae1bd64c8c..00000000000 --- a/release/scripts/camera_changer.py +++ /dev/null @@ -1,121 +0,0 @@ -#!BPY - -""" Registration info for Blender menus: <- these words are ignored -Name: 'Camera Changer' -Blender: 234 -Group: 'Animation' -Tip: 'Create script link to change cameras (based on their names) during an animation' -""" - -__author__ = '3R - R3gis' -__version__ = '1.2' -__url__ = ["Author's site , http://cybercreator.free.fr", "French Blender support forum, http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender"] -__email__=["3R, r3gis@free.fr"] - - -__bpydoc__ = """\ -This script creates an script link to change cameras during an animation. - -The created script link (a Blender Text) is linked to Scene Frame Changed events. - -Usage: - -Run the script, then name the camera Object with the number of the frame(s) -where you want this camera to become active. - -For example:<br> - - a camera called "10" will become active at frame 10.<br> - - a camera called "10,25,185" will become active at frames 10, 25 and 185. - -Notes:<br> - - This script creates another script named camera.py, which is linked to the current scene.<br> - - If there is already a text called "camera.py", but it's from an old version or is not recognized, -you can choose if you want to rename or overwrite it. - - Script inspired by Jean-Michel (jms) Soler's:<br> - http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_changerdecamera.htm -""" - - -# $Id$ -# -# -------------------------------------------------------------------------- -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Copyright (C) 2004-2005: Regis Montoya -# -# 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 ***** -# -------------------------------------------------------------------------- - -#Script inspired of the idea of this one : -#http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_changerdecamera.htm -# -#---------------------------------------------- -# R3gis Montoya (3R) -# -# Pout tout probleme a: -# cybercreator@free.fr -# --------------------------------------------- - -import Blender -from Blender import * -import string - -header = '# camera.py 1.3 scriptlink' - -camera_change_scriptlink = header + \ -''' -import Blender -def main(): - scn = Blender.Scene.GetCurrent() - frame = str(Blender.Get('curframe')) - - # change the camera if it has the current frame - for ob_cam in [ob for ob in scn.objects if ob.type == 'Camera']: - for number in ob_cam.name.split(','): - if number == frame: - scn.setCurrentCamera(ob_cam) - return -main() -''' - -def main(): - - # Get the text - try: cam_text = Blender.Text.Get('camera.py') - except: cam_text = None - - if cam_text: - if cam_text.asLines()[0] != header: - ret = Blender.Draw.PupMenu("WARNING: An old camera.py exists%t|Overwrite|Rename old version text") - if ret == -1: return # EXIT DO NOTHING - elif ret == 1: Text.unlink(cam_text) - elif ret == 2: cam_text.name = 'old_camera.txt' - cam_text = None - - if not cam_text: - scripting=Blender.Text.New('camera.py') - scripting.write(camera_change_scriptlink) - - scn=Scene.GetCurrent() - scriptlinks = scn.getScriptLinks('FrameChanged') - if not scriptlinks or ('camera.py' not in scriptlinks): - scn.addScriptLink('camera.py','FrameChanged') - Blender.Draw.PupMenu('FrameChange Scriptlink Added%t|Name camera objects to their activation frame numbers(s) seperated by commas|valid names are "1,10,46" or "1,10,200" or "200" (without quotation marks)') - Blender.Window.RedrawAll() - -if __name__ == '__main__': - main()
\ No newline at end of file diff --git a/release/scripts/config.py b/release/scripts/config.py deleted file mode 100644 index cbf8e272b91..00000000000 --- a/release/scripts/config.py +++ /dev/null @@ -1,801 +0,0 @@ -#!BPY - -""" -Name: 'Scripts Config Editor' -Blender: 236 -Group: 'System' -Tooltip: 'View and edit available scripts configuration data' -""" - -__author__ = "Willian P. Germano" -__version__ = "0.1 2005/04/14" -__email__ = ('scripts', 'Author, wgermano:ig*com*br') -__url__ = ('blender', 'blenderartists.org') - -__bpydoc__ ="""\ -This script can be used to view and edit configuration data stored -by other scripts. - -Technical: this data is saved as dictionary keys with the -Blender.Registry module functions. It is persistent while Blender is -running and, if the script's author chose to, is also saved to a file -in the scripts config data dir. - -Usage: - -- Start Screen: - -To access any available key, select it from (one of) the menu(s). - -Hotkeys:<br> - ESC or Q: [Q]uit<br> - H: [H]elp - -- Keys Config Screen: - -This screen exposes the configuration data for the chosen script key. If the -buttons don't fit completely on the screen, you can scroll up or down with -arrow keys or a mouse wheel. Leave the mouse pointer over any button to get -a tooltip about that option. - -Any change can be reverted -- unless you have already applied it. - -If the key is already stored in a config file, there will be a toggle button -(called 'file') that controls whether the changes will be written back to -the file or not. If you just want to change the configuration for the current -session, simply unset that button. Note, though, that data from files has -precedence over those keys already loaded in Blender, so if you re-run this -config editor, unsaved changes will not be seen. - -Hotkeys:<br> - ESC: back to Start Screen<br> - Q: [Q]uit<br> - U: [U]ndo changes<br> - ENTER: apply changes (can't be reverted, then)<br> - UP, DOWN Arrows and mouse wheel: scroll text up / down - -Notes: - -a) Available keys are determined by which scripts you use. If the key you -expect isn't available (or maybe there are none or too few keys), either the -related script doesn't need or still doesn't support this feature or the key -has not been stored yet, in which case you just need to run that script once -to make its config data available. - -b) There are two places where config data files can be saved: the -bpydata/config/ dir (1) inside the default scripts dir or (2) inside the user -defined Python scripts dir -(User Preferences window -> File Paths tab -> Python path). If available, -(2) is the default and also the recommended option, because then fresh Blender -installations won't delete your config data. To use this option, simply set a -dir for Python scripts at the User Preferences window and make sure this dir -has the subdirs bpydata/ and bpydata/config/ inside it. - -c) The key called "General" in the "Other" menu has general config options. -All scripts where that data is relevant are recommended to access it and set -behaviors accordingly. -""" - -# $Id$ -# -# -------------------------------------------------------------------------- -# config.py version 0.1 2005/04/08 -# -------------------------------------------------------------------------- -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Copyright (C) 2004: Willian P. Germano, wgermano _at_ ig.com.br -# -# 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 ***** -# -------------------------------------------------------------------------- - -import Blender -from Blender import Draw, BGL, Registry, Window, sys as bsys -from Blender.Window import Theme -from BPyRegistry import LoadConfigData, SaveConfigData, HasConfigData,\ - BPY_KEY_IN_FILE - -MAX_STR_LEN = 300 # max length for a string -MAX_ITEMS_NUM = 100 # max number for each type of button - -# --- -# The "General" configure options key is managed from this script. -verbose = True -confirm_overwrite = True - -tooltips = { - 'verbose': 'print script messages (info, warnings, errors) to the console', - 'confirm_overwrite': 'scripts should always confirm before overwriting files' -} - -CFG_LIST = ['verbose', 'confirm_overwrite', 'tooltips'] -KEY_NAME = 'General' - -def update_registry(): - rd = {} - for var in CFG_LIST: - exec("rd['%s']=%s" % (var, var)) - Registry.SetKey(KEY_NAME, rd, True) - -rd = Registry.GetKey('General', True) -if rd: - try: - for var in CFG_LIST[:-1]: # no need to update tooltips - exec("%s=rd['%s']" % (var, var)) - except: update_registry() - -else: - update_registry() -# --- - -# script globals: -CFGKEY = '' -LABELS = [] -GD = {} # groups dict (includes "Other" for unmapped keys) -INDEX = 0 # to pass button indices to fs callbacks -FREEKEY_IDX = 0 # index of set of keys not mapped to a script name -KEYMENUS = [] -ALL_SCRIPTS = {} -ALL_GROUPS = [] -START_SCREEN = 0 -CONFIG_SCREEN = 1 -DISK_UPDATE = True # write changed data to its config file - -ACCEPTED_TYPES = [bool, int, float, str, unicode] - -SCREEN = START_SCREEN - -SCROLL_DOWN = 0 - -# events: -BEVT_START = 50 -BEVT_EXIT = 0 + BEVT_START -BEVT_BACK = 1 + BEVT_START -BEVT_DISK = 2 + BEVT_START -BEVT_CANCEL = 3 + BEVT_START -BEVT_APPLY = 4 + BEVT_START -BEVT_HELP = 5 + BEVT_START -BEVT_DEL = 6 + BEVT_START -BEVT_KEYMENU = [] -BUT_KEYMENU = [] -BEVT_BOOL = 100 -BEVT_INT = BEVT_BOOL + MAX_ITEMS_NUM -BEVT_FLOAT = BEVT_BOOL + 2*MAX_ITEMS_NUM -BEVT_STR = BEVT_BOOL + 3*MAX_ITEMS_NUM -BEVT_BROWSEDIR = BEVT_BOOL + 4*MAX_ITEMS_NUM -BEVT_BROWSEFILE = BEVT_BOOL + 5*MAX_ITEMS_NUM -BUT_TYPES = { - bool: 0, - int: 0, - float: 0, - str: 0 -} - -# Function definitions: - -def get_keys(): - LoadConfigData() # loads all data from files in (u)scripts/bpydata/config/ - return [k for k in Registry.Keys() if k[0] != "_"] - - -def show_help(script = 'config.py'): - Blender.ShowHelp(script) - - -def fs_dir_callback(pathname): - global CFGKEY, INDEX - - pathname = bsys.dirname(pathname) - datatypes = CFGKEY.sorteddata - datatypes[str][INDEX][1] = pathname - - -def fs_file_callback(pathname): - global CFGKEY, INDEX - - datatypes = CFGKEY.sorteddata - datatypes[str][INDEX][1] = pathname - - -# parse Bpymenus file to get all script filenames -# (used to show help for a given key) -def fill_scripts_dict(): - global ALL_SCRIPTS, ALL_GROUPS - - group = '' - group_len = 0 - sep = bsys.sep - home = Blender.Get('homedir') - if not home: - errmsg = """ -Can't find Blender's home dir and so can't find the -Bpymenus file automatically stored inside it, which -is needed by this script. Please run the -Help -> System -> System Information script to get -information about how to fix this. -""" - raise SystemError, errmsg - fname = bsys.join(home, 'Bpymenus') - if not bsys.exists(fname): return False - f = file(fname, 'r') - lines = f.readlines() - f.close() - for l in lines: - if l.rfind('{') > 0: - group = l.split()[0] - ALL_GROUPS.append(group) - group_len += 1 - continue - elif l[0] != "'": continue - fields = l.split("'") - if len(fields) > 2: - menuname = fields[1].replace('...','') - fields = fields[2].split() - if len(fields) > 1: - fname = fields[1].split(sep)[-1] - i = 1 - while not fname.endswith('.py'): - i += 1 - fname = "%s %s" % (fname, fields[i]) - ALL_SCRIPTS[fname] = (menuname, group_len - 1) - return True - - -def map_to_registered_script(name): - global ALL_SCRIPTS - - if not name.endswith('.py'): - name = "%s.py" % name - if ALL_SCRIPTS.has_key(name): - return ALL_SCRIPTS[name] # == (menuname, group index) - return None - - -def reset(): - global LABELS, GD, KEYMENUS, KEYS - - # init_data is recalled when a key is deleted, so: - LABELS = [] - GD = {} - KEYMENUS = [] - KEYS = get_keys() - - -# gather all script info, fill gui menus -def init_data(): - global KEYS, GD, ALL_GROUPS, ALL_SCRIPTS, KEYMENUS, LABELS - global BUT_KEYMENU, BEVT_KEYMENU, FREEKEY_IDX - - for k in ALL_GROUPS: - GD[k] = [] - GD[None] = [] - - for k in KEYS: - res = map_to_registered_script(k) - if res: - GD[ALL_GROUPS[res[1]]].append((k, res[0])) - else: GD[None].append((k, k)) - - for k in GD.keys(): - if not GD[k]: GD.pop(k) - - if GD.has_key(None): - GD['Other'] = GD[None] - GD.pop(None) - FREEKEY_IDX = -1 - - BUT_KEYMENU = range(len(GD)) - - for k in GD.keys(): - kmenu = ['Configuration Keys: %s%%t' % k] - for j in GD[k]: - kmenu.append(j[1]) - kmenu = "|".join(kmenu) - KEYMENUS.append(kmenu) - LABELS.append(k) - - if FREEKEY_IDX < 0: - FREEKEY_IDX = LABELS.index('Other') - - length = len(KEYMENUS) - BEVT_KEYMENU = range(1, length + 1) - BUT_KEYMENU = range(length) - - -# for theme colors: -def float_colors(cols): - return map(lambda x: x / 255.0, cols) - - - -class Config: - - def __init__(self, key, has_group = True): - global DISK_UPDATE - - self.key = key - self.has_group = has_group - self.name = key - self.fromdisk = HasConfigData(key) & BPY_KEY_IN_FILE - if not self.fromdisk: DISK_UPDATE = False - else: DISK_UPDATE = True - - self.origdata = Registry.GetKey(key, True) - data = self.data = self.origdata.copy() - - if not data: - Draw.PupMenu('ERROR: couldn\'t find requested data') - self.data = None - return - - keys = data.keys() - nd = {} - for k in keys: - nd[k.lower()] = k - - if nd.has_key('tooltips'): - ndval = nd['tooltips'] - self.tips = data[ndval] - data.pop(ndval) - else: self.tips = 0 - - if nd.has_key('limits'): - ndval = nd['limits'] - self.limits = data[ndval] - data.pop(ndval) - else: self.limits = 0 - - if self.has_group: - scriptname = key - if not scriptname.endswith('.py'): - scriptname = "%s.py" % scriptname - elif nd.has_key('script'): - ndval = nd['script'] - scriptname = data[ndval] - data.pop(ndval) - if not scriptname.endswith('.py'): - scriptname = "%s.py" % scriptname - else: scriptname = None - - self.scriptname = scriptname - - self.sort() - - - def needs_update(self): # check if user changed data - data = self.data - new = self.sorteddata - - for vartype in new.keys(): - for i in new[vartype]: - if data[i[0]] != i[1]: return 1 - - return 0 # no changes - - - def update(self): # update original key - global DISK_UPDATE - - data = self.data - odata = self.origdata - new = self.sorteddata - for vartype in new.keys(): - for i in new[vartype]: - if data[i[0]] != i[1]: data[i[0]] = i[1] - if odata[i[0]] != i[1]: odata[i[0]] = i[1] - - if DISK_UPDATE: Registry.SetKey(self.key, odata, True) - - def delete(self): - global DISK_UPDATE - - delmsg = 'OK?%t|Delete key from memory' - if DISK_UPDATE: - delmsg = "%s and from disk" % delmsg - if Draw.PupMenu(delmsg) == 1: - Registry.RemoveKey(self.key, DISK_UPDATE) - return True - - return False - - - def revert(self): # revert to original key - data = self.data - new = self.sorteddata - for vartype in new.keys(): - for i in new[vartype]: - if data[i[0]] != i[1]: i[1] = data[i[0]] - - - def sort(self): # create a new dict with types as keys - global ACCEPTED_TYPES, BUT_TYPES - - data = self.data - datatypes = {} - keys = [k for k in data.keys() if k[0] != '_'] - for k in keys: - val = data[k] - tval = type(val) - if tval not in ACCEPTED_TYPES: continue - if not datatypes.has_key(tval): - datatypes[tval] = [] - datatypes[type(val)].append([k, val]) - if datatypes.has_key(unicode): - if not datatypes.has_key(str): datatypes[str] = datatypes[unicode] - else: - for i in datatypes[unicode]: datatypes[str].append(i) - datatypes.pop(unicode) - for k in datatypes.keys(): - dk = datatypes[k] - dk.sort() - dk.reverse() - BUT_TYPES[k] = range(len(dk)) - self.sorteddata = datatypes - - -# GUI: - -# gui callbacks: - -def gui(): # drawing the screen - - global SCREEN, START_SCREEN, CONFIG_SCREEN, KEYMENUS, LABELS - global BEVT_KEYMENU, BUT_KEYMENU, CFGKEY - global BUT_TYPES, SCROLL_DOWN, VARS_NUM - - WIDTH, HEIGHT = Window.GetAreaSize() - - theme = Theme.Get()[0] - tui = theme.get('ui') - ttxt = theme.get('text') - - COL_BG = float_colors(ttxt.back) - COL_TXT = ttxt.text - COL_TXTHI = ttxt.text_hi - - BGL.glClearColor(COL_BG[0],COL_BG[1],COL_BG[2],COL_BG[3]) - BGL.glClear(BGL.GL_COLOR_BUFFER_BIT) - BGL.glColor3ub(COL_TXT[0],COL_TXT[1], COL_TXT[2]) - - if SCREEN == START_SCREEN: - x = 10 - y = 10 - h = 20 - w = 90 - BGL.glRasterPos2i(x, y) - Draw.Text('Select a configuration key to access it. Press Q or ESC to leave.') - km_len = len(KEYMENUS) - km_columns = (WIDTH - x) / w - if km_columns == 0: km_rows = km_len - else: - km_rows = km_len / km_columns - if (km_len % km_columns): km_rows += 1 - if km_rows == 0: km_rows = 1 - ystart = y + 2*h*km_rows - if ystart > (HEIGHT - 70): ystart = HEIGHT - 70 - y = ystart - column = 1 - for i, km in enumerate(KEYMENUS): - column += 1 - BGL.glRasterPos2i(x + 2, y + h + 5) - Draw.Text(LABELS[i]) - BUT_KEYMENU[i] = Draw.Menu(km, BEVT_KEYMENU[i], - x, y, w - 10, h, 0, 'Choose a key to access its configuration data') - if column > km_columns: - column = 1 - y -= 2*h - if y < 35: break - x = 10 - else: x += w - x = 10 - y = 50 + ystart - BGL.glColor3ub(COL_TXTHI[0], COL_TXTHI[1], COL_TXTHI[2]) - BGL.glRasterPos2i(x, y) - Draw.Text('Scripts Configuration Editor') - Draw.PushButton('help', BEVT_HELP, x, 22, 45, 16, - 'View help information about this script (hotkey: H)') - - elif SCREEN == CONFIG_SCREEN: - x = y = 10 - h = 18 - data = CFGKEY.sorteddata - tips = CFGKEY.tips - fromdisk = CFGKEY.fromdisk - limits = CFGKEY.limits - VARS_NUM = 0 - for k in data.keys(): - VARS_NUM += len(data[k]) - lines = VARS_NUM + 5 # to account for header and footer - y = lines*h - if y > HEIGHT - 20: y = HEIGHT - 20 - BGL.glColor3ub(COL_TXTHI[0],COL_TXTHI[1], COL_TXTHI[2]) - BGL.glRasterPos2i(x, y) - Draw.Text('Scripts Configuration Editor') - y -= 20 - BGL.glColor3ub(COL_TXT[0],COL_TXT[1], COL_TXT[2]) - txtsize = 10 - if HEIGHT < lines*h: - BGL.glRasterPos2i(10, 5) - txtsize += Draw.Text('Arrow keys or mouse wheel to scroll, ') - BGL.glRasterPos2i(txtsize, 5) - Draw.Text('Q or ESC to return.') - BGL.glRasterPos2i(x, y) - Draw.Text('Key: "%s"' % CFGKEY.name) - bh = 16 - bw = 45 - by = 16 - i = -1 - if CFGKEY.scriptname: - i = 0 - Draw.PushButton('help', BEVT_HELP, x, by, bw, bh, - 'Show documentation for the script that owns this key (hotkey: H)') - Draw.PushButton('back', BEVT_BACK, x + (1+i)*bw, by, bw, bh, - 'Back to config keys selection screen (hotkey: ESC)') - Draw.PushButton('exit', BEVT_EXIT, x + (2+i)*bw, by, bw, bh, - 'Exit from Scripts Config Editor (hotkey: Q)') - Draw.PushButton('revert', BEVT_CANCEL, x + (3+i)*bw, by, bw, bh, - 'Revert data to original values (hotkey: U)') - Draw.PushButton('apply', BEVT_APPLY, x + (4+i)*bw, by, bw, bh, - 'Apply changes, if any (hotkey: ENTER)') - delmsg = 'Delete this data key from memory' - if fromdisk: delmsg = "%s and from disk" % delmsg - Draw.PushButton('delete', BEVT_DEL, x + (5+i)*bw, by, bw, bh, - '%s (hotkey: DELETE)' % delmsg) - if fromdisk: - Draw.Toggle("file", BEVT_DISK, x + 3 + (6+i)*bw, by, bw, bh, DISK_UPDATE, - 'Update also the file where this config key is stored') - i = -1 - top = -1 - y -= 20 - yend = 30 - if data.has_key(bool) and y > 0: - lst = data[bool] - for l in lst: - top += 1 - i += 1 - if top < SCROLL_DOWN: continue - y -= h - if y < yend: break - w = 20 - tog = data[bool][i][1] - if tips and tips.has_key(l[0]): tooltip = tips[l[0]] - else: tooltip = "click to toggle" - BUT_TYPES[bool][i] = Draw.Toggle("", BEVT_BOOL + i, - x, y, w, h, tog, tooltip) - BGL.glRasterPos2i(x + w + 3, y + 5) - Draw.Text(l[0].lower().replace('_', ' ')) - i = -1 - y -= 5 - if data.has_key(int) and y > 0: - lst = data[int] - for l in lst: - w = 70 - top += 1 - i += 1 - if top < SCROLL_DOWN: continue - y -= h - if y < yend: break - val = data[int][i][1] - if limits: min, max = limits[l[0]] - else: min, max = 0, 10 - if tips and tips.has_key(l[0]): tooltip = tips[l[0]] - else: tooltip = "click / drag to change" - BUT_TYPES[int][i] = Draw.Number("", BEVT_INT + i, - x, y, w, h, val, min, max, tooltip) - BGL.glRasterPos2i(x + w + 3, y + 3) - Draw.Text(l[0].lower().replace('_', ' ')) - i = -1 - y -= 5 - if data.has_key(float) and y > 0: - lst = data[float] - for l in lst: - w = 70 - top += 1 - i += 1 - if top < SCROLL_DOWN: continue - y -= h - if y < yend: break - val = data[float][i][1] - if limits: min, max = limits[l[0]] - else: min, max = 0.0, 1.0 - if tips and tips.has_key(l[0]): tooltip = tips[l[0]] - else: tooltip = "click and drag to change" - BUT_TYPES[float][i] = Draw.Number("", BEVT_FLOAT + i, - x, y, w, h, val, min, max, tooltip) - BGL.glRasterPos2i(x + w + 3, y + 3) - Draw.Text(l[0].lower().replace('_', ' ')) - i = -1 - y -= 5 - if data.has_key(str) and y > 0: - lst = data[str] - for l in lst: - top += 1 - i += 1 - if top < SCROLL_DOWN: continue - y -= h - if y < yend: break - name = l[0].lower() - is_dir = is_file = False - if name.find('_dir', -4) > 0: is_dir = True - elif name.find('_file', -5) > 0: is_file = True - w = WIDTH - 20 - wbrowse = 50 - if is_dir and w > wbrowse: w -= wbrowse - if tips and tips.has_key(l[0]): tooltip = tips[l[0]] - else: tooltip = "click to write a new string" - name = name.replace('_',' ') + ': ' - if len(l[1]) > MAX_STR_LEN: - l[1] = l[1][:MAX_STR_LEN] - BUT_TYPES[str][i] = Draw.String(name, BEVT_STR + i, - x, y, w, h, l[1], MAX_STR_LEN, tooltip) - if is_dir: - Draw.PushButton('browse', BEVT_BROWSEDIR + i, x+w+1, y, wbrowse, h, - 'click to open a file selector (pick any file in the desired dir)') - elif is_file: - Draw.PushButton('browse', BEVT_BROWSEFILE + i, x + w + 1, y, 50, h, - 'click to open a file selector') - - -def fit_scroll(): - global SCROLL_DOWN, VARS_NUM - max = VARS_NUM - 1 # so last item is always visible - if SCROLL_DOWN > max: - SCROLL_DOWN = max - elif SCROLL_DOWN < 0: - SCROLL_DOWN = 0 - - -def event(evt, val): # input events - - global SCREEN, START_SCREEN, CONFIG_SCREEN - global SCROLL_DOWN, CFGKEY - - if not val: return - - if evt == Draw.ESCKEY: - if SCREEN == START_SCREEN: Draw.Exit() - else: - if CFGKEY.needs_update(): - if Draw.PupMenu('UPDATE?%t|Data was changed') == 1: - CFGKEY.update() - SCREEN = START_SCREEN - SCROLL_DOWN = 0 - Draw.Redraw() - return - elif evt == Draw.QKEY: - if SCREEN == CONFIG_SCREEN and CFGKEY.needs_update(): - if Draw.PupMenu('UPDATE?%t|Data was changed') == 1: - CFGKEY.update() - Draw.Exit() - return - elif evt == Draw.HKEY: - if SCREEN == START_SCREEN: show_help() - elif CFGKEY.scriptname: show_help(CFGKEY.scriptname) - return - - elif SCREEN == CONFIG_SCREEN: - if evt in [Draw.DOWNARROWKEY, Draw.WHEELDOWNMOUSE]: - SCROLL_DOWN += 1 - fit_scroll() - elif evt in [Draw.UPARROWKEY, Draw.WHEELUPMOUSE]: - SCROLL_DOWN -= 1 - fit_scroll() - elif evt == Draw.UKEY: - if CFGKEY.needs_update(): - CFGKEY.revert() - elif evt == Draw.RETKEY or evt == Draw.PADENTER: - if CFGKEY.needs_update(): - CFGKEY.update() - elif evt == Draw.DELKEY: - if CFGKEY.delete(): - reset() - init_data() - SCREEN = START_SCREEN - SCROLL_DOWN = 0 - else: return - Draw.Redraw() - - -def button_event(evt): # gui button events - - global SCREEN, START_SCREEN, CONFIG_SCREEN, CFGKEY, DISK_UPDATE - global BEVT_KEYMENU, BUT_KEYMENU, BUT_TYPES, SCROLL_DOWN, GD, INDEX - global BEVT_EXIT, BEVT_BACK, BEVT_APPLY, BEVT_CANCEL, BEVT_HELP, FREEKEY_IDX - - if SCREEN == START_SCREEN: - for e in BEVT_KEYMENU: - if evt == e: - index = e - 1 - k = BUT_KEYMENU[index].val - 1 - CFGKEY = Config(GD[LABELS[index]][k][0], index != FREEKEY_IDX) - if CFGKEY.data: - SCREEN = CONFIG_SCREEN - Draw.Redraw() - return - if evt == BEVT_EXIT: - Draw.Exit() - elif evt == BEVT_HELP: - show_help() - return - - elif SCREEN == CONFIG_SCREEN: - datatypes = CFGKEY.sorteddata - if evt >= BEVT_BROWSEFILE: - INDEX = evt - BEVT_BROWSEFILE - Window.FileSelector(fs_file_callback, 'Choose file') - elif evt >= BEVT_BROWSEDIR: - INDEX = evt - BEVT_BROWSEDIR - Window.FileSelector(fs_dir_callback, 'Choose any file') - elif evt >= BEVT_STR: - var = BUT_TYPES[str][evt - BEVT_STR].val - datatypes[str][evt - BEVT_STR][1] = var - elif evt >= BEVT_FLOAT: - var = BUT_TYPES[float][evt - BEVT_FLOAT].val - datatypes[float][evt - BEVT_FLOAT][1] = var - elif evt >= BEVT_INT: - var = BUT_TYPES[int][evt - BEVT_INT].val - datatypes[int][evt - BEVT_INT][1] = var - elif evt >= BEVT_BOOL: - var = datatypes[bool][evt - BEVT_BOOL][1] - if var == True: var = False - else: var = True - datatypes[bool][evt - BEVT_BOOL][1] = var - - elif evt == BEVT_BACK: - if SCREEN == CONFIG_SCREEN: - SCREEN = START_SCREEN - SCROLL_DOWN = 0 - Draw.Redraw() - elif evt == BEVT_EXIT: - if CFGKEY.needs_update(): - if Draw.PupMenu('UPDATE?%t|Data was changed') == 1: - CFGKEY.update() - Draw.Exit() - return - elif evt == BEVT_APPLY: - if CFGKEY.needs_update(): - CFGKEY.update() - elif evt == BEVT_CANCEL: - if CFGKEY.needs_update(): - CFGKEY.revert() - elif evt == BEVT_DEL: - if CFGKEY.delete(): - reset() - init_data() - SCREEN = START_SCREEN - SCROLL_DOWN = 0 - elif evt == BEVT_DISK: - if DISK_UPDATE: DISK_UPDATE = False - else: DISK_UPDATE = True - elif evt == BEVT_HELP: - show_help(CFGKEY.scriptname) - return - else: - return - Draw.Redraw() - -# End of definitions - - -KEYS = get_keys() - -if not KEYS: - Draw.PupMenu("NO DATA: please read this help screen") - Blender.ShowHelp('config.py') -else: - fill_scripts_dict() - init_data() - Draw.Register(gui, event, button_event) diff --git a/release/scripts/console.py b/release/scripts/console.py deleted file mode 100644 index c6ae22a86f5..00000000000 --- a/release/scripts/console.py +++ /dev/null @@ -1,861 +0,0 @@ -#!BPY - -""" -Name: 'Interactive Python Console' -Blender: 245 -Group: 'System' -Tooltip: 'Interactive Python Console' -""" - -__author__ = "Campbell Barton aka ideasman42" -__url__ = ["www.blender.org", "blenderartists.org", "www.python.org"] -__bpydoc__ = """\ -This is an interactive console, similar to Python's own command line interpreter. Since it is embedded in Blender, it has access to all Blender Python modules. - -Those completely new to Python are recommended to check the link button above -that points to its official homepage, with news, downloads and documentation. - -Usage:<br> - Type your code and hit "Enter" to get it executed.<br> - - Right mouse click: Console Menu (Save output, etc);<br> - - Mousewheel: Scroll text - - Arrow keys: command history and cursor;<br> - - Shift + Backspace: Backspace whole word;<br> - - Shift + Arrow keys: jump words;<br> - - Ctrl + (+/- or mousewheel): Zoom text size;<br> - - Ctrl + Enter: auto compleate based on variable names and modules loaded -- multiple choices popup a menu;<br> - - Shift + Enter: multiline functions -- delays executing code until only Enter is pressed. -""" - -# -------------------------------------------------------------------------- -# ***** 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 ***** -# -------------------------------------------------------------------------- - -import Blender -import bpy -from Blender import * -import sys as python_sys -import StringIO - -# Constants -__DELIMETERS__ = '. ,=+-*/%<>&~][{}():\t' -__VARIABLE_DELIMETERS__ = ' ,=+-*/%<>&~{}():\t' - -__LINE_HISTORY__ = 500 - -global __FONT_SIZE__ - -__FONT_SIZES__ = ( ('tiny', 10), ('small', 12), ('normalfix', 14), ('large', 16) ) -__FONT_SIZE__ = 2 # index for the list above, normal default. - -global __CONSOLE_LINE_OFFSET__ -__CONSOLE_LINE_OFFSET__ = 0 - -cmdBuffer = [] # dosnt need to be global - -''' -# Generic Blender functions -def getActScriptWinRect(): - area = Window.GetAreaSize() - area = (area[0]-1, area[1]-1) - for scrInfo in Window.GetScreenInfo(Window.Types['SCRIPT'], 'win', ''): - if scrInfo['vertices'][2]-scrInfo['vertices'][0] == area[0]: - if scrInfo['vertices'][3]-scrInfo['vertices'][1] == area[1]: - return scrInfo['vertices'] - return None -''' - - -# menuText, # per group -def PupMenuLess(menu, groupSize=35): - more = [' more...'] - less = [' less...'] - - menuList= menu.split('|') - - # No Less Needed, just call. - if len(menuList) < groupSize: - return Draw.PupMenu(menu) - - title = menuList[0].split('%t')[0] - - # Split the list into groups - menuGroups = [[]] - for li in menuList[1:]: - if len(menuGroups[-1]) < groupSize: - menuGroups[-1].append(li) - else: - menuGroups.append([li]) - - # Stores teh current menu group we are looking at - groupIdx = 0 - while 1: - # Give us a title with the menu number - numTitle = [ ' '.join([title, str(groupIdx + 1), 'of', str(len(menuGroups)), '%t'])] - if groupIdx == 0: - menuString = '|'.join(numTitle + menuGroups[groupIdx] + more) - elif groupIdx == len(menuGroups)-1: - menuString = '|'.join(numTitle + less + menuGroups[groupIdx]) - else: # In the middle somewhere so Show a more and less - menuString = '|'.join(numTitle + less + menuGroups[groupIdx] + more) - result = Draw.PupMenu(menuString) - # User Exit - if result == -1: - return -1 - - if groupIdx == 0: # First menu - if result-1 < groupSize: - return result - else: # must be more - groupIdx +=1 - elif groupIdx == len(menuGroups): # Last Menu - if result == 1: # Must be less - groupIdx -= 1 - else: # Must be a choice - return result + (groupIdx*groupSize) - - else: - if result == 1: # Must be less - groupIdx -= 1 - elif result-2 == groupSize: - groupIdx +=1 - else: - return result - 1 + (groupIdx*groupSize) - - - -# Use newstyle classes, Im not bothering with inheretence -# but slots are faster. -class cmdLine(object): - __slots__ = [\ - 'cmd', # is the command string, or any other message - 'type',# type: 0:user input 1:program feedback 2:error message. 3:option feedback - 'exe' # 0- not yet executed 1:executed - ] - def __init__(self, cmd, type, exe): - self.cmd = cmd - self.type = type - self.exe = exe - -# Include external file with internal namespace -def include(filename): - file = open(filename, 'r') - filedata = file.read() - file.close() - return compile(filedata, filename, 'exec') - -# Writes command line data to a blender text file. -def writeCmdData(type): - newText = Text.New('command_output.py', 1) - if type == 3: newText.write('\n'.join( [ myCmd.cmd for myCmd in cmdBuffer ] )) - else: newText.write('\n'.join( [ myCmd.cmd for myCmd in cmdBuffer if myCmd.type is type] )) - Draw.PupMenu('%s written' % newText.name) - -def insertCmdData(): - texts = list(bpy.data.texts) - textNames = [tex.name for tex in texts] - if textNames: - choice = Draw.PupMenu('|'.join(textNames)) - if choice != -1: - text = texts[choice-1] - - # Add the text! - for l in text.asLines(): - cmdBuffer.append(cmdLine('%s ' % l, 0, 0)) - Draw.Redraw() - - -COLLECTED_VAR_NAMES = {} # a list of keys, each key has a list of absolute paths - -# Pain and simple recursice dir(), accepts a string -unused_types = str, dict, list, float, int, str, type, tuple, type(dir), type(None) -def rdir(dirString, depth=0): - #print ' ' * depth, dirString - # MAX DEPTH SET HERE - if depth > 5: - # print 'maxdepoth reached.' - return - - global COLLECTED_VAR_NAMES - dirStringSplit = dirString.split('.') - - exec('value=' + dirString) - - if type(value) in unused_types: - # print 'bad type' - return - dirList = dir(value) - - for dirItem in dirList: - if dirItem.startswith('_'): - continue - - dirData = None - try: - # Rare cases this can mess up, material.shader was a problem. - exec('dirData = %s.%s' % (dirString, dirItem)) - #print dirData - except: - # Dont bother with this data. - continue - #print 'HEY', dirData, dirItem - #if type(dirItem) != str: - # print dirItem, type(dirItem) - - if dirItem not in COLLECTED_VAR_NAMES: # .keys() - COLLECTED_VAR_NAMES[dirItem] = [] - - # Add the string - # splitD = dirString.split('"')[-2] - - # Example of dirString - # __CONSOLE_VAR_DICT__["Main"].scenes.active.render - - # Works but can be faster - # splitD = dirString.replace('__CONSOLE_VAR_DICT__["', '').replace('"]', '') - - splitD = dirString[22:].replace('"]', '') - - if splitD not in COLLECTED_VAR_NAMES[dirItem]: - # print dirItem, dirString, splitD, - COLLECTED_VAR_NAMES[dirItem].append(splitD) - - - # Stops recursice stuff, overlooping - #print type(dirItem) - #if type(dirData) == types.ClassType or \ - # type(dirData) == types.ModuleType: - type_dirData = type(dirData) - if type_dirData not in unused_types: - # print type(dirData), dirItem - # Dont loop up dirs for strings ints etc. - if dirItem not in dirStringSplit: - rdir( '%s.%s' % (dirString, dirItem), depth+1) - ''' - elif depth == 0: # Add local variables - # print type(dirData), dirItem - # Dont loop up dirs for strings ints etc. - if dirItem not in dirStringSplit: - rdir( '%s.%s' % (dirString, dirItem), depth+1) - ''' - -def recursive_dir(): - global COLLECTED_VAR_NAMES - - for name in __CONSOLE_VAR_DICT__: # .keys() - if not name.startswith('_'): # Dont pick names like __name__ - rdir('__CONSOLE_VAR_DICT__["%s"]' % name) - #print COLLECTED_VAR_NAMES - COLLECTED_VAR_NAMES[name] = [''] - return COLLECTED_VAR_NAMES - -# Runs the code line(s) the user has entered and handle errors -# As well as feeding back the output into the blender window. -def runUserCode(__USER_CODE_STRING__): - global __CONSOLE_VAR_DICT__ # We manipulate the variables here. loading and saving from localspace to this global var. - - # Open A File like object to write all output to, that would useually be printed. - python_sys.stdout.flush() # Get rid of whatever came before - __FILE_LIKE_STRING__ = StringIO.StringIO() # make a new file like string, this saves up from making a file. - __STD_OUTPUT__ = python_sys.stdout # we need to store the normal output. - python_sys.stdout=__FILE_LIKE_STRING__ # Now anything printed will be written to the file like string. - - # Try and run the user entered line(s) - try: - # Load all variabls from global dict to local space. - __TMP_VAR_NAME__ = __TMP_VAR__ = '' # so as not to raise an error when del'ing - - for __TMP_VAR_NAME__, __TMP_VAR__ in __CONSOLE_VAR_DICT__.items(): - exec('%s%s' % (__TMP_VAR_NAME__,'=__TMP_VAR__')) - del __TMP_VAR_NAME__ - del __TMP_VAR__ - - # Now all the vars are loaded, execute the code. # Newline thanks to phillip, - exec(compile(__USER_CODE_STRING__, 'blender_cmd.py', 'single')) #exec(compile(__USER_CODE_STRING__, 'blender_cmd.py', 'exec')) - - # Flush global dict, allow the user to remove items. - __CONSOLE_VAR_DICT__ = {} - - __TMP_VAR_NAME__ = '' # so as not to raise an error when del'ing - # Write local veriables to global __CONSOLE_VAR_DICT__ - for __TMP_VAR_NAME__ in dir(): - if __TMP_VAR_NAME__ != '__FILE_LIKE_STRING__' and\ - __TMP_VAR_NAME__ != '__STD_OUTPUT__' and\ - __TMP_VAR_NAME__ != '__TMP_VAR_NAME__' and\ - __TMP_VAR_NAME__ != '__USER_CODE_STRING__': - - # Execute the local > global coversion. - exec('%s%s' % ('__CONSOLE_VAR_DICT__[__TMP_VAR_NAME__]=', __TMP_VAR_NAME__)) - del __TMP_VAR_NAME__ - - except: # Prints the REAL exception. - error = '%s: %s' % (python_sys.exc_type, python_sys.exc_value) - for errorLine in error.split('\n'): - cmdBuffer.append(cmdLine(errorLine, 2, None)) # new line to type into - - python_sys.stdout = __STD_OUTPUT__ # Go back to output to the normal blender console - - # Copy all new output to cmdBuffer - - __FILE_LIKE_STRING__.seek(0) # the readline function requires that we go back to the start of the file. - - for line in __FILE_LIKE_STRING__.readlines(): - cmdBuffer.append(cmdLine(line, 1, None)) - - cmdBuffer.append(cmdLine(' ', 0, 0)) # new line to type into - python_sys.stdout=__STD_OUTPUT__ - __FILE_LIKE_STRING__.close() - - - - - -#------------------------------------------------------------------------------# -# event handling code # -#------------------------------------------------------------------------------# -def handle_event(evt, val): - - # Insert Char into the cammand line - def insCh(ch): # Instert a char - global cursor - # Later account for a cursor variable - cmdBuffer[-1].cmd = ('%s%s%s' % ( cmdBuffer[-1].cmd[:cursor], ch, cmdBuffer[-1].cmd[cursor:])) - - #------------------------------------------------------------------------------# - # Define Complex Key Actions # - #------------------------------------------------------------------------------# - def actionEnterKey(): - global histIndex, cursor - - def getIndent(string): - # Gather white space to add in the previous line - # Ignore the last char since its padding. - whiteSpace = '' - #for i in range(len(cmdBuffer[-1].cmd)): - for i in xrange(len(string)-1): - if cmdBuffer[-1].cmd[i] == ' ' or cmdBuffer[-1].cmd[i] == '\t': - whiteSpace += string[i] - else: - break - return whiteSpace - - # Autocomplete - if Window.GetKeyQualifiers() & Window.Qual.CTRL: - actionAutoCompleate() - return - - # Are we in the middle of a multiline part or not? - # try be smart about it - if cmdBuffer[-1].cmd.split('#')[0].rstrip().endswith(':'): - # : indicates an indent is needed - cmdBuffer.append(cmdLine('\t%s ' % getIndent(cmdBuffer[-1].cmd), 0, 0)) - print ': indicates an indent is needed' - - elif cmdBuffer[-1].cmd[0] in [' ', '\t'] and len(cmdBuffer[-1].cmd) > 1 and cmdBuffer[-1].cmd.split(): - # white space at the start means he havnt finished the multiline. - cmdBuffer.append(cmdLine('%s ' % getIndent(cmdBuffer[-1].cmd), 0, 0)) - print 'white space at the start means he havnt finished the multiline.' - - elif Window.GetKeyQualifiers() & Window.Qual.SHIFT: - # Crtl forces multiline - cmdBuffer.append(cmdLine('%s ' % getIndent(cmdBuffer[-1].cmd), 0, 0)) - print 'Crtl forces multiline' - - else: # Execute multiline code block - - # Multiline code will still run with 1 line, - multiLineCode = ['if 1:'] # End of the multiline first. - - # Seek the start of the file multiline - i = 1 - while cmdBuffer[-i].exe == 0: - i+=1 - - while i > 1: - i-=1 - - if cmdBuffer[-i].cmd == ' ':# Tag as an output type so its not used in the key history - cmdBuffer[-i].type = 1 - else: # Tab added at the start for added if 1: statement - multiLineCode.append('\t%s' % cmdBuffer[-i].cmd ) - - # Mark as executed - cmdBuffer[-i].exe = 1 - - multiLineCode.append('\tpass') # reverse will make this the start. - - # Dubug, print the code that is executed. - #for m in multiLineCode: print m - - runUserCode('\n'.join(multiLineCode)) - - # Clear the output based on __LINE_HISTORY__ - if len(cmdBuffer) > __LINE_HISTORY__: - cmdBuffer[:__LINE_HISTORY__] = [] - - histIndex = cursor = -1 # Reset cursor and history - - def actionUpKey(): - global histIndex - if abs(histIndex)+1 >= len(cmdBuffer): - histIndex = -1 - - # When wrapping allow 1 plank lines - if cmdBuffer[-1].cmd != ' ': - cmdBuffer[-1].cmd = ' ' - return - - histIndex_orig = histIndex - histIndex -= 1 - - while (cmdBuffer[histIndex].type != 0 and abs(histIndex) < len(cmdBuffer)) or \ - ( cmdBuffer[histIndex].cmd == cmdBuffer[histIndex_orig].cmd): - histIndex -= 1 - - if cmdBuffer[histIndex].type == 0: # we found one - cmdBuffer[-1].cmd = cmdBuffer[histIndex].cmd - - def actionDownKey(): - global histIndex - if histIndex >= -2: - histIndex = -len(cmdBuffer) - - # When wrapping allow 1 plank lines - if cmdBuffer[-1].cmd != ' ': - cmdBuffer[-1].cmd = ' ' - return - - histIndex_orig = histIndex - histIndex += 1 - while (cmdBuffer[histIndex].type != 0 and histIndex != -2) or \ - ( cmdBuffer[histIndex].cmd == cmdBuffer[histIndex_orig].cmd): - - histIndex += 1 - - if cmdBuffer[histIndex].type == 0: # we found one - cmdBuffer[-1].cmd = cmdBuffer[histIndex].cmd - - def actionRightMouse(): - global __FONT_SIZE__ - choice = Draw.PupMenu('Console Menu%t|Write Input Data (white)|Write Output Data (blue)|Write Error Data (red)|Write All Text|%l|Insert Blender text|%l|Font Size|%l|Clear Output|Quit') - - if choice == 1: - writeCmdData(0) # type 0 user - elif choice == 2: - writeCmdData(1) # type 1 user output - elif choice == 3: - writeCmdData(2) # type 2 errors - elif choice == 4: - writeCmdData(3) # All - elif choice == 6: - insertCmdData() # Insert text from Blender and run it. - elif choice == 8: - # Fontsize. - font_choice = Draw.PupMenu('Font Size%t|Large|Normal|Small|Tiny') - if font_choice != -1: - if font_choice == 1: - __FONT_SIZE__ = 3 - elif font_choice == 2: - __FONT_SIZE__ = 2 - elif font_choice == 3: - __FONT_SIZE__ = 1 - elif font_choice == 4: - __FONT_SIZE__ = 0 - Draw.Redraw() - elif choice == 10: # Clear all output - cmdBuffer[:] = [cmd for cmd in cmdBuffer if cmd.type == 0] # keep user input - Draw.Redraw() - elif choice == 11: # Exit - Draw.Exit() - - - # Auto compleating, quite complex- use recutsice dir for the moment. - def actionAutoCompleate(): # Ctrl + Tab - if not cmdBuffer[-1].cmd[:cursor].split(): - return - - - RECURSIVE_DIR = recursive_dir() - - # get last name of user input - editVar = cmdBuffer[-1].cmd[:cursor] - # Split off spaces operators etc from the staryt of the command so we can use the startswith function. - for splitChar in __VARIABLE_DELIMETERS__: - editVar = editVar[:-1].split(splitChar)[-1] + editVar[-1] - - - # Now we should have the var by its self - if editVar: - possibilities = [] - - for __TMP_VAR_NAME__ in RECURSIVE_DIR: #.keys(): - #print '\t', __TMP_VAR_NAME__ - if __TMP_VAR_NAME__ == editVar: - # print 'ADITVAR IS A VAR' - pass - ''' - elif __TMP_VAR_NAME__.startswith( editVar ): - print __TMP_VAR_NAME__, 'aaa' - possibilities.append( __TMP_VAR_NAME__ ) - ''' - possibilities.append( __TMP_VAR_NAME__ ) - - if len(possibilities) == 1: - cmdBuffer[-1].cmd = ('%s%s%s' % (cmdBuffer[-1].cmd[:cursor - len(editVar)], possibilities[0], cmdBuffer[-1].cmd[cursor:])) - - elif possibilities: # If its not just [] - # -1 with insert is the second last. - - # Text choice - #cmdBuffer.insert(-1, cmdLine('options: %s' % ' '.join(possibilities), 3, None)) - - menuList = [] # A lits of tuples- ABSOLUTE, RELATIVE - - for __TMP_VAR_NAME__ in possibilities: - for usage in RECURSIVE_DIR[__TMP_VAR_NAME__]: - # Account for non absolute (variables for eg.) - if usage: # not '' - absName = '%s.%s' % (usage, __TMP_VAR_NAME__) - - if __TMP_VAR_NAME__.startswith(editVar): - menuList.append( # Used for names and can be entered when pressing shift. - (absName, # Absolute name - __TMP_VAR_NAME__) # Relative name, non shift - ) - - #else: - # if absName.find(editVar) != -1: - # menuList.append((__TMP_VAR_NAME__, __TMP_VAR_NAME__)) # Used for names and can be entered when pressing shift. - - # No items to display? no menu - if not menuList: - return - - menuList.sort() - - choice = PupMenuLess( # Menu for the user to choose the autocompleate - 'Choices (Shift for local name, Ctrl for Docs)%t|' + # Title Text - '|'.join(['%s, %s' % m for m in menuList])) # Use Absolute names m[0] - - if choice != -1: - if Window.GetKeyQualifiers() & Window.Qual.CTRL: # Help - cmdBuffer[-1].cmd = ('help(%s%s) ' % (cmdBuffer[-1].cmd[:cursor - len(editVar)], menuList[choice-1][0])) - elif Window.GetKeyQualifiers() & Window.Qual.SHIFT: # Put in the long name - cmdBuffer[-1].cmd = ('%s%s%s' % (cmdBuffer[-1].cmd[:cursor - len(editVar)], menuList[choice-1][1], cmdBuffer[-1].cmd[cursor:])) - else: # Only paste in the Short name - cmdBuffer[-1].cmd = ('%s%s%s' % (cmdBuffer[-1].cmd[:cursor - len(editVar)], menuList[choice-1][0], cmdBuffer[-1].cmd[cursor:])) - - - else: - # print 'NO EDITVAR' - return - - # ------------------end------------------ # - - # Quit from menu only - #if (evt == Draw.ESCKEY and not val): - # Draw.Exit() - if evt == Draw.MOUSEX or evt == Draw.MOUSEY: # AVOID TOO MANY REDRAWS. - return - - - global cursor - global histIndex - global __FONT_SIZE__ - global __CONSOLE_LINE_OFFSET__ - - ascii = Blender.event - - resetScroll = True - - #------------------------------------------------------------------------------# - # key codes and key handling # - #------------------------------------------------------------------------------# - - # UP DOWN ARROW KEYS, TO TRAVERSE HISTORY - if (evt == Draw.UPARROWKEY and val): actionUpKey() - elif (evt == Draw.DOWNARROWKEY and val): actionDownKey() - - elif (evt == Draw.RIGHTARROWKEY and val): - if Window.GetKeyQualifiers() & Window.Qual.SHIFT: - wordJump = False - newCursor = cursor+1 - while newCursor<0: - - if cmdBuffer[-1].cmd[newCursor] not in __DELIMETERS__: - newCursor+=1 - else: - wordJump = True - break - if wordJump: # Did we find a new cursor pos? - cursor = newCursor - else: - cursor = -1 # end of line - else: - cursor +=1 - if cursor > -1: - cursor = -1 - - elif (evt == Draw.LEFTARROWKEY and val): - if Window.GetKeyQualifiers() & Window.Qual.SHIFT: - wordJump = False - newCursor = cursor-1 - while abs(newCursor) < len(cmdBuffer[-1].cmd): - - if cmdBuffer[-1].cmd[newCursor] not in __DELIMETERS__ or\ - newCursor == cursor: - newCursor-=1 - else: - wordJump = True - break - if wordJump: # Did we find a new cursor pos? - cursor = newCursor - else: - cursor = -len(cmdBuffer[-1].cmd) # Start of line - - else: - if len(cmdBuffer[-1].cmd) > abs(cursor): - cursor -=1 - - elif (evt == Draw.HOMEKEY and val): - cursor = -len(cmdBuffer[-1].cmd) - - elif (evt == Draw.ENDKEY and val): - cursor = -1 - - elif (evt == Draw.TABKEY and val): - insCh('\t') - - elif (evt == Draw.BACKSPACEKEY and val): - if Window.GetKeyQualifiers() & Window.Qual.SHIFT: - i = -1 - for d in __DELIMETERS__: - i = max(i, cmdBuffer[-1].cmd[:cursor-1].rfind(d)) - if i == -1: - i=0 - cmdBuffer[-1].cmd = ('%s%s' % (cmdBuffer[-1].cmd[:i] , cmdBuffer[-1].cmd[cursor:])) - - else: - # Normal backspace. - cmdBuffer[-1].cmd = ('%s%s' % (cmdBuffer[-1].cmd[:cursor-1] , cmdBuffer[-1].cmd[cursor:])) - - elif (evt == Draw.DELKEY and val) and cursor < -1: - cmdBuffer[-1].cmd = cmdBuffer[-1].cmd[:cursor] + cmdBuffer[-1].cmd[cursor+1:] - cursor +=1 - - elif ((evt == Draw.RETKEY or evt == Draw.PADENTER) and val): - actionEnterKey() - - elif (evt == Draw.RIGHTMOUSE and not val): actionRightMouse(); return - - elif (evt == Draw.PADPLUSKEY or evt == Draw.EQUALKEY or evt == Draw.WHEELUPMOUSE) and val and Window.GetKeyQualifiers() & Window.Qual.CTRL: - __FONT_SIZE__ += 1 - __FONT_SIZE__ = min(len(__FONT_SIZES__)-1, __FONT_SIZE__) - elif (evt == Draw.PADMINUS or evt == Draw.MINUSKEY or evt == Draw.WHEELDOWNMOUSE) and val and Window.GetKeyQualifiers() & Window.Qual.CTRL: - __FONT_SIZE__ -=1 - __FONT_SIZE__ = max(0, __FONT_SIZE__) - - - elif evt == Draw.WHEELUPMOUSE and val: - __CONSOLE_LINE_OFFSET__ += 1 - __CONSOLE_LINE_OFFSET__ = min(len(cmdBuffer)-2, __CONSOLE_LINE_OFFSET__) - resetScroll = False - - elif evt == Draw.WHEELDOWNMOUSE and val: - __CONSOLE_LINE_OFFSET__ -= 1 - __CONSOLE_LINE_OFFSET__ = max(0, __CONSOLE_LINE_OFFSET__) - resetScroll = False - - - elif ascii: - insCh(chr(ascii)) - else: - return # dont redraw. - - # If the user types in anything then scroll to bottom. - if resetScroll: - __CONSOLE_LINE_OFFSET__ = 0 - Draw.Redraw() - - -def draw_gui(): - # Get the bounds from ObleGL directly - __CONSOLE_RECT__ = BGL.Buffer(BGL.GL_FLOAT, 4) - BGL.glGetFloatv(BGL.GL_SCISSOR_BOX, __CONSOLE_RECT__) - __CONSOLE_RECT__= __CONSOLE_RECT__.list - - # Clear the screen - BGL.glClearColor(0.0, 0.0, 0.0, 1.0) - BGL.glClear(BGL.GL_COLOR_BUFFER_BIT) # use it to clear the color buffer - - - # Fixed margin. use a margin since 0 margin can be hard to seewhen close to a crt's edge. - margin = 4 - - # Convenience - FNT_NAME, FNT_HEIGHT = __FONT_SIZES__[__FONT_SIZE__] - - # Draw cursor location colour - if __CONSOLE_LINE_OFFSET__ == 0: - cmd2curWidth = Draw.GetStringWidth(cmdBuffer[-1].cmd[:cursor], FNT_NAME) - BGL.glColor3f(0.8, 0.2, 0.2) - if cmd2curWidth == 0: - BGL.glRecti(margin,2,margin+2, FNT_HEIGHT+2) - else: - BGL.glRecti(margin + cmd2curWidth-2,2, margin+cmd2curWidth, FNT_HEIGHT+2) - - BGL.glColor3f(1,1,1) - # Draw the set of cammands to the buffer - consoleLineIdx = __CONSOLE_LINE_OFFSET__ + 1 - wrapLineIndex = 0 - while consoleLineIdx < len(cmdBuffer) and __CONSOLE_RECT__[3] > (consoleLineIdx - __CONSOLE_LINE_OFFSET__) * FNT_HEIGHT: - if cmdBuffer[-consoleLineIdx].type == 0: - BGL.glColor3f(1, 1, 1) - elif cmdBuffer[-consoleLineIdx].type == 1: - BGL.glColor3f(.3, .3, 1) - elif cmdBuffer[-consoleLineIdx].type == 2: - BGL.glColor3f(1.0, 0, 0) - elif cmdBuffer[-consoleLineIdx].type == 3: - BGL.glColor3f(0, 0.8, 0) - else: - BGL.glColor3f(1, 1, 0) - - if consoleLineIdx == 1: # user input - BGL.glRasterPos2i(margin, (FNT_HEIGHT * (consoleLineIdx-__CONSOLE_LINE_OFFSET__)) - 8) - Draw.Text(cmdBuffer[-consoleLineIdx].cmd, FNT_NAME) - else: # WRAP - lwid = Draw.GetStringWidth(cmdBuffer[-consoleLineIdx].cmd, FNT_NAME) - if margin + lwid > __CONSOLE_RECT__[2]: - wrapLineList = [] - wtext = cmdBuffer[-consoleLineIdx].cmd - wlimit = len(wtext) - chunksz = int(( __CONSOLE_RECT__[2] - margin ) / (lwid / len(wtext))) - lstart = 0 - fsize = FNT_NAME - while lstart < wlimit: - lend = min(lstart+chunksz,wlimit) - ttext = wtext[lstart:lend] - while lend < wlimit and Draw.GetStringWidth(ttext, fsize) + margin < __CONSOLE_RECT__[2]: - lend += 1 - ttext = wtext[lstart:lend] - while lend > lstart+1 and Draw.GetStringWidth(ttext, fsize) + margin > __CONSOLE_RECT__[2]: - lend -= 1 - ttext = wtext[lstart:lend] - wrapLineList.append(ttext) - lstart = lend - # Now we have a list of lines, draw them (OpenGLs reverse ordering requires this odd change) - wrapLineList.reverse() - for wline in wrapLineList: - BGL.glRasterPos2i(margin, (FNT_HEIGHT*((consoleLineIdx-__CONSOLE_LINE_OFFSET__) + wrapLineIndex)) - 8) - Draw.Text(wline, FNT_NAME) - wrapLineIndex += 1 - wrapLineIndex-=1 # otherwise we get a silly extra line. - - else: # no wrapping. - - BGL.glRasterPos2i(margin, (FNT_HEIGHT * ((consoleLineIdx-__CONSOLE_LINE_OFFSET__)+wrapLineIndex)) - 8) - Draw.Text(cmdBuffer[-consoleLineIdx].cmd, FNT_NAME) - consoleLineIdx += 1 - -# This recieves the event index, call a function from here depending on the event. -def handle_button_event(evt): - pass - - -# Run the console -__CONSOLE_VAR_DICT__ = {} # Initialize var dict - - -# Print Startup lines, add __bpydoc__ to the console startup. -for l in __bpydoc__.split('<br>'): - cmdBuffer.append( cmdLine(l, 1, None) ) - - -histIndex = cursor = -1 # How far back from the first letter are we? - in current CMD line, history if for moving up and down lines. - -# Autoexec, startup code. -scriptDir = Get('scriptsdir') -console_autoexec = None -if scriptDir: - if not scriptDir.endswith(Blender.sys.sep): - scriptDir += Blender.sys.sep - - console_autoexec = '%s%s' % (scriptDir, 'console_autoexec.py') - - if not sys.exists(console_autoexec): - # touch the file - try: - open(console_autoexec, 'w').close() - cmdBuffer.append(cmdLine('...console_autoexec.py not found, making new in scripts dir', 1, None)) - except: - cmdBuffer.append(cmdLine('...console_autoexec.py could not write, this is ok', 1, None)) - scriptDir = None # make sure we only use this for console_autoexec.py - - if not sys.exists(console_autoexec): - console_autoexec = None - - else: - cmdBuffer.append(cmdLine('...Using existing console_autoexec.py in scripts dir', 1, None)) - - - -#-Autoexec---------------------------------------------------------------------# -# Just use the function to jump into local naming mode. -# This is so we can loop through all of the autoexec functions / vars and add them to the __CONSOLE_VAR_DICT__ -def include_console(includeFile): - global __CONSOLE_VAR_DICT__ # write autoexec vars to this. - - # Execute an external py file as if local - exec(include(includeFile)) - -def standard_imports(): - # Write local to global __CONSOLE_VAR_DICT__ for reuse, - - exec('%s%s' % ('__CONSOLE_VAR_DICT__["bpy"]=', 'bpy')) - exec('%s%s' % ('__CONSOLE_VAR_DICT__["Blender"]=', 'Blender')) - - for ls in (dir(), dir(Blender)): - for __TMP_VAR_NAME__ in ls: - # Execute the local > global coversion. - exec('%s%s' % ('__CONSOLE_VAR_DICT__[__TMP_VAR_NAME__]=', __TMP_VAR_NAME__)) - - # Add dummy imports to input so output scripts to a text file work as expected - cmdBuffer.append(cmdLine('import bpy', 0, 1)) - cmdBuffer.append(cmdLine('import Blender', 0, 1)) # pretend we have been executed, as we kindof have. - cmdBuffer.append(cmdLine('from Blender import *', 0, 1)) - -if scriptDir and console_autoexec: - include_console(console_autoexec) # pass the blender module - -standard_imports() # import Blender and bpy - -#-end autoexec-----------------------------------------------------------------# - - -# Append new line to write to -cmdBuffer.append(cmdLine(' ', 0, 0)) - -#------------------------------------------------------------------------------# -# register the event handling code, GUI # -#------------------------------------------------------------------------------# -def main(): - Draw.Register(draw_gui, handle_event, handle_button_event) - -if __name__ == '__main__': - main() diff --git a/release/scripts/discombobulator.py b/release/scripts/discombobulator.py deleted file mode 100644 index 6dbb4e5382b..00000000000 --- a/release/scripts/discombobulator.py +++ /dev/null @@ -1,1526 +0,0 @@ -#!BPY - -""" -Name: 'Discombobulator' -Blender: 237 -Group: 'Mesh' -Tip: 'Adds random geometry to a mesh' -""" - -__author__ = "Evan J. Rosky (syrux)" -__url__ = ("Script's homepage, http://evan.nerdsofparadise.com/programs/discombobulator/index.html") -__version__ = "237" -__bpydoc__ = """\ -Discombobulator adds random geometry to a mesh. - -As an example, this script can easily give a "high-tech" -look to walls and spaceships. - -Definitions:<br> - - Protrusions: extrusions of each original face on the mesh. -You may have from 1 to 4 protrusions on each face.<br> - - Taper: The tips of each protrusion will be a percentage -smaller than the base.<br> - - Doodads: small extruded blocks/shapes that are randomly placed -about the top of a protrusion or face. - - -Usage:<br> - Input your settings, make sure the mesh you would like to modify -is selected (active) and then click on "Discombobulate".<br> - See the scripts tutorial page (on the homepage) for more info. - - -New Features:<br> - - Will use existing materials if there are any.<br> - - Clicking "Assign materials by part" will allow assigning -of different material indices to Protrusion or Doodad Sides -and Tops in the gui element below it.<br> - - Setting a material index to 0 will use whatever material -is assigned to the face that is discombobulated. - - You can now scroll using the arrow keys. - - -Notes:<br> - - Modifications can be restricted to selected faces -by setting "Only selected faces" for protrusions and/or -doodads.<br> - - It's possible to restrict mesh generation to add only -protrusions or only doodads instead of both.<br> - - You may also choose to have Discombobulator select the -tops of created protrusions by clicking the corresponding -number of protrusion buttons under "Select Tops". You may -also do the same for doodads by choosing "Select Doodads" and -"Only Select Tops". You may choose to select the whole doodads -by leaving "Only Select Tops" off.<br> - - By selecting "Deselect Selected" you can have -discombobulator deselect everything but the selections it -makes.<br> - - The "Face %" option will set the percentage of faces that -will be modified either for the doodads or the protrusions.<br> - - "Copy Before Modifying" will create a new object with the -modifications where leaving it off will overwrite the original -mesh.<br> - -You can find more information at the Link above. -""" - - -# $Id$ -# -# Updated 2006-09-26 -# Changes since last version: -# > Works with Blender CVS and hopefully with Blender 2.40. -# > Swaps min/max values when min>max rather than complaining. -# > Will keep previously assigned materials. -# > Now allows user to assign custom material indices to -# Protrusion and Doodad Sides and Tops. -# > The initial Gui Layout will change depending on the aspect -# ratio of the window it is in. -# > Using the arrow keys will scroll the gui. -# -# -------------------------------------------------------------------------- -# Discombobulator v2.1b -# by Evan J. Rosky, 2005 -# This plugin is protected by the GPL: Gnu Public Licence -# GPL - http://www.gnu.org/copyleft/gpl.html -# -------------------------------------------------------------------------- -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Copyright (C) 2005: Evan J. Rosky -# -# 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 ***** -# -------------------------------------------------------------------------- - -#Hit Alt-P to run - -import Blender -from Blender import NMesh,Object,Material,Window,Types,Scene -from Blender.NMesh import Vert,Face -from Blender.Mathutils import * - -import defaultdoodads -import BPyMathutils -from BPyMathutils import genrand -a = BPyMathutils.sgenrand(int(round(Rand(1000,99999),0))) - -#Create random numbers -def randnum(low,high): - num = genrand() - num = num*(high-low) - num = num+low - return num - -#Object Vars -newmesh = NMesh.GetRaw() -materialArray = [0] - -#Material Vars -reassignMats = 0 -protSideMat = 1 -protTopMat = 2 -doodSideMat = 3 -doodTopMat = 4 -thereAreMats = 0 -currmat = 0 - -#Global Vars -makenewobj = 1 -errortext = "Remember to select an object." -editmode = 0 - -#Protrusion Vars -makeprots = 1 -faceschangedpercent = 1.0 -minimumheight = 0.2 -maximumheight = 0.4 -subface1 = 1 -subface2 = 1 -subface3 = 1 -subface4 = 1 -subfaceArray = [1,2,3,4] -minsubfaces = 1 -minimumtaperpercent = 0.15 -maximumtaperpercent = 0.35 -useselectedfaces = 0 -selectface1 = 1 -selectface2 = 1 -selectface3 = 1 -selectface4 = 1 -deselface = 1 - -#Doodad Vars -makedoodads = 1 -doodadfacepercent = 1.0 -selectdoodad = 0 -onlyonprotrusions = 0 -doodonselectedfaces = 0 -selectdoodadtoponly = 0 -doodad1 = 1 -doodad2 = 1 -doodad3 = 1 -doodad4 = 1 -doodad5 = 1 -doodad6 = 1 -doodadminperface = 2 -doodadmaxperface = 6 -doodadminsize = 0.15 -doodadmaxsize = 0.45 -doodadminheight = 0.0 -doodadmaxheight = 0.1 -doodadArray = [1,2,3,4,5,6] - -def makeSubfaceArray(): - global subfaceArray - global subface1 - global subface2 - global subface3 - global subface4 - - subfaceArray = [] - if subface1 > 0: - subfaceArray.append(1) - if subface2 > 0: - subfaceArray.append(2) - if subface3 > 0: - subfaceArray.append(3) - if subface4 > 0: - subfaceArray.append(4) - -def makeDoodadArray(): - global doodadArray - global doodad1 - global doodad2 - global doodad3 - global doodad4 - global doodad5 - global doodad6 - - doodadArray = [] - if doodad1 > 0: - doodadArray.append(1) - if doodad2 > 0: - doodadArray.append(2) - if doodad3 > 0: - doodadArray.append(3) - if doodad4 > 0: - doodadArray.append(4) - if doodad5 > 0: - doodadArray.append(5) - if doodad6 > 0: - doodadArray.append(6) - -def extrude(mid,nor,protrusion,v1,v2,v3,v4,tosel=1,flipnor=0): - taper = 1 - randnum(minimumtaperpercent,maximumtaperpercent) - newmesh_verts = newmesh.verts - newmesh_faces = newmesh.faces - - vert = newmesh_verts[v1] - point = (vert.co - mid)*taper + mid + protrusion*Vector(nor) - ver = Vert(point[0],point[1],point[2]) - ver.sel = tosel - newmesh_verts.append(ver) - vert = newmesh_verts[v2] - point = (vert.co - mid)*taper + mid + protrusion*Vector(nor) - ver = Vert(point[0],point[1],point[2]) - ver.sel = tosel - newmesh_verts.append(ver) - vert = newmesh_verts[v3] - point = (vert.co - mid)*taper + mid + protrusion*Vector(nor) - ver = Vert(point[0],point[1],point[2]) - ver.sel = tosel - newmesh_verts.append(ver) - vert = newmesh_verts[v4] - point = (vert.co - mid)*taper + mid + protrusion*Vector(nor) - ver = Vert(point[0],point[1],point[2]) - ver.sel = tosel - newmesh_verts.append(ver) - - faceindex = len(newmesh_verts) - 4 - - #side face 1 - face = Face([newmesh_verts[v1], newmesh_verts[v2], newmesh_verts[faceindex+1], newmesh_verts[faceindex]]) - if flipnor != 0: - face.v.reverse() - if thereAreMats == 1: - if reassignMats == 0 or protSideMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = protSideMat-1 - newmesh_faces.append(face) - - #side face 2 - face = Face([newmesh_verts[v2], newmesh_verts[v3], newmesh_verts[faceindex+2], newmesh_verts[faceindex+1]]) - if flipnor != 0: - face.v.reverse() - if thereAreMats == 1: - if reassignMats == 0 or protSideMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = protSideMat-1 - newmesh_faces.append(face) - - #side face 3 - face = Face([newmesh_verts[v3], newmesh_verts[v4], newmesh_verts[faceindex+3], newmesh_verts[faceindex+2]]) - if flipnor != 0: - face.v.reverse() - if thereAreMats == 1: - if reassignMats == 0 or protSideMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = protSideMat-1 - newmesh_faces.append(face) - - #side face 4 - face = Face([newmesh_verts[v4], newmesh_verts[v1], newmesh_verts[faceindex], newmesh_verts[faceindex+3]]) - if flipnor != 0: - face.v.reverse() - if thereAreMats == 1: - if reassignMats == 0 or protSideMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = protSideMat-1 - newmesh_faces.append(face) - - #top face - face = Face(newmesh_verts[-4:]) - if flipnor != 0: - face.v.reverse() - if tosel == 1: - face.sel = 1 - if thereAreMats == 1: - if reassignMats == 0 or protTopMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = protTopMat-1 - newmesh_faces.append(face) - return face - -#Sets the global protrusion values -def setProtrusionValues(p0,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14,p15): - - #Protrusions - global makeprots - global minimumtaperpercent - global maximumtaperpercent - global faceschangedpercent - global minimumheight - global maximumheight - global subface1 - global subface2 - global subface3 - global subface4 - global useselectedfaces - global selectface1 - global selectface2 - global selectface3 - global selectface4 - global deselface - global subfaceArray - - #Protrusions - makeprots = p0 - faceschangedpercent = p1 - minimumheight = p2 - maximumheight = p3 - subface1 = p4 - subface2 = p5 - subface3 = p6 - subface4 = p7 - minimumtaperpercent = p8 - maximumtaperpercent = p9 - useselectedfaces = p10 - selectface1 = p11 - selectface2 = p12 - selectface3 = p13 - selectface4 = p14 - deselface = p15 - makeSubfaceArray() - if len(subfaceArray) == 0: - makeprots = 0 - - if minimumheight > maximumheight: - a = maximumheight - maximimheight = minimumheight - minimumheight = a - elif minimumtaperpercent > maximumtaperpercent: - a = maximumtaperpercent - maximimtaperpercent = minimumtaperpercent - minimumtaperpercent = a - -#Sets the global Doodad values -def setDoodadValues(d0,d1,d2,d3,d4,d5,d6,d7,d8,d9,d10,d11,d12,d13,d14,d15,d16,d17): - - #Doodads - global makedoodads - global doodadfacepercent - global selectdoodad - global onlyonprotrusions - global doodad1 - global doodad2 - global doodad3 - global doodad4 - global doodad5 - global doodad6 - global doodadminperface - global doodadmaxperface - global doodadminsize - global doodadmaxsize - global doodadminheight - global doodadmaxheight - global doodadArray - global doodonselectedfaces - global selectdoodadtoponly - - #Doodads - makedoodads = d0 - doodadfacepercent = d1 - selectdoodad = d2 - onlyonprotrusions = d3 - doodad1 = d4 - doodad2 = d5 - doodad3 = d6 - doodad4 = d7 - doodad5 = d8 - doodad6 = d9 - doodadminperface = d10 - doodadmaxperface = d11 - doodadminsize = d12 - doodadmaxsize = d13 - doodadminheight = d14 - doodadmaxheight = d15 - doodonselectedfaces = d16 - selectdoodadtoponly = d17 - makeDoodadArray() - if len(doodadArray) == 0: - makedoodads = 0 - - elif doodadminperface > doodadmaxperface: - a = doodadmaxperface - doodadmaxperface = doodadminperface - doodadminperface = a - elif doodadminsize > doodadmaxsize: - a = doodadmaxsize - doodadmaxsize = doodadminsize - doodadminsize = a - elif doodadminheight > doodadmaxheight: - a = doodadmaxheight - doodadmaxheight = doodadminheight - doodadminheight = a - -#Sets other global values -def setOtherValues(g0,m0,m1,m2,m3,m4): - - #Global - global reassignMats - global makenewobj - global protSideMat - global protTopMat - global doodSideMat - global doodTopMat - - #Get Misc Variables - makenewobj = g0 - reassignMats = m0 - protSideMat = m1 - protTopMat = m2 - doodSideMat = m3 - doodTopMat = m4 - -def discombobulate(): - - #Global - global origmesh - global newmesh - global makenewobj - global origobj - global newobj - global messagetext - global errortext - global editmode - - #Protrusions - global makeprots - global minimumtaperpercent - global maximumtaperpercent - global faceschangedpercent - global minimumheight - global maximumheight - global subface1 - global subface2 - global subface3 - global subface4 - global useselectedfaces - global selectface1 - global selectface2 - global selectface3 - global selectface4 - global deselface - global subfaceArray - - #Doodads - global makedoodads - global doodadfacepercent - global selectdoodad - global onlyonprotrusions - global doodad1 - global doodad2 - global doodad3 - global doodad4 - global doodad5 - global doodad6 - global doodadminperface - global doodadmaxperface - global doodadminsize - global doodadmaxsize - global doodadminheight - global doodadmaxheight - global doodadArray - global doodonselectedfaces - global selectdoodadtoponly - - #Global - global materialArray - global reassignMats - global protSideMat - global protTopMat - global doodSideMat - global doodTopMat - global thereAreMats - global currmat - - origobj = Scene.GetCurrent().objects.active - if not origobj: - glRasterPos2d(10,50) - errortext = "YOU MUST SELECT AN OBJECT!" - messagetext = ErrorText(errortext) - Blender.Redraw() - return - - #Leave Editmode - editmode = Window.EditMode() - if editmode: Window.EditMode(0) - - #Get Major Variables - - origmesh = origobj.getData() - - if origobj.type != 'Mesh': - glRasterPos2d(10,50) - errortext = "OBJECT MUST BE MESH!" - messagetext = ErrorText(errortext) - Blender.Redraw() - return - - newmesh = NMesh.GetRaw() - materialArray = origmesh.getMaterials() - if len(materialArray) < 1: - thereAreMats = 0 - else: - thereAreMats = 1 - - #add material indices if necessary (only up to 4) - if thereAreMats == 1 and reassignMats == 1: - if len(materialArray) < 4: - if protSideMat > 4: protSideMat = 4 - if protTopMat > 4: protTopMat = 4 - if doodSideMat > 4: doodSideMat = 4 - if doodTopMat > 4: doodTopMat = 4 - else: - if protSideMat > len(materialArray): protSideMat = len(materialArray) - if protTopMat > len(materialArray): protTopMat = len(materialArray) - if doodSideMat > len(materialArray): doodSideMat = len(materialArray) - if doodTopMat > len(materialArray): doodTopMat = len(materialArray) - - #This only does something if there are less than 4 verts - for matind in [protSideMat,protTopMat,doodSideMat,doodTopMat]: - if matind > len(materialArray) and matind <= 4: - for i in xrange(len(materialArray),matind+1): - materialArray.append(Material.New("AddedMat " + str(i))) - - #Sets the materials - newmesh.setMaterials(materialArray) - - #Set the doodad settings - defaultdoodads.settings(selectdoodadtoponly,materialArray,reassignMats,thereAreMats,doodSideMat,doodTopMat) - #defaultdoodads.settings(selectdoodadtoponly,materialArray,reassignMats,thereAreMats,currmat) - - newmesh.verts.extend(origmesh.verts) - - #Start modifying faces - for currface in origmesh.faces: - - currmat = currface.materialIndex - defaultdoodads.setCurrMat(currmat) - - #Check if it is a triangle - if len(currface.v)<4: - face = Face([newmesh.verts[currface.v[0].index],newmesh.verts[currface.v[1].index],newmesh.verts[currface.v[2].index]]) - if thereAreMats == 1: - face.materialIndex = currmat - newmesh.faces.append(face) - continue - - #Check whether or not to make protrusions - if makeprots == 0: - face = Face([newmesh.verts[currface.v[0].index],newmesh.verts[currface.v[1].index],newmesh.verts[currface.v[2].index],newmesh.verts[currface.v[3].index]]) - if thereAreMats == 1: - face.materialIndex = currmat - newmesh.faces.append(face) - if makedoodads == 1 and onlyonprotrusions == 0: - if doodonselectedfaces == 1: - if currface.sel: - tempmesh = NMesh.GetRaw() - tempmesh = defaultdoodads.createDoodad(doodadArray,face, doodadminsize, doodadmaxsize, doodadminheight,doodadmaxheight, selectdoodad, doodadminperface, doodadmaxperface, doodadfacepercent) - newmesh.verts.extend(tempmesh.verts) - newmesh.faces.extend(tempmesh.faces) - else: - tempmesh = NMesh.GetRaw() - tempmesh = defaultdoodads.createDoodad(doodadArray,face, doodadminsize, doodadmaxsize, doodadminheight,doodadmaxheight, selectdoodad, doodadminperface, doodadmaxperface, doodadfacepercent) - newmesh.verts.extend(tempmesh.verts) - newmesh.faces.extend(tempmesh.faces) - continue - - #Check if only changing selected faces - if useselectedfaces == 1: - #check if currface is selected - if currface.sel: - a = 1 - else: - face = Face([newmesh.verts[currface.v[0].index],newmesh.verts[currface.v[1].index],newmesh.verts[currface.v[2].index],newmesh.verts[currface.v[3].index]]) - if thereAreMats == 1: - face.materialIndex = currmat - newmesh.faces.append(face) - if makedoodads == 1 and onlyonprotrusions == 0: - if doodonselectedfaces != 1: - tempmesh = NMesh.GetRaw() - tempmesh = defaultdoodads.createDoodad(doodadArray,face, doodadminsize, doodadmaxsize, doodadminheight,doodadmaxheight, selectdoodad, doodadminperface, doodadmaxperface, doodadfacepercent) - newmesh.verts.extend(tempmesh.verts) - newmesh.faces.extend(tempmesh.faces) - continue - #Check if face should be modified by random chance - if randnum(0,1)>faceschangedpercent: - face = Face([newmesh.verts[currface.v[0].index],newmesh.verts[currface.v[1].index],newmesh.verts[currface.v[2].index],newmesh.verts[currface.v[3].index]]) - if thereAreMats == 1: - face.materialIndex = currmat - newmesh.faces.append(face) - if makedoodads == 1 and onlyonprotrusions == 0: - if doodonselectedfaces == 1: - if currface.sel: - tempmesh = NMesh.GetRaw() - tempmesh = defaultdoodads.createDoodad(doodadArray,face, doodadminsize, doodadmaxsize, doodadminheight,doodadmaxheight, selectdoodad, doodadminperface, doodadmaxperface, doodadfacepercent) - newmesh.verts.extend(tempmesh.verts) - newmesh.faces.extend(tempmesh.faces) - else: - tempmesh = NMesh.GetRaw() - tempmesh = defaultdoodads.createDoodad(doodadArray,face, doodadminsize, doodadmaxsize, doodadminheight,doodadmaxheight, selectdoodad, doodadminperface, doodadmaxperface, doodadfacepercent) - newmesh.verts.extend(tempmesh.verts) - newmesh.faces.extend(tempmesh.faces) - continue - - center = Vector([0,0,0]) - for pt in currface.v: - center = center + pt.co - center = center / len(currface.v) - - #Determine amount of subfaces - subfaces = round(randnum(1,len(subfaceArray)),0) - subfaces = subfaceArray[(int(subfaces) - 1)] - - ######################## START DEALING WITH PROTRUSIONS ##################### - - if subfaces == 1: - prot = randnum(minimumheight,maximumheight) - tempface = extrude(center,currface.no,prot,currface.v[0].index,currface.v[1].index,currface.v[2].index,currface.v[3].index,selectface1) - if makedoodads == 1: - if doodonselectedfaces == 1: - if currface.sel: - tempmesh = NMesh.GetRaw() - tempmesh = defaultdoodads.createDoodad(doodadArray, tempface, doodadminsize, doodadmaxsize, doodadminheight,doodadmaxheight, selectdoodad, doodadminperface, doodadmaxperface, doodadfacepercent) - newmesh.verts.extend(tempmesh.verts) - newmesh.faces.extend(tempmesh.faces) - else: - tempmesh = NMesh.GetRaw() - tempmesh = defaultdoodads.createDoodad(doodadArray, tempface, doodadminsize, doodadmaxsize, doodadminheight,doodadmaxheight, selectdoodad, doodadminperface, doodadmaxperface, doodadfacepercent) - newmesh.verts.extend(tempmesh.verts) - newmesh.faces.extend(tempmesh.faces) - - elif subfaces == 2: - orientation = int(round(randnum(0,1))) - p1 = currface.v[orientation] - p2 = currface.v[orientation + 1] - p3 = ((p2.co - p1.co)/2) + p1.co - ve1 = Vert(p3[0],p3[1],p3[2]) - ve1.sel = 0 - p1 = currface.v[2 + orientation] - if orientation < 0.5: - p2 = currface.v[3] - else: - p2 = currface.v[0] - p3 = ((p2.co - p1.co)/2) + p1.co - ve2 = Vert(p3[0],p3[1],p3[2]) - ve2.sel = 0 - if orientation < 0.5: - verti = currface.v[3] - p3 = verti.index - v1 = p3 - verti = currface.v[0] - p0 = verti.index - v2 = p0 - else: - verti = currface.v[0] - p0 = verti.index - v1 = p0 - verti = currface.v[1] - p1 = verti.index - v2 = p1 - newmesh.verts.append(ve1) - newmesh.verts.append(ve2) - index = len(newmesh.verts) - 2 - v4 = index + 1 - v3 = index - center = Vector([0, 0, 0]) - for pt in [newmesh.verts[v1],newmesh.verts[v2],newmesh.verts[v3],newmesh.verts[v4]]: - center += pt.co - center = center/4 - prot = randnum(minimumheight,maximumheight) - tempface = extrude(center,currface.no,prot,v1,v2,v3,v4,selectface2) - if makedoodads == 1: - if doodonselectedfaces == 1: - if currface.sel: - tempmesh = NMesh.GetRaw() - tempmesh = defaultdoodads.createDoodad(doodadArray, tempface, doodadminsize, doodadmaxsize, doodadminheight,doodadmaxheight, selectdoodad, doodadminperface, doodadmaxperface, doodadfacepercent) - newmesh.verts.extend(tempmesh.verts) - newmesh.faces.extend(tempmesh.faces) - else: - tempmesh = NMesh.GetRaw() - tempmesh = defaultdoodads.createDoodad(doodadArray, tempface, doodadminsize, doodadmaxsize, doodadminheight,doodadmaxheight, selectdoodad, doodadminperface, doodadmaxperface, doodadfacepercent) - newmesh.verts.extend(tempmesh.verts) - newmesh.faces.extend(tempmesh.faces) - if orientation < 0.5: - verti = currface.v[1] - p1 = verti.index - v1 = p1 - verti = currface.v[2] - p2 = verti.index - v2 = p2 - else: - verti = currface.v[2] - p2 = verti.index - v1 = p2 - verti = currface.v[3] - p3 = verti.index - v2 = p3 - center = Vector([0]*3) - for pt in [newmesh.verts[v1],newmesh.verts[v2],newmesh.verts[v3],newmesh.verts[v4]]: - center += pt.co - center = center/4 - prot = randnum(minimumheight,maximumheight) - tempface = extrude(center,currface.no,prot,v1,v2,v4,v3,selectface2) - if makedoodads == 1: - if doodonselectedfaces == 1: - if currface.sel: - tempmesh = NMesh.GetRaw() - tempmesh = defaultdoodads.createDoodad(doodadArray, tempface, doodadminsize, doodadmaxsize, doodadminheight,doodadmaxheight, selectdoodad, doodadminperface, doodadmaxperface, doodadfacepercent) - newmesh.verts.extend(tempmesh.verts) - newmesh.faces.extend(tempmesh.faces) - else: - tempmesh = NMesh.GetRaw() - tempmesh = defaultdoodads.createDoodad(doodadArray, tempface, doodadminsize, doodadmaxsize, doodadminheight,doodadmaxheight, selectdoodad, doodadminperface, doodadmaxperface, doodadfacepercent) - newmesh.verts.extend(tempmesh.verts) - newmesh.faces.extend(tempmesh.faces) - if orientation < 0.5: - face = Face([newmesh.verts[p0],newmesh.verts[p1],newmesh.verts[v3]]) - if thereAreMats == 1: - if reassignMats == 0 or protSideMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = protSideMat-1 - newmesh.faces.append(face) - face = Face([newmesh.verts[p2],newmesh.verts[p3],newmesh.verts[v4]]) - if thereAreMats == 1: - if reassignMats == 0 or protSideMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = protSideMat-1 - newmesh.faces.append(face) - else: - face = Face([newmesh.verts[p1],newmesh.verts[p2],newmesh.verts[v3]]) - if thereAreMats == 1: - if reassignMats == 0 or protSideMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = protSideMat-1 - newmesh.faces.append(face) - face = Face([newmesh.verts[p3],newmesh.verts[p0],newmesh.verts[v4]]) - if thereAreMats == 1: - if reassignMats == 0 or protSideMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = protSideMat-1 - newmesh.faces.append(face) - - elif subfaces == 3: - layer2inds = [] - layer2verts = [] - orientation = int(round(randnum(0,1))) - rotation = int(round(randnum(0,1))) - p1 = currface.v[orientation] - p2 = currface.v[orientation + 1] - p3 = ((p2.co - p1.co)/2) + p1.co - ve1 = Vert(p3[0],p3[1],p3[2]) - ve1.sel = 0 - p1 = currface.v[2 + orientation] - if orientation < 0.5: - p2 = currface.v[3] - else: - p2 = currface.v[0] - p3 = ((p2.co - p1.co)/2) + p1.co - ve2 = Vert(p3[0],p3[1],p3[2]) - ve2.sel = 0 - fp = [] - - #make first protrusion - if rotation < 0.5: - if orientation < 0.5: - verti = currface.v[3] - fp.append(verti.index) - v1 = verti.index - verti = currface.v[0] - fp.append(verti.index) - v2 = verti.index - layer2verts.extend([newmesh.verts[currface.v[1].index],newmesh.verts[currface.v[2].index]]) - else: - verti = currface.v[0] - fp.append(verti.index) - v1 = verti.index - verti = currface.v[1] - fp.append(verti.index) - v2 = verti.index - layer2verts.extend([newmesh.verts[currface.v[2].index],newmesh.verts[currface.v[3].index]]) - newmesh.verts.append(ve1) - newmesh.verts.append(ve2) - index = len(newmesh.verts) - 2 - v4 = index + 1 - v3 = index - center = Vector([0]*3) - for pt in [newmesh.verts[v1],newmesh.verts[v2],newmesh.verts[v3],newmesh.verts[v4]]: - center += pt.co - center = center/4 - prot = randnum(minimumheight,maximumheight) - layer2inds.extend([v3,v4]) - tempface = extrude(center,currface.no,prot,v1,v2,v3,v4,selectface3) - if makedoodads == 1: - if doodonselectedfaces == 1: - if currface.sel: - tempmesh = NMesh.GetRaw() - tempmesh = defaultdoodads.createDoodad(doodadArray, tempface, doodadminsize, doodadmaxsize, doodadminheight,doodadmaxheight, selectdoodad, doodadminperface, doodadmaxperface, doodadfacepercent) - newmesh.verts.extend(tempmesh.verts) - newmesh.faces.extend(tempmesh.faces) - else: - tempmesh = NMesh.GetRaw() - tempmesh = defaultdoodads.createDoodad(doodadArray, tempface, doodadminsize, doodadmaxsize, doodadminheight,doodadmaxheight, selectdoodad, doodadminperface, doodadmaxperface, doodadfacepercent) - newmesh.verts.extend(tempmesh.verts) - newmesh.faces.extend(tempmesh.faces) - #Still first protrusion - else: - if orientation < 0.5: - verti = currface.v[1] - fp.append(verti.index) - v1 = verti.index - verti = currface.v[2] - fp.append(verti.index) - v2 = verti.index - layer2verts.extend([newmesh.verts[currface.v[0].index],newmesh.verts[currface.v[3].index]]) - else: - verti = currface.v[2] - fp.append(verti.index) - v1 = verti.index - verti = currface.v[3] - fp.append(verti.index) - v2 = verti.index - layer2verts.extend([newmesh.verts[currface.v[1].index],newmesh.verts[currface.v[0].index]]) - newmesh.verts.append(ve2) - newmesh.verts.append(ve1) - index = len(newmesh.verts) - 2 - v4 = index - v3 = index + 1 - center = Vector([0]*3) - for pt in [newmesh.verts[v1],newmesh.verts[v2],newmesh.verts[v3],newmesh.verts[v4]]: - center += pt.co - center = center/4 - prot = randnum(minimumheight,maximumheight) - layer2inds.extend([index, index +1]) - tempface = extrude(center,currface.no,prot,v1,v2,v4,v3,selectface3) - if makedoodads == 1: - if doodonselectedfaces == 1: - if currface.sel: - tempmesh = NMesh.GetRaw() - tempmesh = defaultdoodads.createDoodad(doodadArray, tempface, doodadminsize, doodadmaxsize, doodadminheight,doodadmaxheight, selectdoodad, doodadminperface, doodadmaxperface, doodadfacepercent) - newmesh.verts.extend(tempmesh.verts) - newmesh.faces.extend(tempmesh.faces) - else: - tempmesh = NMesh.GetRaw() - tempmesh = defaultdoodads.createDoodad(doodadArray, tempface, doodadminsize, doodadmaxsize, doodadminheight,doodadmaxheight, selectdoodad, doodadminperface, doodadmaxperface, doodadfacepercent) - newmesh.verts.extend(tempmesh.verts) - newmesh.faces.extend(tempmesh.faces) - - #split next rect(pre-arranged, no orientation crud)--make flag in extruder for only one existing vert in mesh - p1 = newmesh.verts[layer2inds[0]] - p2 = newmesh.verts[layer2inds[1]] - p3 = ((p2.co - p1.co)/2) + p1.co - ve3 = Vert(p3[0],p3[1],p3[2]) - ve3.sel = 0 - p1 = layer2verts[0] - p2 = layer2verts[1] - p3 = ((p2.co - p1.co)/2) + p1.co - ve4 = Vert(p3[0],p3[1],p3[2]) - ve4.sel = 0 - newmesh.verts.append(ve3) - newmesh.verts.append(ve4) - tempindex = len(newmesh.verts) - 2 - v5 = tempindex - v6 = tempindex + 1 - verti = layer2verts[0] - t0 = verti.index - center = Vector([0]*3) - for pt in [newmesh.verts[v5],newmesh.verts[v6],newmesh.verts[t0],newmesh.verts[v3]]: - center += pt.co - center = center/4 - prot = randnum(minimumheight,maximumheight) - if rotation < 0.5: flino = 1 - else: flino = 0 - tempface = extrude(center,currface.no,prot,v3,v5,v6,t0,selectface3,flino) - if makedoodads == 1: - if doodonselectedfaces == 1: - if currface.sel: - tempmesh = NMesh.GetRaw() - tempmesh = defaultdoodads.createDoodad(doodadArray, tempface, doodadminsize, doodadmaxsize, doodadminheight,doodadmaxheight, selectdoodad, doodadminperface, doodadmaxperface, doodadfacepercent) - newmesh.verts.extend(tempmesh.verts) - newmesh.faces.extend(tempmesh.faces) - tempmesh = NMesh.GetRaw() - tempmesh = defaultdoodads.createDoodad(doodadArray, tempface, doodadminsize, doodadmaxsize, doodadminheight,doodadmaxheight, selectdoodad, doodadminperface, doodadmaxperface, doodadfacepercent) - newmesh.verts.extend(tempmesh.verts) - newmesh.faces.extend(tempmesh.faces) - if rotation < 0.5: - fpt = t0 - face = Face([newmesh.verts[fp[1]],newmesh.verts[fpt],newmesh.verts[v3]]) - if thereAreMats == 1: - if reassignMats == 0 or protSideMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = protSideMat-1 - newmesh.faces.append(face) - else: - fpt = t0 - face = Face([newmesh.verts[fp[0]],newmesh.verts[v3],newmesh.verts[fpt]]) - if thereAreMats == 1: - if reassignMats == 0 or protSideMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = protSideMat-1 - newmesh.faces.append(face) - verti = layer2verts[1] - tempindex = verti.index - center = Vector([0]*3) - for pt in [newmesh.verts[v5],newmesh.verts[v6],newmesh.verts[tempindex],newmesh.verts[v4]]: - center += pt.co - center = center/4 - prot = randnum(minimumheight,maximumheight) - tempface = extrude(center,currface.no,prot,v6,v5,v4,tempindex,selectface3,flino) - if makedoodads == 1: - if doodonselectedfaces == 1: - if currface.sel: - tempmesh = NMesh.GetRaw() - tempmesh = defaultdoodads.createDoodad(doodadArray, tempface, doodadminsize, doodadmaxsize, doodadminheight,doodadmaxheight, selectdoodad, doodadminperface, doodadmaxperface, doodadfacepercent) - newmesh.verts.extend(tempmesh.verts) - newmesh.faces.extend(tempmesh.faces) - else: - tempmesh = NMesh.GetRaw() - tempmesh = defaultdoodads.createDoodad(doodadArray, tempface, doodadminsize, doodadmaxsize, doodadminheight,doodadmaxheight, selectdoodad, doodadminperface, doodadmaxperface, doodadfacepercent) - newmesh.verts.extend(tempmesh.verts) - newmesh.faces.extend(tempmesh.faces) - if rotation < 0.5: - face = Face([newmesh.verts[tempindex],newmesh.verts[fp[0]],newmesh.verts[v4]]) - if thereAreMats == 1: - if reassignMats == 0 or protSideMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = protSideMat-1 - newmesh.faces.append(face) - face = Face([newmesh.verts[fpt],newmesh.verts[tempindex],newmesh.verts[v6]]) - if thereAreMats == 1: - if reassignMats == 0 or protSideMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = protSideMat-1 - newmesh.faces.append(face) - else: - face = Face([newmesh.verts[tempindex],newmesh.verts[v4],newmesh.verts[fp[1]]]) - if thereAreMats == 1: - if reassignMats == 0 or protSideMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = protSideMat-1 - newmesh.faces.append(face) - face = Face([newmesh.verts[tempindex],newmesh.verts[fpt],newmesh.verts[v6]]) - if thereAreMats == 1: - if reassignMats == 0 or protSideMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = protSideMat-1 - newmesh.faces.append(face) - - else: - #get all points - verti = currface.v[0] - p0 = verti.index - - verti = currface.v[1] - p1 = verti.index - - pt = ((newmesh.verts[p1].co - newmesh.verts[p0].co)/2) + newmesh.verts[p0].co - v1 = Vert(pt[0],pt[1],pt[2]) - v1.sel = 0 - - verti = currface.v[2] - p2 = verti.index - - pt = ((newmesh.verts[p2].co - newmesh.verts[p1].co)/2) + newmesh.verts[p1].co - v2 = Vert(pt[0],pt[1],pt[2]) - v2.sel = 0 - - verti = currface.v[3] - p3 = verti.index - - pt = ((newmesh.verts[p3].co - newmesh.verts[p2].co)/2) + newmesh.verts[p2].co - v3 = Vert(pt[0],pt[1],pt[2]) - v3.sel = 0 - - pt = ((newmesh.verts[p0].co - newmesh.verts[p3].co)/2) + newmesh.verts[p3].co - v4 = Vert(pt[0],pt[1],pt[2]) - v4.sel = 0 - - pt = ((v3.co - v1.co)/2) + v1.co - m = Vert(pt[0],pt[1],pt[2]) - m.sel = 0 - - #extrusion 1 - newmesh.verts.extend([v1,m,v4]) - index = len(newmesh.verts) - 3 - v1 = index - m = index + 1 - v4 = index + 2 - center = Vector([0]*3) - for pt in [newmesh.verts[p0],newmesh.verts[v1],newmesh.verts[m],newmesh.verts[v4]]: - center += pt.co - center = center/4 - prot = randnum(minimumheight,maximumheight) - tempface = extrude(center,currface.no,prot,p0,v1,m,v4,selectface4) - if makedoodads == 1: - if doodonselectedfaces == 1: - if currface.sel: - tempmesh = NMesh.GetRaw() - tempmesh = defaultdoodads.createDoodad(doodadArray, tempface, doodadminsize, doodadmaxsize, doodadminheight,doodadmaxheight, selectdoodad, doodadminperface, doodadmaxperface, doodadfacepercent) - newmesh.verts.extend(tempmesh.verts) - newmesh.faces.extend(tempmesh.faces) - else: - tempmesh = NMesh.GetRaw() - tempmesh = defaultdoodads.createDoodad(doodadArray, tempface, doodadminsize, doodadmaxsize, doodadminheight,doodadmaxheight, selectdoodad, doodadminperface, doodadmaxperface, doodadfacepercent) - newmesh.verts.extend(tempmesh.verts) - newmesh.faces.extend(tempmesh.faces) - - #extrusion 2 - newmesh.verts.extend([v2]) - index = len(newmesh.verts) - 1 - v2 = index - center = Vector([0]*3) - for pt in [newmesh.verts[m],newmesh.verts[v1],newmesh.verts[p1],newmesh.verts[v2]]: - center += pt.co - center = center/4 - prot = randnum(minimumheight,maximumheight) - tempface = extrude(center,currface.no,prot,m,v1,p1,v2,selectface4) - if makedoodads == 1: - if doodonselectedfaces == 1: - if currface.sel: - tempmesh = NMesh.GetRaw() - tempmesh = defaultdoodads.createDoodad(doodadArray, tempface, doodadminsize, doodadmaxsize, doodadminheight,doodadmaxheight, selectdoodad, doodadminperface, doodadmaxperface, doodadfacepercent) - newmesh.verts.extend(tempmesh.verts) - newmesh.faces.extend(tempmesh.faces) - else: - tempmesh = NMesh.GetRaw() - tempmesh = defaultdoodads.createDoodad(doodadArray, tempface, doodadminsize, doodadmaxsize, doodadminheight,doodadmaxheight, selectdoodad, doodadminperface, doodadmaxperface, doodadfacepercent) - newmesh.verts.extend(tempmesh.verts) - newmesh.faces.extend(tempmesh.faces) - - #extrusion 3 - newmesh.verts.extend([v3]) - index = len(newmesh.verts) - 1 - v3 = index - center = Vector([0]*3) - for pt in [newmesh.verts[m],newmesh.verts[v2],newmesh.verts[p2],newmesh.verts[v3]]: - center += pt.co - center = center/4 - prot = randnum(minimumheight,maximumheight) - tempface = extrude(center,currface.no,prot,m,v2,p2,v3,selectface4) - if makedoodads == 1: - if doodonselectedfaces == 1: - if currface.sel: - tempmesh = NMesh.GetRaw() - tempmesh = defaultdoodads.createDoodad(doodadArray, tempface, doodadminsize, doodadmaxsize, doodadminheight,doodadmaxheight, selectdoodad, doodadminperface, doodadmaxperface, doodadfacepercent) - newmesh.verts.extend(tempmesh.verts) - newmesh.faces.extend(tempmesh.faces) - else: - tempmesh = NMesh.GetRaw() - tempmesh = defaultdoodads.createDoodad(doodadArray, tempface, doodadminsize, doodadmaxsize, doodadminheight,doodadmaxheight, selectdoodad, doodadminperface, doodadmaxperface, doodadfacepercent) - newmesh.verts.extend(tempmesh.verts) - newmesh.faces.extend(tempmesh.faces) - - #extrusion 4 - center = Vector([0]*3) - for pt in [newmesh.verts[m],newmesh.verts[v3],newmesh.verts[p3],newmesh.verts[v4]]: - center += pt.co - center = center/4 - prot = randnum(minimumheight,maximumheight) - tempface = extrude(center,currface.no,prot,v4,m,v3,p3,selectface4) - if makedoodads == 1: - if doodonselectedfaces == 1: - if currface.sel: - tempmesh = NMesh.GetRaw() - tempmesh = defaultdoodads.createDoodad(doodadArray, tempface, doodadminsize, doodadmaxsize, doodadminheight,doodadmaxheight, selectdoodad, doodadminperface, doodadmaxperface, doodadfacepercent) - newmesh.verts.extend(tempmesh.verts) - newmesh.faces.extend(tempmesh.faces) - else: - tempmesh = NMesh.GetRaw() - tempmesh = defaultdoodads.createDoodad(doodadArray, tempface, doodadminsize, doodadmaxsize, doodadminheight,doodadmaxheight, selectdoodad, doodadminperface, doodadmaxperface, doodadfacepercent) - newmesh.verts.extend(tempmesh.verts) - newmesh.faces.extend(tempmesh.faces) - - face = Face([newmesh.verts[p0],newmesh.verts[p1],newmesh.verts[v1]]) - if thereAreMats == 1: - if reassignMats == 0 or protSideMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = protSideMat-1 - newmesh.faces.append(face) - face = Face([newmesh.verts[p1],newmesh.verts[p2],newmesh.verts[v2]]) - if thereAreMats == 1: - if reassignMats == 0 or protSideMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = protSideMat-1 - newmesh.faces.append(face) - face = Face([newmesh.verts[p2],newmesh.verts[p3],newmesh.verts[v3]]) - if thereAreMats == 1: - if reassignMats == 0 or protSideMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = protSideMat-1 - newmesh.faces.append(face) - face = Face([newmesh.verts[p3],newmesh.verts[p0],newmesh.verts[v4]]) - if thereAreMats == 1: - if reassignMats == 0 or protSideMat == 0: - face.materialIndex = currmat - else: - face.materialIndex = protSideMat-1 - newmesh.faces.append(face) - - #NMesh.PutRaw(newmesh) - if deselface == 1: - for unvert in origmesh.verts: - newmesh.verts[unvert.index].sel = 0 - if makenewobj == 1: - newobj = origobj.__copy__() - newobj.link(newmesh) - scene = Blender.Scene.GetCurrent() - scene.objects.link(newobj) - origobj.sel = 0 - else: - origobj.link(newmesh) - - #Return to Editmode if previously in it - if editmode: Window.EditMode(1) - -####################### gui ###################### -from Blender.BGL import * -from Blender.Draw import * - -def ErrorText(errortext): - Window.WaitCursor(0) - Text(errortext) - PupMenu("ERROR: %s" % errortext.lower()) - -#Global Buttons -makenewobject = Create(makenewobj) -messagetext = Create(errortext) - -#Protrusion Buttons -doprots = Create(makeprots) -facechange = Create(faceschangedpercent*100) -minheight = Create(minimumheight) -maxheight = Create(maximumheight) -sub1 = Create(subface1) -sub2 = Create(subface2) -sub3 = Create(subface3) -sub4 = Create(subface4) -mintaper = Create(minimumtaperpercent*100) -maxtaper = Create(maximumtaperpercent*100) -useselected = Create(useselectedfaces) -selface1 = Create(selectface1) -selface2 = Create(selectface2) -selface3 = Create(selectface3) -selface4 = Create(selectface4) -deselectvertices = Create(deselface) -#selectbyverts = Create(vertselected) - -#Doodad Buttons -dodoodads = Create(makedoodads) -doodadfacechange = Create(doodadfacepercent*100) -seldoodad = Create(selectdoodad) -onprot = Create(onlyonprotrusions) -dood1 = Create(doodad1) -dood2 = Create(doodad2) -dood3 = Create(doodad3) -dood4 = Create(doodad4) -dood5 = Create(doodad5) -dood6 = Create(doodad6) -doodadminamount = Create(doodadminperface) -doodadmaxamount = Create(doodadmaxperface) -doodsizemin = Create(doodadminsize*100) -doodsizemax = Create(doodadmaxsize*100) -doodheightmin = Create(doodadminheight) -doodheightmax = Create(doodadmaxheight) -doodonselface = Create(doodonselectedfaces) -seldoodtop = Create(selectdoodadtoponly) - -#Material Buttons -assignNewMats = Create(reassignMats) -replProtSideIndex = Create(protSideMat) -replProtTopIndex = Create(protTopMat) -replDoodSideIndex = Create(doodSideMat) -replDoodTopIndex = Create(doodTopMat) - -# Events -EVENT_NONE = 1 -EVENT_DISCOMBOBULATE = 2 -EVENT_EXIT = 3 - -# Additions for moving gui -hadd = 0 -wadd = 0 -thadd = 410 -phadd = 245 -pwadd = 0 -dhadd = 55 -dwadd = 0 -ghadd = 10 -gwadd = 0 -mhadd = 55 -mwadd = 312 - -def colorbox(x,y,xright,bottom): - glColor3f(0.75, 0.75, 0.75) - glRecti(x + 1, y + 1, xright - 1, bottom - 1) - -firstDraw = 1 - -def draw(): - - #Protrusions - global doprots - global facechange - global minheight - global maxheight - global sub1 - global sub2 - global sub3 - global sub4 - global mintaper - global maxtaper - global useselected - global selface1 - global selface2 - global selface3 - global selface4 - global deselectvertices - #global selectbyverts - - #Doodads - global dodoodads - global doodadfacechange - global seldoodad - global onprot - global dood1 - global dood2 - global dood3 - global dood4 - global dood5 - global dood6 - global doodadminamount - global doodadmaxamount - global doodsizemin - global doodsizemax - global doodheightmin - global doodheightmax - global doodonselface - global seldoodtop - - #Materials - global assignNewMats - global replProtSideIndex - global replProtTopIndex - global replDoodSideIndex - global replDoodTopIndex - - #Global Settings - global makenewobject - global messagetext - global errortext - global EVENT_NONE,EVENT_DRAW,EVENT_EXIT,EVENT_UP,EVENT_DOWN,EVENT_LEFT,EVENT_RIGHT - - # Additions for moving gui - global hadd - global wadd - global thadd - global phadd - global pwadd - global dhadd - global dwadd - global ghadd - global gwadd - global mhadd - global mwadd - - #This is for creating the initial layout - global firstDraw - if(firstDraw == 1): - if(((Window.GetAreaSize()[1])*1.7) < Window.GetAreaSize()[0]): - thadd = 180 - phadd = 10 - dhadd = 10 - mhadd = 55 - ghadd = 10 - pwadd = 0 - dwadd = 305 - mwadd = 610 - gwadd = 610 - else: - thadd = 505 - phadd = 346 - dhadd = 160 - mhadd = 56 - ghadd = 10 - pwadd = 0 - dwadd = 0 - mwadd = 0 - gwadd = 0 - firstDraw = 0 - - - #Title :420high - glClearColor(0.6, 0.6, 0.6, 1.0) - glClear(GL_COLOR_BUFFER_BIT) - glColor3f(0.0,0.0,0.0) - glRasterPos2d(8+wadd, thadd+hadd) - Text("Discombobulator v2.1b") - - #Protrusion - colorbox(8+pwadd+wadd,150+phadd+hadd,312+pwadd+wadd,phadd-5+hadd) - glColor3f(0.0,0.0,0.0) - glRasterPos2d(12+pwadd+wadd, 140+phadd+hadd) - Text("Protrusions:") - doprots = Toggle("Make Protrusions",EVENT_NONE,12+pwadd+wadd,117+phadd+hadd,145,18,doprots.val,"Make Protrusions?") - facechange = Number("Face %: ",EVENT_NONE,162+pwadd+wadd,117+phadd+hadd,145,18,facechange.val,0,100,"Percentage of faces that will grow protrusions") - useselected = Toggle("Only selected faces",EVENT_NONE,12+pwadd+wadd,97+phadd+hadd,145,18,useselected.val,"If on, only selected faces will be modified") - deselectvertices = Toggle("Deselect Selected",EVENT_NONE,162+pwadd+wadd,97+phadd+hadd,145,18,deselectvertices.val,"Deselects any selected vertex except for ones selected by \"Select Tops\"") - - #Protrusion properties - glColor3f(0.0,0.0,0.0) - glRasterPos2d(12+pwadd+wadd, 80+phadd+hadd) - Text("Protrusion Properties:") - BeginAlign() - minheight = Number("Min Height: ",EVENT_NONE,12+pwadd+wadd,57+phadd+hadd,145,18,minheight.val,-100.0,100.0,"Minimum height of any protrusion") - maxheight = Number("Max Height: ",EVENT_NONE,162+pwadd+wadd,57+phadd+hadd,145,18,maxheight.val,-100.0,100.0,"Maximum height of any protrusion") - EndAlign() - BeginAlign() - mintaper = Number("Min Taper %: ",EVENT_NONE,12+pwadd+wadd,37+phadd+hadd,145,18,mintaper.val,0,100,"Minimum taper percentage of protrusion") - maxtaper = Number("Max Taper %: ",EVENT_NONE,162+pwadd+wadd,37+phadd+hadd,145,18,maxtaper.val,0,100,"Maximum taper percentage of protrusion") - EndAlign() - glRasterPos2d(19+pwadd+wadd, 22+phadd+hadd) - Text("Number of protrusions:") - BeginAlign() - sub1 = Toggle("1",EVENT_NONE,12+pwadd+wadd,phadd+hadd,34,18,sub1.val,"One Protrusion") - sub2 = Toggle("2",EVENT_NONE,48+pwadd+wadd,phadd+hadd,34,18,sub2.val,"Two Protrusions") - sub3 = Toggle("3",EVENT_NONE,84+pwadd+wadd,phadd+hadd,34,18,sub3.val,"Three Protrusions") - sub4 = Toggle("4",EVENT_NONE,120+pwadd+wadd,phadd+hadd,34,18,sub4.val,"Four Protrusions") - EndAlign() - glRasterPos2d(195+pwadd+wadd, 22+phadd+hadd) - Text("Select tops of:") - BeginAlign() - selface1 = Toggle("1",EVENT_NONE,165+pwadd+wadd,phadd+hadd,34,18,selface1.val,"Select the tip of the protrusion when it is created") - selface2 = Toggle("2",EVENT_NONE,201+pwadd+wadd,phadd+hadd,34,18,selface2.val,"Select the tips of each protrusion when they are created") - selface3 = Toggle("3",EVENT_NONE,237+pwadd+wadd,phadd+hadd,34,18,selface3.val,"Select the tips of each protrusion when they are created") - selface4 = Toggle("4",EVENT_NONE,273+pwadd+wadd,phadd+hadd,34,18,selface4.val,"Select the tips of each protrusion when they are created") - EndAlign() - #Doodads - colorbox(8+dwadd+wadd,175+dhadd+hadd,312+dwadd+wadd,dhadd-5+hadd) - glColor3f(0.0,0.0,0.0) - glRasterPos2d(12+dwadd+wadd, 165+dhadd+hadd) - Text("Doodads:") - BeginAlign() - dood1 = Toggle("1 Box",EVENT_NONE,12+dwadd+wadd,142+dhadd+hadd,45,18,dood1.val,"Creates a rectangular box") - dood2 = Toggle("2 Box",EVENT_NONE,61+dwadd+wadd,142+dhadd+hadd,45,18,dood2.val,"Creates 2 side-by-side rectangular boxes") - dood3 = Toggle("3 Box",EVENT_NONE,110+dwadd+wadd,142+dhadd+hadd,45,18,dood3.val,"Creates 3 side-by-side rectangular boxes") - EndAlign() - BeginAlign() - dood4 = Toggle("\"L\"",EVENT_NONE,164+dwadd+wadd,142+dhadd+hadd,45,18,dood4.val,"Creates a Tetris-style \"L\" shape") - dood5 = Toggle("\"T\"",EVENT_NONE,213+dwadd+wadd,142+dhadd+hadd,45,18,dood5.val,"Creates a Tetris-style \"T\" shape") - dood6 = Toggle("\"S\"",EVENT_NONE,262+dwadd+wadd,142+dhadd+hadd,45,18,dood6.val,"Creates a sort-of \"S\" or \"Z\" shape") - EndAlign() - dodoodads = Toggle("Make Doodads",EVENT_NONE,12+dwadd+wadd,120+dhadd+hadd,145,18,dodoodads.val,"Make Doodads?") - doodadfacechange = Number("Face %: ",EVENT_NONE,162+dwadd+wadd,120+dhadd+hadd,145,18,doodadfacechange.val,0,100,"Percentage of faces that will gain doodads") - seldoodad = Toggle("Select Doodads",EVENT_NONE,12+dwadd+wadd,100+dhadd+hadd,145,18,seldoodad.val,"Selects doodads when they are created") - seldoodtop = Toggle("Only Select Tops",EVENT_NONE,162+dwadd+wadd,100+dhadd+hadd,145,18,seldoodtop.val,"Only Selects tops of doodads when\"Select Doodads\" is on") - doodonselface = Toggle("Only selected faces",EVENT_NONE,12+dwadd+wadd,80+dhadd+hadd,145,18,doodonselface.val,"Only create doodads on selected faces") - onprot = Toggle("Only on Protrusions",EVENT_NONE,162+dwadd+wadd,80+dhadd+hadd,145,18,onprot.val,"Only place doodads on protrusions") - - #Doodad Properties - glColor3f(0.0,0.0,0.0) - glRasterPos2d(12+dwadd+wadd, 63+dhadd+hadd) - Text("Doodad Properties:") - BeginAlign() - doodadminamount = Number("Min Amount: ",EVENT_NONE,12+dwadd+wadd,40+dhadd+hadd,145,18,doodadminamount.val,0,100,"Minimum number of doodads per face") - doodadmaxamount = Number("Max Amount: ",EVENT_NONE,162+dwadd+wadd,40+dhadd+hadd,145,18,doodadmaxamount.val,0,100,"Maximum number of doodads per face") - EndAlign() - BeginAlign() - doodheightmin = Number("Min Height: ",EVENT_NONE,12+dwadd+wadd,20+dhadd+hadd,145,18,doodheightmin.val,0.0,100.0,"Minimum height of any doodad") - doodheightmax = Number("Max Height: ",EVENT_NONE,162+dwadd+wadd,20+dhadd+hadd,145,18,doodheightmax.val,0.0,100.0,"Maximum height of any doodad") - EndAlign() - BeginAlign() - doodsizemin = Number("Min Size %: ",EVENT_NONE,12+dwadd+wadd,dhadd+hadd,145,18,doodsizemin.val,0.0,100.0,"Minimum size of any doodad in percentage of face") - doodsizemax = Number("Max Size %: ",EVENT_NONE,162+dwadd+wadd,dhadd+hadd,145,18,doodsizemax.val,0.0,100.0,"Maximum size of any doodad in percentage of face") - EndAlign() - - #Materials - colorbox(8+mwadd+wadd,93+mhadd+hadd,312+mwadd+wadd,mhadd-5+hadd) - glColor3f(0.0,0.0,0.0) - glRasterPos2d(12+mwadd+wadd, 83+mhadd+hadd) - Text("Materials:") - glRasterPos2d(12+mwadd+wadd, 43+mhadd+hadd) - Text("Assigned Material Indices:") - assignNewMats = Toggle("Assign materials by part",EVENT_NONE,32+mwadd+wadd,60+mhadd+hadd,256,18,assignNewMats.val,"Otherwise, previous materials will be preserved") - replProtSideIndex = Number("Protrusion Sides:",EVENT_NONE,12+mwadd+wadd,20+mhadd+hadd,145,18,replProtSideIndex.val,0,16,"Material index assigned to sides of protrusions") - replProtTopIndex = Number("Protrusion Tops:",EVENT_NONE,162+mwadd+wadd,20+mhadd+hadd,145,18,replProtTopIndex.val,0,16,"Material index assigned to tops of protrusions") - replDoodSideIndex = Number("Doodad Sides:",EVENT_NONE,12+mwadd+wadd,mhadd+hadd,145,18,replDoodSideIndex.val,0,16,"Material index assigned to sides of doodads") - replDoodTopIndex = Number("Doodad Tops:",EVENT_NONE,162+mwadd+wadd,mhadd+hadd,145,18,replDoodTopIndex.val,0,16,"Material index assigned to tops and bottoms of doodads") - - #Global Parts - colorbox(8+gwadd+wadd,35+ghadd+hadd,312+gwadd+wadd,ghadd-5+hadd) - glColor3f(1.0,0.0,0.0) - glRasterPos2d(12+gwadd+wadd,25+ghadd+hadd) - messagetext = Text(errortext) - glColor3f(0.0,0.0,0.0) - makenewobject = Toggle("Copy Before Modifying",EVENT_NONE,162+gwadd+wadd,ghadd+hadd,145,18,makenewobject.val,"If selected, the original object will be copied before it is changed") - Button("Discombobulate",EVENT_DISCOMBOBULATE,12+gwadd+wadd,ghadd+hadd,100,18) - Button("Exit",EVENT_EXIT,120+gwadd+wadd,ghadd+hadd,30,18) - -def event(evt, val): - global wadd - global hadd - - if (evt == RIGHTARROWKEY and val): - wadd = wadd + 20 - Redraw(1) - if (evt == LEFTARROWKEY and val): - wadd = wadd - 20 - Redraw(1) - if (evt == UPARROWKEY and val): - hadd = hadd + 20 - Redraw(1) - if (evt == DOWNARROWKEY and val): - hadd = hadd - 20 - Redraw(1) - if (evt == QKEY and not val): - Exit() - -def bevent(evt): - - #Protrusions - global doprots - global facechange - global minheight - global maxheight - global sub1 - global sub2 - global sub3 - global sub4 - global mintaper - global maxtaper - global useselected - global selface1 - global selface2 - global selface3 - global selface4 - global deselectvertices - #global selectbyverts - - #Doodads - global dodoodads - global doodadfacechange - global seldoodad - global onprot - global dood1 - global dood2 - global dood3 - global dood4 - global dood5 - global dood6 - global doodadminamount - global doodadmaxamount - global doodsizemin - global doodsizemax - global doodheightmin - global doodheightmax - global doodonselface - global seldoodtop - - #Materials - global assignNewMats - global replProtSideIndex - global replProtTopIndex - global replDoodSideIndex - global replDoodTopIndex - - #Global Settings - global makenewobject - global messagetext - global errortext - global EVENT_NONE,EVENT_DRAW,EVENT_EXIT - - ######### Manages GUI events - if evt==EVENT_EXIT: - Exit() - elif evt==EVENT_DISCOMBOBULATE: - Window.WaitCursor(1) - setProtrusionValues(doprots.val,facechange.val/100,minheight.val,maxheight.val,sub1.val,sub2.val,sub3.val,sub4.val,mintaper.val/100,maxtaper.val/100,useselected.val,selface1.val,selface2.val,selface3.val,selface4.val,deselectvertices.val) - setDoodadValues(dodoodads.val,doodadfacechange.val/100,seldoodad.val,onprot.val,dood1.val,dood2.val,dood3.val,dood4.val,dood5.val,dood6.val,doodadminamount.val,doodadmaxamount.val,doodsizemin.val/100,doodsizemax.val/100,doodheightmin.val,doodheightmax.val,doodonselface.val,seldoodtop.val) - setOtherValues(makenewobject.val,assignNewMats.val,replProtSideIndex.val,replProtTopIndex.val,replDoodSideIndex.val,replDoodTopIndex.val) - discombobulate() - Window.WaitCursor(0) - Blender.Redraw() - -Register(draw, event, bevent) diff --git a/release/scripts/envelope_symmetry.py b/release/scripts/envelope_symmetry.py deleted file mode 100644 index a72e8c060b4..00000000000 --- a/release/scripts/envelope_symmetry.py +++ /dev/null @@ -1,174 +0,0 @@ -#!BPY - -""" -Name: 'Envelope Symmetry' -Blender: 234 -Group: 'Animation' -Tooltip: 'Make envelope symmetrical' -""" - -__author__ = "Jonas Petersen" -__url__ = ("blender", "blenderartists.org", "Script's homepage, http://www.mindfloaters.de/blender/", "thread at blender.org, http://www.blender.org/modules.php?op=modload&name=phpBB2&file=viewtopic&t=4858 ") -__version__ = "0.9 2004-11-10" -__doc__ = """\ -This script creates perfectly symmetrical envelope sets. It is part of the -envelop assignment tools. - -"Envelopes" are Mesh objects with names following this naming convention: - -<bone name>:<float value> - -Please check the script's homepage and the thread at blender.org (last link button above) for more info. - -For this version users need to edit the script code to change default options. -""" - -# -------------------------------------------------------------------------- -# "Envelope Symmetry" by Jonas Petersen -# Version 0.9 - 10th November 2004 - first public release -# -------------------------------------------------------------------------- -# -# A script for creating perfectly symmetrical envelope sets. It is -# part of the envelope assignment tool. -# -# It is available in Object Mode via the menu item: -# -# Object -> Scripts -> Envelope Symmetry -# -# With default settings it will: -# -# - Look for bones -# -# Find the latest version at: http://www.mindfloaters.de/blender/ -# -# -------------------------------------------------------------------------- -# $Id$ -# -------------------------------------------------------------------------- -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Copyright (C) 2004: Jonas Petersen, jonas at mindfloaters dot de -# -# 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 ***** - -# -------------------------------------------------------------------------- -# CONFIGURATION -# -------------------------------------------------------------------------- - -# Note: Theses values will later be editable via a gui interface -# within Blender. - -# The suffix for the reference and opposite envelope. -# The configuration of of the opposite envelope will be overwritten by -# the configuration of the reference envelope (shape, position, bone, weight). -# The default is REF_SUFFIX = '.L' and OPP_SUFFIX = '.R'. -REF_SUFFIX = '.R' -OPP_SUFFIX = '.L' - -# MIRROR_AXIS defines the axis in which bones are mirrored/aligned. -# Values: -# 0 for X (default) -# 1 for Y -# 2 for Z -MIRROR_AXIS = 0 - -# SEPARATOR is the character used to delimit the bone name and the weight -# in the envelope name. -SEPARATOR = ":" - -# -------------------------------------------------------------------------- -# END OF CONFIGURATION -# -------------------------------------------------------------------------- - -import Blender, math, sys -from Blender import Mathutils -from BPyNMesh import * - -def flipFace(v): - if len(v) == 3: v[0], v[1], v[2] = v[2], v[1], v[0] - elif len(v) == 4: v[0], v[1], v[2], v[3] = v[3], v[2], v[1], v[0] - -# return object with given object name (with variable parts) and mesh name -def getObjectByName(obj_name, mesh_name): - for obj in Blender.Scene.GetCurrent().objects: - if obj.type == "Mesh": -# if obj.getName()[0:len(obj_name)] == obj_name and obj.getData().name == mesh_name: - # use only mesh_name so bone name and weight (in the envelope name) - # can be changed by the user and mirrored by the script. - if obj.getData(name_only=1) == mesh_name: - return obj - return False - -SUFFIX_LEN = len(REF_SUFFIX); - -Blender.Window.EditMode(0) - -count = 0 -for obj in Blender.Scene.GetCurrent().objects: - if obj.type != 'Mesh': - continue - - count += 1 - name = obj.name - pos = name.find(SEPARATOR) - if (pos > -1): - ApplySizeAndRotation(obj) - - base_name = name[0:pos-SUFFIX_LEN] - suffix = name[pos-SUFFIX_LEN:pos] - weight = name[pos:len(name)] # the SEPARATOR following a float value - - if suffix == REF_SUFFIX: - mesh = obj.getData() - mirror_name = base_name + OPP_SUFFIX + weight - mirror_mesh_name = mesh.name + ".mirror" - - mirror_obj = getObjectByName(base_name + OPP_SUFFIX, mirror_mesh_name) - - if mirror_obj: - - # update vertices - - mirror_mesh = mirror_obj.getData() - for i in xrange(len(mesh.verts)): - org = mesh.verts[i] - mir = mirror_mesh.verts[i] - mir.co[0], mir.co[1], mir.co[2] = org.co[0], org.co[1], org.co[2] - mir.co[MIRROR_AXIS] *= -1 - - mirror_mesh.update() - else: - - # create mirror object - - mirror_mesh = obj.data - for face in mirror_mesh.faces: - flipFace(face.v) - for vert in mirror_mesh.verts: - vert.co[MIRROR_AXIS] *= -1 - - mirror_obj = Blender.NMesh.PutRaw(mirror_mesh, mirror_mesh_name) - - # update name, drawType and location - - mirror_obj.setName(mirror_name) - mirror_obj.drawType = obj.drawType - - loc = [obj.LocX, obj.LocY, obj.LocZ] - loc[MIRROR_AXIS] *= -1 - mirror_obj.setLocation(loc) - -Blender.Window.EditMode(0) diff --git a/release/scripts/export-iv-0.1.py b/release/scripts/export-iv-0.1.py deleted file mode 100644 index 647dd9c5518..00000000000 --- a/release/scripts/export-iv-0.1.py +++ /dev/null @@ -1,304 +0,0 @@ -#!BPY - -""" -Name: 'OpenInventor (.iv)...' -Blender: 236 -Group: 'Export' -Tip: 'Export to OpenInventor file format. (.iv)' -""" -__author__ = ("Radek Barton") -__url__ = ["http://blackhex.no-ip.org/"] -__email__ = ["scripts"] -__version__ = "0.1" - - -__bpydoc__ = """\ -This script exports to the Open Inventor format. - -Usage: - -Run this script from "File->Export" menu. - -Note: -""" -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Script copyright (C) Radek Barton -# -# 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 ***** -# - -import Blender -math_pi= 3.1415926535897931 - -def WriteHeader(file): - file.write("#Inventor V2.1 ascii\n\n") - file.write("Separator\n") - file.write("{\n") - file.write(" ShapeHints\n") - file.write(" {\n") - file.write(" vertexOrdering COUNTERCLOCKWISE\n") - file.write(" }\n") - -def WriteFooter(file): - file.write("}\n") - -def WriteMesh(file, ob): - file.write(" Separator\n") - file.write(" {\n") - file.write(" # %s\n" % ob.name) - WriteMatrix(file, ob) - mesh = ob.getData() - WriteMaterials(file, mesh) - WriteTexture(file, mesh) - WriteNormals(file, mesh) - WriteVertices(file, mesh) - WriteFaces(file, mesh) - file.write(" }\n") - -def WriteMatrix(file, ob): - matrix = ob.getMatrix() - file.write(" MatrixTransform\n") - file.write(" {\n") - file.write(" matrix\n") - for line in matrix: - file.write(" %.6f %.6f %.6f %.6f\n" % (line[0], line[1], line[2], line[3])) - file.write(" }\n") - -def WriteColors(file, mesh): - file.write(" vertexProperty VertexProperty\n") - file.write(" {\n") - file.write(" orderedRGBA\n") - file.write(" [\n") - for face in mesh.faces: - for I in xrange(len(face)): - file.write(" 0x%02x%02x%02x%02x,\n" % (face.col[I].r, - face.col[I].g, face.col[I].b, face.col[I].a)) - file.write(" ]\n") - file.write(" materialBinding PER_VERTEX\n") - file.write(" }\n") - -def WriteMaterials(file, mesh): - if mesh.materials: - file.write(" Material\n") - file.write(" {\n") - file.write(" ambientColor\n") - file.write(" [\n") - for mat in mesh.materials: - file.write(" %.6f %.6f %.6f,\n" % (mat.mirCol[0], mat.mirCol[1], - mat.mirCol[2])) - file.write(" ]\n") - file.write(" diffuseColor\n") - file.write(" [\n") - for mat in mesh.materials: - file.write(" %.6f %.6f %.6f,\n" % (mat.rgbCol[0], mat.rgbCol[1], - mat.rgbCol[2])) - file.write(" ]\n") - file.write(" specularColor\n") - file.write(" [\n") - for mat in mesh.materials: - file.write(" %.6f %.6f %.6f,\n" % (mat.specCol[0] * mat.spec / 2.0, - mat.specCol[1] * mat.spec / 2.0, mat.specCol[2] * mat.spec / 2.0)) - file.write(" ]\n") - file.write(" emissiveColor\n") - file.write(" [\n") - for mat in mesh.materials: - file.write(" %.6f %.6f %.6f,\n" % (mat.rgbCol[0] * mat.emit, - mat.rgbCol[1] * mat.emit, mat.rgbCol[0] * mat.emit)) - file.write(" ]\n") - file.write(" shininess\n") - file.write(" [\n") - for mat in mesh.materials: - file.write(" %.6f,\n" % (mat.hard / 255.0)) - file.write(" ]\n") - file.write(" transparency\n") - file.write(" [\n") - for mat in mesh.materials: - file.write(" %.6f,\n" % (1.0 - mat.alpha)) - file.write(" ]\n") - file.write(" }\n") - file.write(" MaterialBinding\n") - file.write(" {\n") - file.write(" value PER_FACE_INDEXED\n") - file.write(" }\n") - -def WriteTexture(file, mesh): - texture = mesh.faces[0].image # BAD Ju Ju - if texture: - file.write(" Texture2\n") - file.write(" {\n") - file.write(' filename "%s"\n' % texture.getName()) - file.write(" }\n") - file.write(" TextureCoordinate2\n") - file.write(" {\n") - file.write(" point\n") - file.write(" [\n") - if mesh.hasVertexUV(): - for vert in mesh.verts: - file.write(" %s %s,\n" % (vert.uvco[0], vert.uvco[1])) - file.write(" ]\n") - file.write(" }\n") - file.write(" TextureCoordinateBinding\n") - file.write(" {\n") - file.write(" value PER_VERTEX_INDEXED\n") - file.write(" }\n") - elif mesh.hasFaceUV(): - for face in mesh.faces: - for uv in face.uv: - file.write(" %.6f %.6f,\n" % (uv[0], uv[1])) - file.write(" ]\n") - file.write(" }\n") - file.write(" TextureCoordinateBinding\n") - file.write(" {\n") - file.write(" value PER_VERTEX\n") - file.write(" }\n") - -def WriteVertices(file, mesh): - file.write(" Coordinate3\n") - file.write(" {\n") - file.write(" point\n") - file.write(" [\n") - for vert in mesh.verts: - file.write(" %.6f %.6f %.6f,\n" % (vert[0], vert[1], vert[2])) - file.write(" ]\n") - file.write(" }\n") - -def WriteNormals(file, mesh): - file.write(" Normal\n") - file.write(" {\n") - file.write(" vector\n") - file.write(" [\n") - - # make copy of vertex normals - normals = [] - for face in mesh.faces: - if len(face.v) in [3, 4]: - if face.smooth: - for v in face.v: - normals.append(v.no) - else: - for v in face.v: - normals.append(face.no) - - # write normals - for no in normals: - file.write(" %.6f %.6f %.6f,\n" % (no[0], no[1], no[2])) - file.write(" ]\n") - file.write(" }\n") - - # write way how normals are binded - file.write(" NormalBinding\n") - file.write(" {\n") - file.write(" value PER_VERTEX\n") - file.write(" }\n") - -def WriteFaces(file, mesh): - file.write(" IndexedFaceSet\n") - file.write(" {\n") - - # write vertex paint - if mesh.hasVertexColours(): - WriteColors(file, mesh) - - # write material indexes - file.write(" materialIndex\n") - file.write(" [\n") - for face in mesh.faces: - file.write(" %i,\n" % face.mat); - file.write(" ]\n") - - # write faces with coordinate indexes - file.write(" coordIndex\n") - file.write(" [\n") - for face in mesh.faces: - face_v= face.v - if len(face_v) == 3: - file.write(" %i, %i, %i, -1,\n" % (face_v[0].index, - face_v[1].index, face_v[2].index)) - elif len(face_v) == 4: - file.write(" %i, %i, %i, %i, -1,\n" % (face_v[0].index, - face_v[1].index, face_v[2].index, face_v[3].index)) - file.write(" ]\n") - file.write(" }\n") - - -def WriteCamera(file, ob): - camera = ob.getData(); - # perspective camera - if camera.type == 0: - file.write(" PerspectiveCamera\n") - file.write(" {\n") - file.write(" nearDistance %s\n" % (camera.clipStart)) - file.write(" farDistance %s\n" % (camera.clipEnd)) - file.write(" }\n") - # ortho camera - else: - print camera.type - -def WriteLamp(file, ob): - lamp = ob.getData(); - # spot lamp - if lamp.type == 2: - file.write(" SpotLight\n") - file.write(" {\n") - file.write(" intensity %s\n" % (lamp.energy / 10.0)) - file.write(" color %s %s %s\n" % (lamp.col[0], lamp.col[1], lamp.col[2])) - #file.write(" location %s\n" % ()) - #file.write(" direction %s\n" % ()) - file.write(" dropOffRate %s\n" % (lamp.spotBlend)) - file.write(" cutOffAngle %s\n" % (lamp.spotSize * math_pi / 180.0)) - file.write(" }\n") - -# script main function -def ExportToIv(file_name): - scene = Blender.Scene.GetCurrent() - file = open(file_name, "w") - - # make lists of individual ob types - meshes = [] - lamps = [] - cameras = [] - for ob in scene.objects: - obtype= ob.type - if obtype == "Mesh": - meshes.append(ob); - #elif obtype == "Lamp": - # lamps.append(ob); - #elif obtype == "Camera": - # cameras.append(ob); - #else: - # print "Exporting %s objects isn't supported!" % ob.type - - # write header, footer and groups of ob types - WriteHeader(file); - #for camera in cameras: - # WriteCamera(file, camera); - #for lamp in lamps: - # WriteLamp(file, lamp) - for mesh in meshes: - WriteMesh(file, mesh) - WriteFooter(file) - - file.close() - -def FileSelectorCB(file_name): - if not file_name.lower().endswith('.iv'): - file_name += '.iv' - ExportToIv(file_name) - -if __name__ == '__main__': - Blender.Window.FileSelector(FileSelectorCB, "Export IV", Blender.sys.makename(ext='.iv')) diff --git a/release/scripts/export_dxf.py b/release/scripts/export_dxf.py deleted file mode 100644 index 17f2132fbe8..00000000000 --- a/release/scripts/export_dxf.py +++ /dev/null @@ -1,3041 +0,0 @@ -#!BPY - -""" - Name: 'Autodesk DXF (.dxf/dwg)' - Blender: 249 - Group: 'Export' - Tooltip: 'Export geometry to DXF/DWG-r12 (Drawing eXchange Format).' -""" - -__version__ = "1.35 - 2009.06.18" -__author__ = "Remigiusz Fiedler (AKA migius)" -__license__ = "GPL" -__url__ = "http://wiki.blender.org/index.php/Scripts/Manual/Export/autodesk_dxf" -__bpydoc__ ="""The script exports Blender geometry to DXF format r12 version. - -Version %s -Copyright %s -License %s - -extern dependances: dxfLibrary.py, dxfColorMap.py (optionaly: DConvertCon.exe) - -CONTRIBUTORS: -Remigiusz Fiedler (AKA migius) -Alexandros Sigalas (AKA alxarch) -Stani Michiels (AKA stani) - -See the homepage for documentation. -url: %s - -IDEAs: -- HPGL output, usefull for correct scaled printing of 2d drawings - -TODO: -- export dupligroups and dupliverts as blocks (as option) -- optimize POLYFACE routine: remove double-vertices -- fix support for X,Y-rotated curves(to POLYLINEs): fix blender negative-matrix.invert() -- support hierarchies: groups, instances, parented structures -- support n/f-gons as POLYFACEs with invisible edges -- mapping materials to DXF-styles -- ProgressBar -- export rotation of Camera to VIEW/VPORT -- export parented Cameras to VIEW/VPORT -- wip: write drawing extends for automatic view positioning in CAD -- wip: fix text-objects in persp-projection -- wip: translate current 3D-View to *ACTIVE-VPORT -- wip: fix support Include-Duplis, cause not conform with INSERT-method - -History -v1.35 - 2009.06.18 by migius -- export multiple-instances of Curve-Objects as BLOCK/INSERTs -- added export Cameras (ortho and persp) to VPORTs, incl. clipping -- added export Cameras (ortho and persp) to VIEWs, incl. clipping -- export multiple-instances of Mesh-Objects as BLOCK/INSERTs -- on start prints dxfLibrary version -v1.34 - 2009.06.08 by migius -- export Lamps and Cameras as POINTs -- export passepartout for perspective projection -- added option for export objects only from visible layers -- optimized POLYFACE output: remove loose vertices in back-faces-mode -- cleaning code -- fix nasty bug in getExtrusion() -- support text-objects, also in ortho/persp-projection -- support XYmirrored 2d-curves to 2dPOLYLINEs -- support thickness and elevation for curve-objects -- fix extrusion 210-code (3d orientation vector) -- fix POLYFACE export, synchronized also dxfLibrary.py -- changed to the new 2.49 method Vector.cross() -- output style manager (first try) -v1.33 - 2009.05.25 by migius -- bugfix flipping normals in mirrored mesh-objects -- added UI-Button for future Shadow Generator -- support curve objects in projection-2d mode -- UI stuff: camera selector/manager -v1.32 - 2009.05.22 by migius -- debug mode for curve-objects: output redirect to Blender -- wip support 210-code(extrusion) calculation -- default settings for 2D and 3D export -v1.31 - 2009.05.18 by migius -- globals translated to GUI_A/B dictionary -- optimizing back-faces removal for "hidden-lines" mode -- presets for global location and scale (architecture) -- UI layout: scrollbars, pan with MMB/WHEEL, dynamic width -- new GUI with Draw.Register() from DXF-importer.py -v1.30 - 2008.12.14 by migius -- started work on GUI with Draw.Register() -v1.29 - 2009.04.11 by stani -- added DWG support, Stani Michiels idea for binding an extern DXF-DWG-converter -v1.28 - 2009.02.05 by Alexandros Sigalas (alxarch) -- added option to apply modifiers on exported meshes -- added option to also export duplicates (from dupliverts etc) -v1.28 - 2008.10.22 by migius -- workaround for PVert-bug on ubuntu (reported by Yorik) -- add support for FGons - ignore invisible_tagged edges -- add support for camera: ortho and perspective -v1.27 - 2008.10.07 by migius -- exclude Stani's DXF-Library to extern module -v1.26 - 2008.10.05 by migius -- add "hidden mode" substitut: back-faces removal -- add support for mesh ->POLYFACE -- optimized code for "Flat" procedure -v1.25 - 2008.09.28 by migius -- modif FACE class for r12 -- add mesh-polygon -> Bezier-curve converter (Yorik's code) -- add support for curves ->POLYLINEs -- add "3d-View to Flat" - geometry projection to XY-plane -v1.24 - 2008.09.27 by migius -- add start UI with preferences -- modif POLYLINE class for r12 -- changing output format from r9 to r12(AC1009) -v1.23 - 2008.09.26 by migius -- add finish message-box -v1.22 - 2008.09.26 by migius -- add support for curves ->LINEs -- add support for mesh-edges ->LINEs -v1.21 - 2008.06.04 by migius -- initial adaptation for Blender -v1.1 (20/6/2005) by Stani Michiels www.stani.be/python/sdxf -- Python library to generate dxf drawings -______________________________________________________________ -""" % (__author__,__version__,__license__,__url__) - -# -------------------------------------------------------------------------- -# Script copyright (C) 2008 Remigiusz Fiedler (AKA migius) -# -------------------------------------------------------------------------- -# ***** 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 ***** - - -import Blender -from Blender import Mathutils, Window, Scene, Draw, Camera, BezTriple -from Blender import Registry, Object, Mesh, Curve -import os -import subprocess - -try: - import dxfLibrary as DXF - #reload(DXF) - #reload(dxfLibrary) - #from dxfLibrary import * -except: - DXF=None - print "DXF-Exporter: error! found no dxfLibrary.py module in Blender script folder" - Draw.PupMenu("Error%t|found no dxfLibrary.py module in script folder") - - -import math -from math import atan, atan2, log10, sin, cos - -#pi = math.pi -#pi = 3.14159265359 -r2d = 180.0 / math.pi -d2r = math.pi / 180.0 -#note: d2r * angle == math.radians(angle) -#note: r2d * angle == math.degrees(angle) - - -#DEBUG = True #activates debug mode - - -#----globals------------------------------------------ -ONLYSELECTED = 1 # 0/1 = False/True -ONLYVISIBLE = 1 # ignore objects on invisible layers -POLYLINES = 1 # prefer POLYLINEs not LINEs -POLYFACES = 1 # prefer POLYFACEs not 3DFACEs -PROJECTION = 0 # output geometry will be projected to XYplane with Z=0.0 -HIDDEN_LINES = 0 #filter out hidden geometry -SHADOWS = 0 # sun/shadows simulation -CAMERA = 1 # selected camera index -PERSPECTIVE = 0 # projection (camera) type: perspective, opposite to orthographic -CAMERAVIEW = 0 # use camera for projection, opposite is 3d-view -INSTANCES = 1 # Export instances of Mesh/Curve as BLOCK/INSERTs on/off -APPLY_MODIFIERS = 1 -INCLUDE_DUPLIS = 0 -OUTPUT_DWG = 0 #optional save to DWG with extern converter - -G_SCALE = 1.0 #(0.0001-1000) global scaling factor for output dxf data -G_ORIGIN = [0.0,0.0,0.0] #global translation-vector (x,y,z) in Blender units -ELEVATION = 0.0 #standard elevation = coordinate Z value in Blender units - -BYBLOCK = 0 #DXF-attribute: assign property to BLOCK defaults -BYLAYER = None #256 #DXF-attribute: assign property to LAYER defaults -PREFIX = 'BF_' #used as prefix for DXF names -LAYERNAME_DEF = '' #default layer name -LAYERCOLOR_DEF = 7 #default layer color index -LAYERLTYPE_DEF = 0 #'CONTINUOUS' - default layer lineType -ENTITYLAYER_DEF = LAYERNAME_DEF #default entity color index -ENTITYCOLOR_DEF = BYLAYER #default entity color index -ENTITYLTYPE_DEF = BYLAYER #default entity lineType - -E_M = 0 -LAB = "scroll MMB/WHEEL . wip .. todo" #"*) parts under construction" -M_OBJ = 0 - -FILENAME_MAX = 180 #max length of path+file_name string (FILE_MAXDIR + FILE_MAXFILE) -NAMELENGTH_MAX = 80 #max_obnamelength in DXF, (limited to 256? ) -INIFILE_DEFAULT_NAME = 'exportDXF' -INIFILE_EXTENSION = '.ini' -INIFILE_HEADER = '#ExportDXF.py ver.1.0 config data' -INFFILE_HEADER = '#ExportDXF.py ver.1.0 analyze of DXF-data' - -BLOCKREGISTRY = {} # registry and map for BLOCKs -SCENE = None -WORLDX = Mathutils.Vector((1,0,0)) -WORLDY = Mathutils.Vector((0,1,0)) -WORLDZ = Mathutils.Vector((0,0,1)) - -AUTO = BezTriple.HandleTypes.AUTO -FREE = BezTriple.HandleTypes.FREE -VECT = BezTriple.HandleTypes.VECT -ALIGN = BezTriple.HandleTypes.ALIGN - - -#-------- DWG support ------------------------------------------ -extCONV_OK = True -extCONV = 'DConvertCon.exe' -extCONV_PATH = os.path.join(Blender.Get('scriptsdir'),extCONV) -if not os.path.isfile(extCONV_PATH): - extCONV_OK = False - extCONV_TEXT = 'DWG-Exporter: Abort, nothing done!|\ -Copy first %s into Blender script directory.|\ -More details in online Help.' %extCONV -else: - if not os.sys.platform.startswith('win'): - # check if Wine installed: - if subprocess.Popen(('which', 'winepath'), stdout=subprocess.PIPE).stdout.read().strip(): - extCONV_PATH = 'wine %s'%extCONV_PATH - else: - extCONV_OK = False - extCONV_TEXT = 'DWG-Exporter: Abort, nothing done!|\ -The external DWG-converter (%s) needs Wine installed on your system.|\ -More details in online Help.' %extCONV -#print 'extCONV_PATH = ', extCONV_PATH - - -#---------------------------------------------- -def updateMenuCAMERA(): - global CAMERAS - global MenuCAMERA - global MenuLIGHT - - scn = Scene.GetCurrent() - objs = scn.getChildren() - currcam = scn.getCurrentCamera() - if currcam: currcam = currcam.getName() - maincams = [] - MenuCAMERA = "Select Camera%t" - for cam in objs: - if cam.getType() == 'Camera': - if cam.getName()[0:4] != "Temp": - maincams.append(cam.getName()) - maincams.sort() - maincams.reverse() - CAMERAS = maincams - for i, cam in enumerate(CAMERAS): - if cam==currcam: - MenuCAMERA += "|* " + cam - else: MenuCAMERA += "| " + cam - MenuCAMERA += "|current 3d-View" - MenuLIGHT = "Select Sun%t| *todo" - - -#---------------------------------------------- -def updateCAMERA(): - global CAMERA, GUI_A - #CAMERA = 1 - scn = Scene.GetCurrent() - currcam = scn.getCurrentCamera() - if currcam: currcam = currcam.getName() - if currcam in CAMERAS: - CAMERA = CAMERAS.index(currcam)+1 - GUI_A['camera_selected'].val = CAMERA - -#---------------------------------------------- -def gotoCAMERA(): - cam = Object.Get(CAMERAS[CAMERA-1]) - #print 'deb: CAMERA, cam',CAMERA, cam - if cam.getType() != 'Camera': - sure = Draw.PupMenu("Info: %t| It is not a Camera Object.") - else: - scn = Scene.getCurrent() - scn.setCurrentCamera(cam) - Window.CameraView(0) - Window.Redraw() - updateMenuCAMERA() - - -#------- Duplicates support ---------------------------------------------- -def dupTest(object): - """ - Checks objects for duplicates enabled (any type) - object: Blender Object. - Returns: Boolean - True if object has any kind of duplicates enabled. - """ - if (object.enableDupFrames or \ - object.enableDupGroup or \ - object.enableDupVerts): - return True - else: - return False - -def getObjectsAndDuplis(oblist,MATRICES=False,HACK=False): - """ - Return a list of real objects and duplicates and optionally their matrices - oblist: List of Blender Objects - MATRICES: Boolean - Check to also get the objects matrices, default=False - HACK: Boolean - See note, default=False - Returns: List of objects or - List of tuples of the form:(ob,matrix) if MATRICES is set to True - NOTE: There is an ugly hack here that excludes all objects whose name - starts with "dpl_" to exclude objects that are parented to a duplicating - object, User must name objects properly if hack is used. - """ - - result = [] - for ob in oblist: - if INCLUDE_DUPLIS and dupTest(ob): - dup_obs=ob.DupObjects - if len(dup_obs): - for dup_ob, dup_mx in dup_obs: - if MATRICES: - result.append((dup_ob,dup_mx)) - else: - result.append(dup_ob) - else: - if HACK: - if ob.getName()[0:4] != "dpl_": - if MATRICES: - mx = ob.mat - result.append((ob,mx)) - else: - result.append(ob) - else: - if MATRICES: - mx = ob.mat - result.append((ob,mx)) - else: - result.append(ob) - return result - -#----------------------------------------------------- -def hidden_status(faces, mx, mx_n): - # sort out back-faces = with normals pointed away from camera - #print 'HIDDEN_LINES: caution! not full implemented yet' - front_faces = [] - front_edges = [] - for f in faces: - #print 'deb: face=', f #--------- - #print 'deb: dir(face)=', dir(f) #--------- - # get its normal-vector in localCS - vec_normal = f.no.copy() - #print 'deb: vec_normal=', vec_normal #------------------ - # must be transfered to camera/view-CS - vec_normal *= mx_n - #vec_normal *= mb.rotationPart() - #print 'deb:2vec_normal=', vec_normal #------------------ - #vec_normal *= mw0.rotationPart() - #print 'deb:3vec_normal=', vec_normal, '\n' #------------------ - - - frontFace = False - if not PERSPECTIVE: #for ortho mode ---------- - # normal must point the Z direction-hemisphere - if vec_normal[2] > 0.00001: - frontFace = True - else: - v = f.verts[0] - vert = Mathutils.Vector(v.co) * mx - if Mathutils.DotVecs(vert, vec_normal) < 0.00001: - frontFace = True - - if frontFace: - front_faces.append(f.index) - for key in f.edge_keys: - #this test can be done faster with set() - if key not in front_edges: - front_edges.append(key) - - #print 'deb: amount of visible faces=', len(front_faces) #--------- - #print 'deb: visible faces=', front_faces #--------- - #print 'deb: amount of visible edges=', len(front_edges) #--------- - #print 'deb: visible edges=', front_edges #--------- - return front_faces, front_edges - - -#---- migration to 2.49------------------------------------------------- -if 'cross' in dir(Mathutils.Vector()): - #Draw.PupMenu('DXF exporter: Abort%t|This script version works for Blender up 2.49 only!') - def M_CrossVecs(v1,v2): - return v1.cross(v2) #for up2.49 - def M_DotVecs(v1,v2): - return v1.dot(v2) #for up2.49 -else: - def M_CrossVecs(v1,v2): - return Mathutils.CrossVecs(v1,v2) #for pre2.49 - def M_DotVecs(v1,v2): - return Mathutils.DotVecs(v1,v2) #for pre2.49 - - -#----------------------------------------------------- -def getExtrusion(matrix): - """calculates DXF-Extrusion = Arbitrary Xaxis and Zaxis vectors - - """ - AZaxis = matrix[2].copy().resize3D().normalize() # = ArbitraryZvector - Extrusion = [AZaxis[0],AZaxis[1],AZaxis[2]] - if AZaxis[2]==1.0: - Extrusion = None - AXaxis = matrix[0].copy().resize3D() # = ArbitraryXvector - else: - threshold = 1.0 / 64.0 - if abs(AZaxis[0]) < threshold and abs(AZaxis[1]) < threshold: - # AXaxis is the intersection WorldPlane and ExtrusionPlane - AXaxis = M_CrossVecs(WORLDY,AZaxis) - else: - AXaxis = M_CrossVecs(WORLDZ,AZaxis) - #print 'deb:\n' #------------- - #print 'deb:getExtrusion() Extrusion=', Extrusion #--------- - return Extrusion, AXaxis.normalize() - - -#----------------------------------------------------- -def getZRotation(AXaxis, rot_matrix_invert): - """calculates ZRotation = angle between ArbitraryXvector and obj.matrix.Xaxis - - """ - # this works: Xaxis is the obj.matrix-Xaxis vector - # but not correct for all orientations - #Xaxis = matrix[0].copy().resize3D() # = ArbitraryXvector - ##Xaxis.normalize() # = ArbitraryXvector - #ZRotation = - Mathutils.AngleBetweenVecs(Xaxis,AXaxis) #output in radians - - # this works for all orientations, maybe a bit faster - # transform AXaxis into OCS:Object-Coord-System - #rot_matrix = normalizeMat(matrix.rotationPart()) - #rot_matrix_invert = rot_matrix.invert() - vec = AXaxis * rot_matrix_invert - ##vec = AXaxis * matrix.copy().invert() - ##vec.normalize() # not needed for atan2() - #print '\ndeb:getExtrusion() vec=', vec #--------- - ZRotation = - atan2(vec[1],vec[0]) #output in radians - - #print 'deb:ZRotation() ZRotation=', ZRotation*r2d #--------- - return ZRotation - - -#------------------------------------------ -def normalizeMat(matrix): - mat12 = matrix.copy() - mat12 = [Mathutils.Vector(v).normalize() for v in mat12] - if len(mat12)>3: - matr12 = Mathutils.Matrix(mat12[0],mat12[1],mat12[2],mat12[3]) - else: - matr12 = Mathutils.Matrix(mat12[0],mat12[1],mat12[2]) - return matr12 - - -#----------------------------------------------------- -def projected_co(verts, matrix): - """ converts coordinates of points from OCS to WCS->ScreenCS - needs matrix: a projection matrix - needs verts: a list of vectors[x,y,z] - returns a list of [x,y,z] - """ - #print 'deb:projected_co() verts=', verts #--------- - temp_verts = [Mathutils.Vector(v)*matrix for v in verts] - #print 'deb:projected_co() temp_verts=', temp_verts #--------- - - if GUI_A['Z_force_on'].val: locZ = GUI_A['Z_elev'].val - else: locZ = 0.0 - - if PROJECTION: - if PERSPECTIVE: - clipStart = 10.0 - for v in temp_verts: - coef = - clipStart / v[2] - v[0] *= coef - v[1] *= coef - v[2] = locZ - for v in temp_verts: - v[2] = locZ - temp_verts = [v[:3] for v in temp_verts] - #print 'deb:projected_co() out_verts=', temp_verts #--------- - return temp_verts - - -#----------------------------------------------------- -def isLeftHand(matrix): - #Is the matrix a left-hand-system, or not? - ma = matrix.rotationPart() - crossXY = M_CrossVecs(ma[0], ma[1]) - check = M_DotVecs(ma[2], crossXY) - if check < 0.00001: return 1 - return 0 - - -#----------------------------------------------------- -def exportMesh(ob, mx, mx_n, me=None, **common): - """converts Mesh-Object to desired projection and representation(DXF-Entity type) - """ - global BLOCKREGISTRY - entities = [] - block = None - #print 'deb:exportMesh() given common=', common #--------- - if me==None: - me = ob.getData(mesh=1) - else: - me.getFromObject(ob) - # idea: me.transform(mx); get verts data; me.transform(mx_inv)= back to the origin state - # the .transform-method is fast, but bad, cause invasive: - # it manipulates original geometry and by retransformation lefts back rounding-errors - # we dont want to manipulate original data! - #temp_verts = me.verts[:] #doesn't work on ubuntu(Yorik), bug? - if me.verts: - #print 'deb:exportMesh() started' #--------- - - #print 'deb:exportMesh() ob.name=', ob.name #--------- - #print 'deb:exportMesh() me.name=', me.name #--------- - #print 'deb:exportMesh() me.users=', me.users #--------- - # check if there are more instances of this mesh (if used by other objects), then write to BLOCK/INSERT - if GUI_A['instances_on'].val and me.users>1 and not PROJECTION: - if me.name in BLOCKREGISTRY.keys(): - insert_name = BLOCKREGISTRY[me.name] - # write INSERT to entities - entities = exportInsert(ob, mx,insert_name, **common) - else: - # generate geom_output in ObjectCS - allpoints = [v.co for v in me.verts] - identity_matrix = Mathutils.Matrix().identity() - allpoints = projected_co(allpoints, identity_matrix) - #allpoints = toGlobalOrigin(allpoints) - faces=[] - edges=[] - for e in me.edges: edges.append(e.key) - faces = [[v.index for v in f.verts] for f in me.faces] - entities = writeMeshEntities(allpoints, edges, faces, **common) - if entities: # if not empty block - # write BLOCK definition and INSERT entity - # BLOCKREGISTRY = dictionary 'blender_name':'dxf_name'.append(me.name) - BLOCKREGISTRY[me.name]=validDXFr12name(('ME_'+ me.name)) - insert_name = BLOCKREGISTRY[me.name] - block = DXF.Block(insert_name,flag=0,base=(0,0,0),entities=entities) - # write INSERT as entity - entities = exportInsert(ob, mx, insert_name, **common) - - else: # no other instances, so go the standard way - allpoints = [v.co for v in me.verts] - allpoints = projected_co(allpoints, mx) - allpoints = toGlobalOrigin(allpoints) - faces=[] - edges=[] - if me.faces and PROJECTION and HIDDEN_LINES: - #if DEBUG: print 'deb:exportMesh HIDDEN_LINES mode' #--------- - faces, edges = hidden_status(me.faces, mx, mx_n) - faces = [[v.index for v in me.faces[f_nr].verts] for f_nr in faces] - else: - #if DEBUG: print 'deb:exportMesh STANDARD mode' #--------- - for e in me.edges: edges.append(e.key) - #faces = [f.index for f in me.faces] - faces = [[v.index for v in f.verts] for f in me.faces] - #faces = [[allpoints[v.index] for v in f.verts] for f in me.faces] - #print 'deb: allpoints=\n', allpoints #--------- - #print 'deb: edges=\n', edges #--------- - #print 'deb: faces=\n', faces #--------- - if isLeftHand(mx): # then change vertex-order in every face - for f in faces: - f.reverse() - #f = [f[-1]] + f[:-1] #TODO: might be needed - #print 'deb: faces=\n', faces #--------- - entities = writeMeshEntities(allpoints, edges, faces, **common) - - return entities, block - - -#------------------------------------------------- -def writeMeshEntities(allpoints, edges, faces, **common): - """help routine for exportMesh() - """ - entities = [] - - c = mesh_as_list[GUI_A['mesh_as'].val] - if 'POINTs'==c: # export Mesh as multiple POINTs - for p in allpoints: - dxfPOINT = DXF.Point(points=[p],**common) - entities.append(dxfPOINT) - elif 'LINEs'==c or (not faces): - if edges and allpoints: - if DEBUG: mesh_drawBlender(allpoints, edges, None) #deb: draw to blender scene - for e in edges: - points = [allpoints[e[0]], allpoints[e[1]]] - dxfLINE = DXF.Line(points, **common) - entities.append(dxfLINE) - elif faces: - if c in ('POLYFACE','POLYLINE'): - if allpoints: - #TODO: purge allpoints: left only vertices used by faces - if DEBUG: mesh_drawBlender(allpoints, None, faces) #deb: draw to scene - if not (PROJECTION and HIDDEN_LINES): - faces = [[v+1 for v in f] for f in faces] - else: - # for back-Faces-mode remove face-free verts - map=verts_state= [0]*len(allpoints) - for f in faces: - for v in f: - verts_state[v]=1 - if 0 in verts_state: # if dirty state - i,newverts=0,[] - for used_i,used in enumerate(verts_state): - if used: - newverts.append(allpoints[used_i]) - map[used_i]=i - i+=1 - allpoints = newverts - faces = [[map[v]+1 for v in f] for f in faces] - dxfPOLYFACE = DXF.PolyLine([allpoints, faces], flag=64, **common) - #print '\n deb: dxfPOLYFACE=',dxfPOLYFACE #------------- - entities.append(dxfPOLYFACE) - elif '3DFACEs'==c: - if DEBUG: mesh_drawBlender(allpoints, None, faces) #deb: draw to scene - for f in faces: - #print 'deb: face=', f #--------- - points = [allpoints[key] for key in f] - #points = [p.co[:3] for p in points] - #print 'deb: pointsXX=\n', points #--------- - dxfFACE = DXF.Face(points, **common) - entities.append(dxfFACE) - - return entities - - -#----------------------------------------------------- -def mesh_drawBlender(vertList, edgeList, faceList, name="dxfMesh", flatten=False, AT_CUR=True, link=True): - #print 'deb:mesh_drawBlender started XXXXXXXXXXXXXXXXXX' #--------- - ob = Object.New("Mesh",name) - me = Mesh.New(name) - #print 'deb: vertList=\n', vertList #--------- - #print 'deb: edgeList=\n', edgeList #--------- - #print 'deb: faceList=\n', faceList #--------- - me.verts.extend(vertList) - if edgeList: me.edges.extend(edgeList) - if faceList: me.faces.extend(faceList) - if flatten: - for v in me.verts: v.co.z = 0.0 - ob.link(me) - if link: - sce = Scene.getCurrent() - sce.objects.link(ob) - #me.triangleToQuad() - if AT_CUR: - cur_loc = Window.GetCursorPos() - ob.setLocation(cur_loc) - Blender.Redraw() - #return ob - -#----------------------------------------------------- -def curve_drawBlender(vertList, org_point=[0.0,0.0,0.0], closed=0, name="dxfCurve", flatten=False, AT_CUR=True, link=True): - #print 'deb:curve_drawBlender started XXXXXXXXXXXXXXXXXX' #--------- - ob = Object.New("Curve",name) - cu = Curve.New(name) - #print 'deb: vertList=\n', vertList #--------- - curve = cu.appendNurb(BezTriple.New(vertList[0])) - for p in vertList[1:]: - curve.append(BezTriple.New(p)) - for point in curve: - #point.handleTypes = [VECT, VECT] - point.handleTypes = [FREE, FREE] - point.radius = 1.0 - curve.flagU = closed # 0 sets the curve not cyclic=open - cu.setResolu(6) - cu.update() #important for handles calculation - if flatten: - for v in cu.verts: v.co.z = 0.0 - ob.link(cu) - if link: - sce = Scene.getCurrent() - sce.objects.link(ob) - #me.triangleToQuad() - if AT_CUR: - cur_loc = Window.GetCursorPos() - ob.setLocation(cur_loc) - elif org_point: - cur_loc=org_point - ob.setLocation(cur_loc) - Blender.Redraw() - #return ob - - -#----------------------------------------------------- -def toGlobalOrigin(points): - """relocates points to the new location - needs a list of points [x,y,z] - """ - if GUI_A['g_origin_on'].val: - for p in points: - p[0] += G_ORIGIN[0] - p[1] += G_ORIGIN[1] - p[2] += G_ORIGIN[2] - return points - - -#----------------------------------------------------- -def exportEmpty(ob, mx, mw, **common): - """converts Empty-Object to desired projection and representation(DXF-Entity type) - """ - p = Mathutils.Vector(ob.loc) - [p] = projected_co([p], mx) - [p] = toGlobalOrigin([p]) - - entities = [] - c = empty_as_list[GUI_A['empty_as'].val] - if c=="POINT": # export Empty as POINT - dxfPOINT = DXF.Point(points=[p],**common) - entities.append(dxfPOINT) - return entities - -#----------------------------------------------------- -def exportCamera(ob, mx, mw, **common): - """converts Camera-Object to desired projection and representation(DXF-Entity type) - """ - location = Mathutils.Vector(ob.loc) - [location] = projected_co([location], mx) - [location] = toGlobalOrigin([location]) - view_name=validDXFr12name(('CAM_'+ ob.name)) - - camera = Camera.Get(ob.getData(name_only=True)) - #print 'deb: camera=', dir(camera) #------------------ - if camera.type=='persp': - mode = 1+2+4+16 - # mode flags: 1=persp, 2=frontclip, 4=backclip,16=FrontZ - elif camera.type=='ortho': - mode = 0+2+4+16 - - leftBottom=(0.0,0.0) # default - rightTop=(1.0,1.0) # default - center=(0.0,0.0) # default - - direction = Mathutils.Vector(0.0,0.0,1.0) * mx.rotationPart() # in W-C-S - direction.normalize() - target=Mathutils.Vector(ob.loc) - direction # in W-C-S - #ratio=1.0 - width=height= camera.scale # for ortho-camera - lens = camera.lens # for persp-camera - frontClipping = -(camera.clipStart - 1.0) - backClipping = -(camera.clipEnd - 1.0) - - entities, vport, view = [], None, None - c = camera_as_list[GUI_A['camera_as'].val] - if c=="POINT": # export as POINT - dxfPOINT = DXF.Point(points=[location],**common) - entities.append(dxfPOINT) - elif c=="VIEW": # export as VIEW - view = DXF.View(name=view_name, - center=center, width=width, height=height, - frontClipping=frontClipping,backClipping=backClipping, - direction=direction,target=target,lens=lens,mode=mode - ) - elif c=="VPORT": # export as VPORT - vport = DXF.VPort(name=view_name, - center=center, ratio=1.0, height=height, - frontClipping=frontClipping,backClipping=backClipping, - direction=direction,target=target,lens=lens,mode=mode - ) - return entities, vport, view - -#----------------------------------------------------- -def exportLamp(ob, mx, mw, **common): - """converts Lamp-Object to desired projection and representation(DXF-Entity type) - """ - p = Mathutils.Vector(ob.loc) - [p] = projected_co([p], mx) - [p] = toGlobalOrigin([p]) - - entities = [] - c = lamp_as_list[GUI_A['lamp_as'].val] - if c=="POINT": # export as POINT - dxfPOINT = DXF.Point(points=[p],**common) - entities.append(dxfPOINT) - return entities - -#----------------------------------------------------- -def exportInsert(ob, mx, insert_name, **common): - """converts Object to DXF-INSERT in given orientation - """ - WCS_loc = ob.loc # WCS_loc is object location in WorldCoordSystem - sizeX = ob.SizeX - sizeY = ob.SizeY - sizeZ = ob.SizeZ - rotX = ob.RotX - rotY = ob.RotY - rotZ = ob.RotZ - #print 'deb: sizeX=%s, sizeY=%s' %(sizeX, sizeY) #--------- - - Thickness,Extrusion,ZRotation,Elevation = None,None,None,None - - AXaxis = mx[0].copy().resize3D() # = ArbitraryXvector - if not PROJECTION: - #Extrusion, ZRotation, Elevation = getExtrusion(mx) - Extrusion, AXaxis = getExtrusion(mx) - - entities = [] - - if 1: - if not PROJECTION: - ZRotation,Zrotmatrix,OCS_origin,ECS_origin = getTargetOrientation(mx,Extrusion,\ - AXaxis,WCS_loc,sizeX,sizeY,sizeZ,rotX,rotY,rotZ) - ZRotation *= r2d - point = ECS_origin - else: #TODO: fails correct location - point1 = Mathutils.Vector(ob.loc) - [point] = projected_co([point1], mx) - if PERSPECTIVE: - clipStart = 10.0 - coef = -clipStart / (point1*mx)[2] - #print 'deb: coef=', coef #-------------- - #TODO: ? sizeX *= coef - #sizeY *= coef - #sizeZ *= coef - - #print 'deb: point=', point #-------------- - [point] = toGlobalOrigin([point]) - - #if DEBUG: text_drawBlender(textstr,points,OCS_origin) #deb: draw to scene - common['extrusion']= Extrusion - #common['elevation']= Elevation - #print 'deb: common=', common #------------------ - if 0: #DEBUG - #linepoints = [[0,0,0], [AXaxis[0],AXaxis[1],AXaxis[2]]] - linepoints = [[0,0,0], point] - dxfLINE = DXF.Line(linepoints,**common) - entities.append(dxfLINE) - - xscale=sizeX - yscale=sizeY - zscale=sizeZ - cols=None - colspacing=None - rows=None - rowspacing=None - - dxfINSERT = DXF.Insert(insert_name,point=point,rotation=ZRotation,\ - xscale=xscale,yscale=yscale,zscale=zscale,\ - cols=cols,colspacing=colspacing,rows=rows,rowspacing=rowspacing,\ - **common) - entities.append(dxfINSERT) - - return entities - - -#----------------------------------------------------- -def exportText(ob, mx, mw, **common): - """converts Text-Object to desired projection and representation(DXF-Entity type) - """ - text3d = ob.getData() - textstr = text3d.getText() - WCS_loc = ob.loc # WCS_loc is object location in WorldCoordSystem - sizeX = ob.SizeX - sizeY = ob.SizeY - sizeZ = ob.SizeZ - rotX = ob.RotX - rotY = ob.RotY - rotZ = ob.RotZ - #print 'deb: sizeX=%s, sizeY=%s' %(sizeX, sizeY) #--------- - - Thickness,Extrusion,ZRotation,Elevation = None,None,None,None - - AXaxis = mx[0].copy().resize3D() # = ArbitraryXvector - if not PROJECTION: - #Extrusion, ZRotation, Elevation = getExtrusion(mx) - Extrusion, AXaxis = getExtrusion(mx) - - # no thickness/width for TEXTs converted into ScreenCS - if text3d.getExtrudeDepth(): - Thickness = text3d.getExtrudeDepth() * sizeZ - - #Horizontal text justification type, code 72, (optional, default = 0) - # integer codes (not bit-coded) - #0=left, 1=center, 2=right - #3=aligned, 4=middle, 5=fit - Alignment = None - alignment = text3d.getAlignment().value - if alignment in (1,2): Alignment = alignment - - textHeight = text3d.getSize() / 1.7 - textFlag = 0 - if sizeX < 0.0: textFlag |= 2 # set flag for horizontal mirrored - if sizeZ < 0.0: textFlag |= 4 # vertical mirrored - - entities = [] - c = text_as_list[GUI_A['text_as'].val] - - if c=="TEXT": # export text as TEXT - if not PROJECTION: - ZRotation,Zrotmatrix,OCS_origin,ECS_origin = getTargetOrientation(mx,Extrusion,\ - AXaxis,WCS_loc,sizeX,sizeY,sizeZ,rotX,rotY,rotZ) - ZRotation *= r2d - point = ECS_origin - else: #TODO: fails correct location - point1 = Mathutils.Vector(ob.loc) - [point] = projected_co([point1], mx) - if PERSPECTIVE: - clipStart = 10.0 - coef = -clipStart / (point1*mx)[2] - textHeight *= coef - #print 'deb: coef=', coef #-------------- - - #print 'deb: point=', point #-------------- - [point] = toGlobalOrigin([point]) - point2 = point - - #if DEBUG: text_drawBlender(textstr,points,OCS_origin) #deb: draw to scene - common['extrusion']= Extrusion - #common['elevation']= Elevation - common['thickness']= Thickness - #print 'deb: common=', common #------------------ - if 0: #DEBUG - #linepoints = [[0,0,0], [AXaxis[0],AXaxis[1],AXaxis[2]]] - linepoints = [[0,0,0], point] - dxfLINE = DXF.Line(linepoints,**common) - entities.append(dxfLINE) - - dxfTEXT = DXF.Text(text=textstr,point=point,alignment=point2,rotation=ZRotation,\ - flag=textFlag,height=textHeight,justifyhor=Alignment,**common) - entities.append(dxfTEXT) - if Thickness: - common['thickness']= -Thickness - dxfTEXT = DXF.Text(text=textstr,point=point,alignment=point2,rotation=ZRotation,\ - flag=textFlag,height=textHeight,justifyhor=Alignment,**common) - entities.append(dxfTEXT) - return entities - - -#------------------------------------------- -def euler2matrix(rx, ry, rz): - """creates full 3D rotation matrix (optimized) - needs rx, ry, rz angles in radians - """ - #print 'rx, ry, rz: ', rx, ry, rz - A, B = sin(rx), cos(rx) - C, D = sin(ry), cos(ry) - E, F = sin(rz), cos(rz) - AC, BC = A*C, B*C - return Mathutils.Matrix([D*F, D*E, -C], - [AC*F-B*E, AC*E+B*F, A*D], - [BC*F+A*E, BC*E-A*F, B*D]) - - -#----------------------------------------------------- -def getTargetOrientation(mx,Extrusion,AXaxis,WCS_loc,sizeX,sizeY,sizeZ,rotX,rotY,rotZ): - """given - """ - if 1: - rot_matrix = normalizeMat(mx.rotationPart()) - #TODO: workaround for blender negative-matrix.invert() - # partially done: works only for rotX,rotY==0.0 - if sizeX<0.0: rot_matrix[0] *= -1 - if sizeY<0.0: rot_matrix[1] *= -1 - #if sizeZ<0.0: rot_matrix[2] *= -1 - rot_matrix_invert = rot_matrix.invert() - else: #TODO: to check, why below rot_matrix_invert is not equal above one - rot_euler_matrix = euler2matrix(rotX,rotY,rotZ) - rot_matrix_invert = euler2matrix(-rotX,-rotY,-rotZ) - - # OCS_origin is Global_Origin in ObjectCoordSystem - OCS_origin = Mathutils.Vector(WCS_loc) * rot_matrix_invert - #print 'deb: OCS_origin=', OCS_origin #--------- - - ZRotation = rotZ - if Extrusion!=None: - ZRotation = getZRotation(AXaxis,rot_matrix_invert) - #Zrotmatrix = Mathutils.RotationMatrix(-ZRotation, 3, "Z") - rs, rc = sin(ZRotation), cos(ZRotation) - Zrotmatrix = Mathutils.Matrix([rc, rs,0.0],[-rs,rc,0.0],[0.0,0.0,1.0]) - #print 'deb: Zrotmatrix=\n', Zrotmatrix #-------------- - - # ECS_origin is Global_Origin in EntityCoordSystem - ECS_origin = OCS_origin * Zrotmatrix - #print 'deb: ECS_origin=', ECS_origin #--------- - #TODO: it doesnt work yet for negative scaled curve-objects! - return ZRotation,Zrotmatrix,OCS_origin,ECS_origin - - -#----------------------------------------------------- -def exportCurve(ob, mx, mw, **common): - """converts Curve-Object to desired projection and representation(DXF-Entity type) - """ - entities = [] - block = None - curve = ob.getData() - #print 'deb: curve=', dir(curve) #--------- - # TODO: should be: if curve.users>1 and not (PERSPECTIVE or (PROJECTION and HIDDEN_MODE): - if GUI_A['instances_on'].val and curve.users>1 and not PROJECTION: - if curve.name in BLOCKREGISTRY.keys(): - insert_name = BLOCKREGISTRY[curve.name] - # write INSERT to entities - entities = exportInsert(ob, mx,insert_name, **common) - else: - # generate geom_output in ObjectCS - imx = Mathutils.Matrix().identity() - WCS_loc = [0,0,0] # WCS_loc is object location in WorldCoordSystem - #print 'deb: WCS_loc=', WCS_loc #--------- - sizeX = sizeY = sizeZ = 1.0 - rotX = rotY = rotZ = 0.0 - Thickness,Extrusion,ZRotation,Elevation = None,None,None,None - ZRotation,Zrotmatrix,OCS_origin,ECS_origin = None,None,None,None - AXaxis = imx[0].copy().resize3D() # = ArbitraryXvector - OCS_origin = [0,0,0] - if not PROJECTION: - #Extrusion, ZRotation, Elevation = getExtrusion(mx) - Extrusion, AXaxis = getExtrusion(imx) - - # no thickness/width for POLYLINEs converted into Screen-C-S - #print 'deb: curve.ext1=', curve.ext1 #--------- - if curve.ext1: Thickness = curve.ext1 * sizeZ - if curve.ext2 and sizeX==sizeY: - Width = curve.ext2 * sizeX - if "POLYLINE"==curve_as_list[GUI_A['curve_as'].val]: # export as POLYLINE - ZRotation,Zrotmatrix,OCS_origin,ECS_origin = getTargetOrientation(imx,Extrusion,\ - AXaxis,WCS_loc,sizeX,sizeY,sizeZ,rotX,rotY,rotZ) - - entities = writeCurveEntities(curve, imx, - Thickness,Extrusion,ZRotation,Elevation,AXaxis,Zrotmatrix, - WCS_loc,OCS_origin,ECS_origin,sizeX,sizeY,sizeZ, - **common) - - if entities: # if not empty block - # write BLOCK definition and INSERT entity - # BLOCKREGISTRY = dictionary 'blender_name':'dxf_name'.append(me.name) - BLOCKREGISTRY[curve.name]=validDXFr12name(('CU_'+ curve.name)) - insert_name = BLOCKREGISTRY[curve.name] - block = DXF.Block(insert_name,flag=0,base=(0,0,0),entities=entities) - # write INSERT as entity - entities = exportInsert(ob, mx, insert_name, **common) - - else: # no other instances, so go the standard way - WCS_loc = ob.loc # WCS_loc is object location in WorldCoordSystem - #print 'deb: WCS_loc=', WCS_loc #--------- - sizeX = ob.SizeX - sizeY = ob.SizeY - sizeZ = ob.SizeZ - rotX = ob.RotX - rotY = ob.RotY - rotZ = ob.RotZ - #print 'deb: sizeX=%s, sizeY=%s' %(sizeX, sizeY) #--------- - - Thickness,Extrusion,ZRotation,Elevation = None,None,None,None - ZRotation,Zrotmatrix,OCS_origin,ECS_origin = None,None,None,None - AXaxis = mx[0].copy().resize3D() # = ArbitraryXvector - OCS_origin = [0,0,0] - if not PROJECTION: - #Extrusion, ZRotation, Elevation = getExtrusion(mx) - Extrusion, AXaxis = getExtrusion(mx) - - # no thickness/width for POLYLINEs converted into Screen-C-S - #print 'deb: curve.ext1=', curve.ext1 #--------- - if curve.ext1: Thickness = curve.ext1 * sizeZ - if curve.ext2 and sizeX==sizeY: - Width = curve.ext2 * sizeX - if "POLYLINE"==curve_as_list[GUI_A['curve_as'].val]: # export as POLYLINE - ZRotation,Zrotmatrix,OCS_origin,ECS_origin = getTargetOrientation(mx,Extrusion,\ - AXaxis,WCS_loc,sizeX,sizeY,sizeZ,rotX,rotY,rotZ) - entities = writeCurveEntities(curve, mx, - Thickness,Extrusion,ZRotation,Elevation,AXaxis,Zrotmatrix, - WCS_loc,OCS_origin,ECS_origin,sizeX,sizeY,sizeZ, - **common) - - return entities, block - - -#------------------------------------------------- -def writeCurveEntities(curve, mx, - Thickness,Extrusion,ZRotation,Elevation,AXaxis,Zrotmatrix, - WCS_loc,OCS_origin,ECS_origin,sizeX,sizeY,sizeZ, - **common): - """help routine for exportCurve() - """ - entities = [] - - if 1: - for cur in curve: - #print 'deb: START cur=', cur #-------------- - points = [] - if cur.isNurb(): - for point in cur: - #print 'deb:isNurb point=', point #--------- - vec = point[0:3] - #print 'deb: vec=', vec #--------- - pkt = Mathutils.Vector(vec) - #print 'deb: pkt=', pkt #--------- - points.append(pkt) - else: - for point in cur: - #print 'deb:isBezier point=', point.getTriple() #--------- - vec = point.getTriple()[1] - #print 'deb: vec=', vec #--------- - pkt = Mathutils.Vector(vec) - #print 'deb: pkt=', pkt #--------- - points.append(pkt) - - #print 'deb: points', points #-------------- - if len(points)>1: - c = curve_as_list[GUI_A['curve_as'].val] - - if c=="POLYLINE": # export Curve as POLYLINE - if not PROJECTION: - # recalculate points(2d=X,Y) into Entity-Coords-System - for p in points: # list of vectors - p[0] *= sizeX - p[1] *= sizeY - p2 = p * Zrotmatrix - p2[0] += ECS_origin[0] - p2[1] += ECS_origin[1] - p[0],p[1] = p2[0],p2[1] - else: - points = projected_co(points, mx) - #print 'deb: points', points #-------------- - - if cur.isCyclic(): closed = 1 - else: closed = 0 - points = toGlobalOrigin(points) - - if DEBUG: curve_drawBlender(points,OCS_origin,closed) #deb: draw to scene - - common['extrusion']= Extrusion - ##common['rotation']= ZRotation - ##common['elevation']= Elevation - common['thickness']= Thickness - #print 'deb: common=', common #------------------ - - if 0: #DEBUG - p=AXaxis[:3] - entities.append(DXF.Line([[0,0,0], p],**common)) - p=ECS_origin[:3] - entities.append(DXF.Line([[0,0,0], p],**common)) - common['color']= 5 - p=OCS_origin[:3] - entities.append(DXF.Line([[0,0,0], p],**common)) - #OCS_origin=[0,0,0] #only debug---------------- - dxfPLINE = DXF.PolyLine(points,OCS_origin,closed,**common) - entities.append(dxfPLINE) - - dxfPLINE = DXF.PolyLine(points,OCS_origin,closed,**common) - entities.append(dxfPLINE) - if Thickness: - common['thickness']= -Thickness - dxfPLINE = DXF.PolyLine(points,OCS_origin,closed,**common) - entities.append(dxfPLINE) - - elif c=="LINEs": # export Curve as multiple LINEs - points = projected_co(points, mx) - if cur.isCyclic(): points.append(points[0]) - #print 'deb: points', points #-------------- - points = toGlobalOrigin(points) - - if DEBUG: curve_drawBlender(points,WCS_loc,closed) #deb: draw to scene - common['extrusion']= Extrusion - common['elevation']= Elevation - common['thickness']= Thickness - #print 'deb: common=', common #------------------ - for i in range(len(points)-1): - linepoints = [points[i], points[i+1]] - dxfLINE = DXF.Line(linepoints,**common) - entities.append(dxfLINE) - if Thickness: - common['thickness']= -Thickness - for i in range(len(points)-1): - linepoints = [points[i], points[i+1]] - dxfLINE = DXF.Line(linepoints,**common) - entities.append(dxfLINE) - - elif c=="POINTs": # export Curve as multiple POINTs - points = projected_co(points, mx) - for p in points: - dxfPOINT = DXF.Point(points=[p],**common) - entities.append(dxfPOINT) - return entities - - -#----------------------------------------------------- -def getClipBox(camera): - """calculates Field-of-View-Clipping-Box of given Camera - returns clip_box: a list of vertices - returns matr: translation matrix - """ - sce = Scene.GetCurrent() - context = sce.getRenderingContext() - #print 'deb: context=\n', context #------------------ - sizeX = context.sizeX - sizeY = context.sizeY - ratioXY = sizeX/float(sizeY) - #print 'deb: size X,Y, ratio=', sizeX, sizeY, ratioXY #------------------ - - clip1_Z = - camera.clipStart - clip2_Z = - camera.clipEnd - #print 'deb: clip Start=', camera.clipStart #------------------ - #print 'deb: clip End=', camera.clipEnd #------------------ - - if camera.type=='ortho': - scale = camera.scale - #print 'deb: camscale=', scale #------------------ - clip1shiftX = clip2shiftX = camera.shiftX * scale - clip1shiftY = clip2shiftY = camera.shiftY * scale - clip1_X = scale * 0.5 - clip1_Y = scale * 0.5 - if ratioXY > 1.0: clip1_Y /= ratioXY - else: clip1_X *= ratioXY - clip2_X = clip1_X - clip2_Y = clip1_Y - - near = clip1_Z - far = clip2_Z - right, left = clip1_X, -clip1_X - top, bottom = clip1_Y, -clip1_Y - - scaleX = 2.0/float(right - left) - x3 = -float(right + left)/float(right - left) - scaleY = 2.0/float(top - bottom) - y3 = -float(top + bottom)/float(top - bottom) - scaleZ = 1.0/float(far - near) - z3 = -float(near)/float(far - near) - - matrix = Mathutils.Matrix( [scaleX, 0.0, 0.0, x3], - [0.0, scaleY, 0.0, y3], - [0.0, 0.0, scaleZ, z3], - [0.0, 0.0, 0.0, 1.0]) - - elif camera.type=='persp': - #viewpoint = [0.0, 0.0, 0.0] #camera's coordinate system, hehe - #lens = camera.lens - angle = camera.angle - #print 'deb: cam angle=', angle #------------------ - shiftX = camera.shiftX - shiftY = camera.shiftY - fov_coef = atan(angle * d2r) - fov_coef *= 1.3 #incl. passpartou - clip1_k = clip1_Z * fov_coef - clip2_k = clip2_Z * fov_coef - clip1shiftX = - camera.shiftX * clip1_k - clip2shiftX = - camera.shiftX * clip2_k - clip1shiftY = - camera.shiftY * clip1_k - clip2shiftY = - camera.shiftY * clip2_k - clip1_X = clip1_Y = clip1_k * 0.5 - clip2_X = clip2_Y = clip2_k * 0.5 - if ratioXY > 1.0: - clip1_Y /= ratioXY - clip2_Y /= ratioXY - else: - clip1_X *= ratioXY - clip2_X *= ratioXY - - near = clip1_Z - far = clip2_Z - right, left = clip1_X, -clip1_X - top, bottom = clip1_Y, -clip1_Y - #return Matrix( [scaleX, 0.0, x2, 0.0], - #[0.0, scaleY, y2, 0.0], - #[0.0, 0.0, scaleZ, wZ], - #[0.0, 0.0, -1.0, 0.0]) - matrix = Mathutils.Matrix( [(2.0 * near)/float(right - left), 0.0, float(right + left)/float(right - left), 0.0], - [0.0, (2.0 * near)/float(top - bottom), float(top + bottom)/float(top - bottom), 0.0], - [0.0, 0.0, -float(far + near)/float(far - near), -(2.0 * far * near)/float(far - near)], - [0.0, 0.0, -1.0, 0.0]) - - - clip_box = [ - -clip1_X + clip1shiftX, clip1_X + clip1shiftX, - -clip1_Y + clip1shiftY, clip1_Y + clip1shiftY, - -clip2_X + clip2shiftX, clip2_X + clip2shiftX, - -clip2_Y + clip2shiftY, clip2_Y + clip2shiftY, - clip1_Z, clip2_Z] - #print 'deb: clip_box=\n', clip_box #------------------ - #drawClipBox(clip_box) - return clip_box, matrix - - -#----------------------------------------------------- -def drawClipBox(clip_box): - """debug tool: draws Clipping-Box of a Camera View - """ - min_X1, max_X1, min_Y1, max_Y1,\ - min_X2, max_X2, min_Y2, max_Y2,\ - min_Z, max_Z = clip_box - verts = [] - verts.append([min_X1, min_Y1, min_Z]) - verts.append([max_X1, min_Y1, min_Z]) - verts.append([max_X1, max_Y1, min_Z]) - verts.append([min_X1, max_Y1, min_Z]) - verts.append([min_X2, min_Y2, max_Z]) - verts.append([max_X2, min_Y2, max_Z]) - verts.append([max_X2, max_Y2, max_Z]) - verts.append([min_X2, max_Y2, max_Z]) - faces = [[0,1,2,3],[4,5,6,7]] - newmesh = Mesh.New() - newmesh.verts.extend(verts) - newmesh.faces.extend(faces) - - plan = Object.New('Mesh','clip_box') - plan.link(newmesh) - sce = Scene.GetCurrent() - sce.objects.link(plan) - plan.setMatrix(sce.objects.camera.matrix) - - -#------------------------------------------------- -def getCommons(ob): - """set up common attributes for output style: - color=None - extrusion=None - layer='0', - lineType=None - lineTypeScale=None - lineWeight=None - thickness=None - parent=None - """ - - layers = ob.layers #gives a list e.g.[1,5,19] - if layers: ob_layer_nr = layers[0] - #print 'ob_layer_nr=', ob_layer_nr #-------------- - - materials = ob.getMaterials() - if materials: - ob_material = materials[0] - ob_mat_color = ob_material.rgbCol - else: ob_mat_color, ob_material = None, None - #print 'ob_mat_color, ob_material=', ob_mat_color, ob_material #-------------- - - data = ob.getData() - data_materials = ob.getMaterials() - if data_materials: - data_material = data_materials[0] - data_mat_color = data_material.rgbCol - else: data_mat_color, data_material = None, None - #print 'data_mat_color, data_material=', data_mat_color, data_material #-------------- - - entitylayer = ENTITYLAYER_DEF - c = entitylayer_from_list[GUI_A['entitylayer_from'].val] - #["default_LAYER","obj.name","obj.layer","obj.material","obj.data.name","obj.data.material","..vertexgroup","..group","..map_table"] - if c=="default_LAYER": - entitylayer = LAYERNAME_DEF - elif c=="obj.layer" and ob_layer_nr: - entitylayer = 'LAYER'+ str(ob_layer_nr) - elif c=="obj.material" and ob_material: - entitylayer = ob_material.name - elif c=="obj.name": - entitylayer = ob.name - elif c=="obj.data.material" and ob_material: - entitylayer = data_material.name - elif c=="obj.data.name": - entitylayer = data.name - entitylayer = validDXFr12name(PREFIX+entitylayer) - if entitylayer=="": entitylayer = "BF_0" - - entitycolor = ENTITYCOLOR_DEF - c = entitycolor_from_list[GUI_A['entitycolor_from'].val] - if c=="default_COLOR": - entitycolor = LAYERCOLOR_DEF - elif c=="BYLAYER": - entitycolor = BYLAYER - elif c=="BYBLOCK": - entitycolor = BYBLOCK - elif c=="obj.layer" and ob_layer_nr: - entitycolor = ob_layer_nr - elif c=="obj.color" and ob.color: - entitycolor = col2DXF(ob.color) - elif c=="obj.material" and ob_mat_color: - entitycolor = col2DXF(ob_mat_color) - elif c=="obj.data.material" and data_mat_color: - entitycolor = col2DXF(data_mat_color) - #if entitycolor!=None: layercolor = entitycolor - - entityltype = ENTITYLTYPE_DEF - c = entityltype_from_list[GUI_A['entityltype_from'].val] - if c=="default_LTYPE": - entityltype = LAYERLTYPE_DEF - elif c=="BYLAYER": - entityltype = BYLAYER - elif c=="BYBLOCK": - entityltype = BYBLOCK - elif c: - entityltype = c - - return entitylayer,entitycolor,entityltype - - -#----------------------------------------------------- -def do_export(export_list, filepath): - global PERSPECTIVE, CAMERAVIEW, BLOCKREGISTRY - Window.WaitCursor(1) - t = Blender.sys.time() - - # init Drawing --------------------- - d=DXF.Drawing() - # add Tables ----------------- - # initialized automatic: d.blocks.append(b) #section BLOCKS - # initialized automatic: d.styles.append(DXF.Style()) #table STYLE - - #table LTYPE --------------- - #d.linetypes.append(DXF.LineType(name='CONTINUOUS',description='--------',elements=[0.0])) - d.linetypes.append(DXF.LineType(name='DOT',description='. . . . . . .',elements=[0.25, 0.0, -0.25])) - d.linetypes.append(DXF.LineType(name='DASHED',description='__ __ __ __ __',elements=[0.8, 0.5, -0.3])) - d.linetypes.append(DXF.LineType(name='DASHDOT',description='__ . __ . __ .',elements=[1.0, 0.5, -0.25, 0.0, -0.25])) - d.linetypes.append(DXF.LineType(name='DIVIDE',description='____ . . ____ . . ',elements=[1.25, 0.5, -0.25, 0.0, -0.25, 0.0, -0.25])) - d.linetypes.append(DXF.LineType(name='BORDER',description='__ __ . __ __ . ',elements=[1.75, 0.5, -0.25, 0.5, -0.25, 0.0, -0.25])) - d.linetypes.append(DXF.LineType(name='HIDDEN',description='__ __ __ __ __',elements=[0.4, 0.25, -0.25])) - d.linetypes.append(DXF.LineType(name='CENTER',description='____ _ ____ _ __',elements=[2.0, 1.25, -0.25, 0.25, -0.25])) - - #d.vports.append(DXF.VPort('*ACTIVE')) - d.vports.append(DXF.VPort('*ACTIVE',center=(-5.0,1.0),height=10.0)) - #d.vports.append(DXF.VPort('*ACTIVE',leftBottom=(-100.0,-60.0),rightTop=(100.0,60.0))) - #d.views.append(DXF.View('Normal')) #table view - d.views.append(DXF.ViewByWindow('BF_TOPVIEW',leftBottom=(-100,-60),rightTop=(100,60))) #idem - - # add Entities -------------------- - BLOCKREGISTRY = {} # registry and map for BLOCKs - PERSPECTIVE = 0 - something_ready = 0 - selected_len = len(export_list) - sce = Scene.GetCurrent() - - mw = Mathutils.Matrix( [1.0, 0.0, 0.0, 0.0], - [0.0, 1.0, 0.0, 0.0], - [0.0, 0.0, 1.0, 0.0], - [0.0, 0.0, 0.0, 1.0]) - if PROJECTION: - if CAMERA<len(CAMERAS)+1: # the biggest number is the current 3d-view - act_camera = Object.Get(CAMERAS[CAMERA-1]) - #context = sce.getRenderingContext() - #print 'deb: context=\n', context #------------------ - #print 'deb: context=\n', dir(context) #------------------ - #act_camera = sce.objects.camera - #print 'deb: act_camera=', act_camera #------------------ - if act_camera: - CAMERAVIEW = 1 - mc0 = act_camera.matrix.copy() - #print 'deb: camera.Matrix=\n', mc0 #------------------ - camera = Camera.Get(act_camera.getData(name_only=True)) - #print 'deb: camera=', dir(camera) #------------------ - if camera.type=='persp': PERSPECTIVE = 1 - elif camera.type=='ortho': PERSPECTIVE = 0 - # mcp is matrix.camera.perspective - clip_box, mcp = getClipBox(camera) - if PERSPECTIVE: - # get border - # lens = camera.lens - min_X1, max_X1, min_Y1, max_Y1,\ - min_X2, max_X2, min_Y2, max_Y2,\ - min_Z, max_Z = clip_box - verts = [] - verts.append([min_X1, min_Y1, min_Z]) - verts.append([max_X1, min_Y1, min_Z]) - verts.append([max_X1, max_Y1, min_Z]) - verts.append([min_X1, max_Y1, min_Z]) - border=verts - mw = mc0.copy().invert() - - else: # get 3D-View instead of camera-view - #ViewVector = Mathutils.Vector(Window.GetViewVector()) - #print 'deb: ViewVector=\n', ViewVector #------------------ - #TODO: what is Window.GetViewOffset() for? - #print 'deb: Window.GetViewOffset():', Window.GetViewOffset() #--------- - #Window.SetViewOffset([0,0,0]) - mw0 = Window.GetViewMatrix() - #print 'deb: mwOrtho =\n', mw0 #--------- - mwp = Window.GetPerspMatrix() #TODO: how to get it working? - #print 'deb: mwPersp =\n', mwp #--------- - mw = mw0.copy() - - #print 'deb: ViewMatrix=\n', mw #------------------ - - if APPLY_MODIFIERS: tmp_me = Mesh.New('tmp') - else: tmp_me = None - - if GUI_A['paper_space_on'].val==1: espace=1 - else: espace=None - - layernames = [] - for ob,mx in export_list: - entities = [] - block = None - #mx = ob.matrix.copy() - #print 'deb: ob =', ob #--------- - #print 'deb: ob.type =', ob.type #--------- - #print 'deb: mx =\n', mx #--------- - #print 'deb: mw0 =\n', mw0 #--------- - #mx_n is trans-matrix for normal_vectors for front-side faces - mx_n = mx.rotationPart() * mw.rotationPart() - if G_SCALE!=1.0: mx *= G_SCALE - mx *= mw - - #mx_inv = mx.copy().invert() - #print 'deb: mx =\n', mx #--------- - #print 'deb: mx_inv=\n', mx_inv #--------- - - if ob.type in ('Mesh','Curve','Empty','Text','Camera','Lamp'): - elayer,ecolor,eltype = getCommons(ob) - #print 'deb: elayer,ecolor,eltype =', elayer,ecolor,eltype #-------------- - - #TODO: use ob.boundBox for drawing extends - - if elayer!=None: - if elayer not in layernames: - layernames.append(elayer) - if ecolor!=None: tempcolor = ecolor - else: tempcolor = LAYERCOLOR_DEF - d.layers.append(DXF.Layer(color=tempcolor, name=elayer)) - - if (ob.type == 'Mesh') and GUI_B['bmesh'].val: - entities, block = exportMesh(ob, mx, mx_n, tmp_me,\ - paperspace=espace, color=ecolor, layer=elayer, lineType=eltype) - elif (ob.type == 'Curve') and GUI_B['bcurve'].val: - entities, block = exportCurve(ob, mx, mw, \ - paperspace=espace, color=ecolor, layer=elayer, lineType=eltype) - elif (ob.type == 'Empty') and GUI_B['empty'].val: - entities = exportEmpty(ob, mx, mw, \ - paperspace=espace, color=ecolor, layer=elayer, lineType=eltype) - elif (ob.type == 'Text') and GUI_B['text'].val: - entities = exportText(ob, mx, mw, \ - paperspace=espace, color=ecolor, layer=elayer, lineType=eltype) - elif (ob.type == 'Camera') and GUI_B['camera'].val: - entities, vport, view = exportCamera(ob, mx, mw, \ - paperspace=espace, color=ecolor, layer=elayer, lineType=eltype) - if vport: d.vports.append(vport) - if view: d.views.append(view) - elif (ob.type == 'Lamp') and GUI_B['lamp'].val: - entities = exportLamp(ob, mx, mw, \ - paperspace=espace, color=ecolor, layer=elayer, lineType=eltype) - - if entities: - something_ready += 1 - for e in entities: - d.append(e) - - if block: - d.blocks.append(block) #add to BLOCK-section - - - if something_ready: - if PERSPECTIVE: # generate view border - passepartout - identity_matrix = Mathutils.Matrix().identity() - points = projected_co(border, identity_matrix) - closed = 1 - points = toGlobalOrigin(points) - c = curve_as_list[GUI_A['curve_as'].val] - if c=="LINEs": # export Curve as multiple LINEs - for i in range(len(points)-1): - linepoints = [points[i], points[i+1]] - dxfLINE = DXF.Line(linepoints,paperspace=espace,color=LAYERCOLOR_DEF) - entities.append(dxfLINE) - else: - dxfPLINE = DXF.PolyLine(points,points[0],closed,\ - paperspace=espace, color=LAYERCOLOR_DEF) - d.append(dxfPLINE) - - - if not GUI_A['outputDWG_on'].val: - print 'writing to %s' % filepath - try: - d.saveas(filepath) - Window.WaitCursor(0) - #print '%s objects exported to %s' %(something_ready,filepath) - print '%s/%s objects exported in %.2f seconds. -----DONE-----' %(something_ready,selected_len,(Blender.sys.time()-t)) - Draw.PupMenu('DXF Exporter: job finished!| %s/%s objects exported in %.2f sek.' %(something_ready,selected_len, (Blender.sys.time()-t))) - except IOError: - Window.WaitCursor(0) - Draw.PupMenu('DXF Exporter: Write Error: Permission denied:| %s' %filepath) - - else: - if not extCONV_OK: - Draw.PupMenu(extCONV_TEXT) - Window.WaitCursor(False) - else: - print 'temp. exporting to %s' % filepath - d.saveas(filepath) - #Draw.PupMenu('DXF Exporter: job finished') - #print 'exported to %s' % filepath - #print 'finished in %.2f seconds' % (Blender.sys.time()-t) - filedwg = filepath[:-3]+'dwg' - print 'exporting to %s' % filedwg - os.system('%s %s -acad13 -dwg' %(extCONV_PATH,filepath)) - #os.chdir(cwd) - os.remove(filepath) - Window.WaitCursor(0) - print ' finished in %.2f seconds. -----DONE-----' % (Blender.sys.time()-t) - Draw.PupMenu('DWG Exporter: job finished!| %s/%s objects exported in %.2f sek.' %(something_ready,selected_len, (Blender.sys.time()-t))) - else: - Window.WaitCursor(0) - print "Abort: selected objects dont match choosen export option, nothing exported!" - Draw.PupMenu('DXF Exporter: nothing exported!|selected objects dont match choosen export option!') - - -#------------------------------------------------------ -""" -v = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,\ -28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,46,47,58,59,60,61,62,63,64,91,92,93,94,96,\ -123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,\ -151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,\ -171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,\ -191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,\ -211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,\ -231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254] -invalid = ''.join([chr(i) for i in v]) -del v, i -""" -#TODO: validDXFr14 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.' -validDXFr12 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_' - -#------------------------------------------------------ -def cleanName(name,valid): - validname = '' - for ch in name: - if ch not in valid: ch = '_' - validname += ch - return validname - -#------------------------------------------------------ -def validDXFr12name(str_name): - dxfname = str(str_name) - dxfname = dxfname[:NAMELENGTH_MAX].upper() - dxfname = cleanName(dxfname,validDXFr12) - return dxfname - -#print cleanName('dumka',validDXFr12) -#print validDXFr12name('dum 15%ka') - -#------------------------------------------------------ -def col2RGB(color): - return [int(floor(255*color[0])), - int(floor(255*color[1])), - int(floor(255*color[2]))] - -global dxfColors -dxfColors=None - -#------------------------------------------------------ -def col2DXF(rgbcolor): - global dxfColors - if dxfColors is None: - from dxfColorMap import color_map - dxfColors = [(tuple(color),idx) for idx, color in color_map.iteritems()] - dxfColors.sort() - entry = (tuple(rgbcolor), -1) - dxfColors.append(entry) - dxfColors.sort() - i = dxfColors.index(entry) - dxfColors.pop(i) - return dxfColors[i-1][1] - - - -# NEW UI -----#################################################----------------- -# ------------#################################################----------------- - -class Settings: #----------------------------------------------------------------- - """A container for all the export settings and objects. - - This is like a collection of globally accessable persistant properties and functions. - """ - # Optimization constants - MIN = 0 - MID = 1 - PRO = 2 - MAX = 3 - - def __init__(self, keywords, drawTypes): - """initialize all the important settings used by the export functions. - """ - self.obj_number = 1 #global object_number for progress_bar - - self.var = dict(keywords) #a dictionary of (key_variable:Value) control parameter - self.drawTypes = dict(drawTypes) #a dictionary of (entity_type:True/False) = import on/off for this entity_type - - self.var['colorFilter_on'] = False #deb:remi------------ - self.acceptedColors = [0,2,3,4,5,6,7,8,9, - 10 ] - - self.var['materialFilter_on'] = False #deb:remi------------ - self.acceptedLayers = ['3', - '0' - ] - - self.var['groupFilter_on'] = False #deb:remi------------ - self.acceptedLayers = ['3', - '0' - ] - - #self.var['objectFilter_on'] = 0 #deb:remi------------ - self.acceptedBlocks = ['WALL_1871', - 'BOX02' - ] - self.unwantedBlocks = ['BOX05', - 'BOX04' - ] - - - def update(self, keywords, drawTypes): - """update all the important settings used by the draw functions. - mostly used after loading parameters from INI-file - """ - - for k, v in keywords.iteritems(): - self.var[k] = v - #print 'deb:settings_update var %s= %s' %(k, self.var[k]) #-------------- - for t, v in drawTypes.iteritems(): - self.drawTypes[t] = v - #print 'deb:settings_update drawType %s= %s' %(t, self.drawTypes[t]) #-------------- - - self.drawTypes['arc'] = self.drawTypes['surface'] - self.drawTypes['circle'] = self.drawTypes['surface'] - self.drawTypes['ellipse'] = self.drawTypes['surface'] - self.drawTypes['trace'] = self.drawTypes['solid'] - self.drawTypes['insert'] = self.drawTypes['group'] - #self.drawTypes['vport'] = self.drawTypes['view'] - - #print 'deb:self.drawTypes', self.drawTypes #--------------- - - - def validate(self, drawing): - """Given the drawing, build dictionaries of Layers, Colors and Blocks. - """ - global oblist - #adjust the distance parameter to globalScale - if self.var['g_scale'] != 1.0: - self.var['dist_min'] = self.var['dist_min'] / self.var['g_scale'] - self.g_origin = Mathutils.Vector(self.var['g_originX'], self.var['g_originY'], self.var['g_originZ']) - - - def write(self, text, newline=True): - """Wraps the built-in print command in a optimization check. - """ - if self.var['optimization'] <= self.MID: - if newline: - print text - else: - print text, - - - def redraw(self): - """Update Blender if optimization level is low enough. - """ - if self.var['optimization'] <= self.MIN: - Blender.Redraw() - - - def progress(self, done, text): - """Wrapper for Blender.Window.DrawProgressBar. - """ - if self.var['optimization'] <= self.PRO: - progressbar = done * self.obj_number - Window.DrawProgressBar(progressbar, text) - #print 'deb:drawer done, progressbar: ', done, progressbar #----------------------- - - - -# GUI STUFF -----#################################################----------------- -from Blender.BGL import * - -EVENT_NONE = 1 -EVENT_START = 2 -EVENT_REDRAW = 3 -EVENT_LOAD_INI = 4 -EVENT_SAVE_INI = 5 -EVENT_RESET = 6 -EVENT_CHOOSE_INI = 7 -EVENT_CHOOSE_DXF = 8 -EVENT_HELP = 9 -EVENT_CAMERA = 10 -EVENT_LIGHT =11 -EVENT_DXF_DIR = 12 -EVENT_setCAMERA = 13 -# = 14 -EVENT_ORIGIN = 15 -EVENT_SCALE = 16 -EVENT_PRESET2D = 20 -EVENT_PRESET3D = 21 -EVENT_PRESETPLINE = 22 -EVENT_PRESETS = 23 -EVENT_EXIT = 100 - -GUI_A = {} # GUI-buttons dictionary for parameter -GUI_B = {} # GUI-buttons dictionary for drawingTypes - -# settings default, initialize ------------------------ - -#----------------------------------------------- -def prepareMenu(title,list): - menu = title - for i, item in enumerate(list): - menu += '|'+ item + ' %x' + str(i) - return menu - -#----------------------------------------------- -mesh_as_list = ["3DFACEs","POLYFACE","POLYLINE","LINEs","POINTs"] -mesh_as_menu = prepareMenu("export to: %t", mesh_as_list) - -curve_as_list = ["LINEs","POLYLINE","..LWPOLYLINE r14","..SPLINE r14","POINTs"] -curve_as_menu = prepareMenu("export to: %t", curve_as_list) - -surface_as_list = ["..3DFACEs","..POLYFACE","..POINTs","..NURBS"] -surface_as_menu = prepareMenu("export to: %t", surface_as_list) - -meta_as_list = ["..3DFACEs","..POLYFACE","..3DSOLID"] -meta_as_menu = prepareMenu("export to: %t", meta_as_list) - -text_as_list = ["TEXT","..MTEXT","..ATTRIBUT"] -text_as_menu = prepareMenu("export to: %t", text_as_list) - -empty_as_list = ["POINT","..INSERT","..XREF"] -empty_as_menu = prepareMenu("export to: %t|", empty_as_list) - -group_as_list = ["..GROUP","..BLOCK","..ungroup"] -group_as_menu = prepareMenu("export to: %t", group_as_list) - -parent_as_list = ["..BLOCK","..ungroup"] -parent_as_menu = prepareMenu("export to: %t", parent_as_list) - -proxy_as_list = ["..BLOCK","..XREF","..ungroup","..POINT"] -proxy_as_menu = prepareMenu("export to: %t", proxy_as_list) - -camera_as_list = ["..BLOCK","..A_CAMERA","VPORT","VIEW","POINT"] -camera_as_menu = prepareMenu("export to: %t", camera_as_list) - -lamp_as_list = ["..BLOCK","..A_LAMP","POINT"] -lamp_as_menu = prepareMenu("export to: %t", lamp_as_list) - -material_to_list= ["COLOR","LAYER","..LINESTYLE","..BLOCK","..XDATA","..INI-File"] -material_to_menu = prepareMenu("export to: %t", material_to_list) - -ltype_map_list= ["object_rgb","material_rgb","..map_table"] -ltype_map_menu = prepareMenu("export to: %t", ltype_map_list) - - - -layername_from_list = [LAYERNAME_DEF,"drawing_name","scene_name"] -layername_from_menu = prepareMenu("defaultLAYER: %t", layername_from_list) - -layerltype_def_list = ["CONTINUOUS","DOT","DASHED","DASHDOT","BORDER","HIDDEN"] -layerltype_def_menu = prepareMenu("LINETYPE set to: %t",layerltype_def_list) - -entitylayer_from_list = ["default_LAYER","obj.name","obj.layer","obj.material","obj.data.name","obj.data.material","..vertexgroup","..group","..map_table"] -entitylayer_from_menu = prepareMenu("entityLAYER from: %t", entitylayer_from_list) -#print 'deb: entitylayer_from_menu=', entitylayer_from_menu #-------------- - -entitycolor_from_list = ["default_COLOR","BYLAYER","BYBLOCK","obj.layer","obj.color","obj.material","obj.data.material","..map_table"] -entitycolor_from_menu = prepareMenu("entityCOLOR set to: %t",entitycolor_from_list) - -entityltype_from_list = ["default_LTYPE","BYLAYER","BYBLOCK","CONTINUOUS","DOT","DASHED","DASHDOT","BORDER","HIDDEN"] -entityltype_from_menu = prepareMenu("entityCOLOR set to: %t",entityltype_from_list) - -#dxf-LINE,ARC,CIRCLE,ELLIPSE - -g_scale_list = ''.join(( - 'scale factor: %t', - '|user def. %x12', - '|yard to m %x8', - '|feet to m %x7', - '|inch to m %x6', - '| x 100000 %x5', - '| x 10000 %x4', - '| x 1000 %x3', - '| x 100 %x2', - '| x 10 %x1', - '| x 1 %x0', - '| x 0.1 %x-1', - '| x 0.01 %x-2', - '| x 0.001 %x-3', - '| x 0.0001 %x-4', - '| x 0.00001 %x-5')) - -#print 'deb: g_scale_list', g_scale_list #----------- - -dxfFileName = Draw.Create("") -iniFileName = Draw.Create(INIFILE_DEFAULT_NAME + INIFILE_EXTENSION) -user_preset = 0 -config_UI = Draw.Create(0) #switch_on/off extended config_UI -g_scale_as = Draw.Create(int(log10(G_SCALE))) - - -keywords_org = { - 'optimization': 2, - 'dummy_on' : 0, - - 'xref_on' : 1, - 'block_nn': 0, - - 'paper_space_on': 0, - 'layFrozen_on': 0, - 'objectFilter_on': 0, - 'materialFilter_on': 0, - 'colorFilter_on': 0, - 'groupFilter_on': 0, - - 'only_selected_on': ONLYSELECTED, - 'only_visible_on': ONLYVISIBLE, - 'projection_on' : PROJECTION, - 'hidden_lines_on': HIDDEN_LINES, - 'shadows_on' : SHADOWS, - 'light_on' : 1, - 'outputDWG_on' : OUTPUT_DWG, - 'to_polyline_on': POLYLINES, - 'to_polyface_on': POLYFACES, - 'instances_on': INSTANCES, - 'apply_modifiers_on': APPLY_MODIFIERS, - 'include_duplis_on': INCLUDE_DUPLIS, - 'camera_selected': CAMERA, - - 'g_originX' : G_ORIGIN[0], - 'g_originY' : G_ORIGIN[1], - 'g_originZ' : G_ORIGIN[2], - 'g_origin_on': 0, - 'g_scale' : float(G_SCALE), -# 'g_scale_as': int(log10(G_SCALE)), # 0, - 'g_scale_on': 0, - 'Z_force_on': 0, - 'Z_elev': float(ELEVATION), - - - 'prefix_def' : PREFIX, - 'layername_def' : LAYERNAME_DEF, - 'layercolor_def': LAYERCOLOR_DEF, - 'layerltype_def': LAYERLTYPE_DEF, - 'entitylayer_from': 5, - 'entitycolor_from': 1, - 'entityltype_from' : 1, - - 'material_on': 1, - 'material_to': 2, - 'fill_on' : 1, - - 'mesh_as' : 1, - 'curve_as' : 1, - 'surface_as' : 1, - 'meta_as' : 1, - 'text_as' : 0, - 'empty_as' : 0, - 'group_as' : 0, - 'parent_as' : 0, - 'proxy_as' : 0, - 'camera_as': 3, - 'lamp_as' : 2, - } - -drawTypes_org = { - 'bmesh' : 1, - 'bcurve': 1, - 'surface': 0, - 'bmeta' : 0, - 'text' : 1, - 'empty' : 1, - 'group' : 1, - 'parent': 1, - 'proxy' : 0, - 'camera': 0, - 'lamp' : 0, - -# 'view' : 0, - } - -# creating of GUI-buttons -# GUI_A - GUI-buttons dictionary for parameter -# GUI_B - GUI-buttons dictionary for drawingTypes -for k, v in keywords_org.iteritems(): - GUI_A[k] = Draw.Create(v) -for k, v in drawTypes_org.iteritems(): - GUI_B[k] = Draw.Create(v) -#print 'deb:init GUI_A: ', GUI_A #--------------- -#print 'deb:init GUI_B: ', GUI_B #--------------- - -model_space_on = Draw.Create(1) - -# initialize settings-object controls how dxf entities are drawn -settings = Settings(keywords_org, drawTypes_org) - - -def update_RegistryKey(key, item): # - """updates key in Blender.Registry - """ - cache = True # data is also saved to a file - rdict = Registry.GetKey('DXF_Exporter', cache) - if not rdict: rdict = {} - if item: - rdict[key] = item - Registry.SetKey('DXF_Exporter', rdict, cache) - #print 'deb:update_RegistryKey rdict', rdict #--------------- - - -def check_RegistryKey(key): - """ check if the key is already there (saved on a previous execution of this script) - """ - cache = True # data is also saved to a file - rdict = Registry.GetKey('DXF_Exporter', cache) - #print 'deb:check_RegistryKey rdict:', rdict #---------------- - if rdict: # if found, get the values saved there - try: - item = rdict[key] - return item - except: - #update_RegistryKey() # if data isn't valid rewrite it - pass - -def saveConfig(): #--todo----------------------------------------------- - """Save settings/config/materials from GUI to INI-file. - - Write all config data to INI-file. - """ - global iniFileName - - iniFile = iniFileName.val - #print 'deb:saveConfig inifFile: ', inifFile #---------------------- - if iniFile.lower().endswith(INIFILE_EXTENSION): - - #--todo-- sort key.list for output - #key_list = GUI_A.keys().val - #key_list.sort() - #for key in key_list: - # l_name, l_data = key, GUI_A[key].val - # list_A - - output_str = '[%s,%s]' %(GUI_A, GUI_B) - if output_str =='None': - Draw.PupMenu('DXF-Exporter: INI-file: Alert!%t|no config-data present to save!') - else: - if Blender.sys.exists(iniFile): - f = file(iniFile, 'r') - header_str = f.readline() - f.close() - if header_str.startswith(INIFILE_HEADER[0:13]): - if Draw.PupMenu(' OK ? %t|SAVE OVER: ' + '\'%s\'' %iniFile) == 1: - save_ok = True - else: save_ok = False - elif Draw.PupMenu(' OK ? %t|SAVE OVER: ' + '\'%s\'' %iniFile + - '|Alert: this file has no valid ImportDXF-header| ! it may belong to another aplication !') == 1: - save_ok = True - else: save_ok = False - else: save_ok = True - - if save_ok: - # replace: ',' -> ',\n' - # replace: '{' -> '\n{\n' - # replace: '}' -> '\n}\n' - output_str = ',\n'.join(output_str.split(',')) - output_str = '\n}'.join(output_str.split('}')) - output_str = '{\n'.join(output_str.split('{')) - try: - f = file(iniFile, 'w') - f.write(INIFILE_HEADER + '\n# this is a comment line\n') - f.write(output_str) - f.close() - #Draw.PupMenu('DXF-Exporter: INI-file: Done!%t|config-data saved in ' + '\'%s\'' %iniFile) - except: - Draw.PupMenu('DXF-Exporter: INI-file: Error!%t|failure by writing to ' + '\'%s\'|no config-data saved!' %iniFile) - - else: - Draw.PupMenu('DXF-Exporter: INI-file: Alert!%t|no valid name/extension for INI-file selected!') - print "DXF-Exporter: Alert!: no valid INI-file selected." - if not iniFile: - if dxfFileName.val.lower().endswith('.dxf'): - iniFileName.val = dxfFileName.val[0:-4] + INIFILE_EXTENSION - - -def loadConfig(): #remi--todo----------------------------------------------- - """Load settings/config/materials from INI-file. - - TODO: Read material-assignements from config-file. - """ - #20070724 buggy Window.FileSelector(loadConfigFile, 'Load config data from INI-file', inifilename) - global iniFileName, GUI_A, GUI_B - - iniFile = iniFileName.val - update_RegistryKey('iniFileName', iniFile) - #print 'deb:loadConfig iniFile: ', iniFile #---------------------- - if iniFile.lower().endswith(INIFILE_EXTENSION) and Blender.sys.exists(iniFile): - f = file(iniFile, 'r') - header_str = f.readline() - if header_str.startswith(INIFILE_HEADER): - data_str = f.read() - f.close() - #print 'deb:loadConfig data_str from %s: \n' %iniFile , data_str #----------------- - data = eval(data_str) - for k, v in data[0].iteritems(): - try: GUI_A[k].val = v - except: GUI_A[k] = Draw.Create(v) - for k, v in data[1].iteritems(): - try: GUI_B[k].val = v - except: GUI_B[k] = Draw.Create(v) - else: - f.close() - Draw.PupMenu('DXF-Exporter: INI-file: Alert!%t|no valid header in INI-file: ' + '\'%s\'' %iniFile) - else: - Draw.PupMenu('DXF-Exporter: INI-file: Alert!%t|no valid INI-file selected!') - print "DXF-Exporter: Alert!: no valid INI-file selected." - if not iniFileName: - if dxfFileName.val.lower().endswith('.dxf'): - iniFileName.val = dxfFileName.val[0:-4] + INIFILE_EXTENSION - - - -def updateConfig(keywords, drawTypes): #----------------------------------------------- - """updates GUI_settings with given dictionaries - - """ - global GUI_A, GUI_B - #print 'deb:lresetDefaultConfig keywords_org: \n', keywords_org #--------- - for k, v in keywords.iteritems(): - GUI_A[k].val = v - for k, v in drawTypes.iteritems(): - GUI_B[k].val = v - -def resetDefaultConfig(): #----------------------------------------------- - """Resets settings/config/materials to defaults. - - """ - #print 'deb:lresetDefaultConfig keywords_org: \n', keywords_org #--------- - updateConfig(keywords_org, drawTypes_org) - - -def presetConfig_polyline(activate): #----------------------------------------------- - """Sets settings/config for polygon representation: POLYLINE(FACE) or LINEs/3DFACEs. - - """ - global GUI_A - if activate: - GUI_A['to_polyline_on'].val = 1 - GUI_A['mesh_as'].val = 1 - GUI_A['curve_as'].val = 1 - else: - GUI_A['to_polyline_on'].val = 0 - GUI_A['mesh_as'].val = 0 - GUI_A['curve_as'].val = 0 - -def resetDefaultConfig_2D(): #----------------------------------------------- - """Sets settings/config/materials to defaults 2D. - - """ - keywords2d = { - 'projection_on' : 1, - 'fill_on' : 1, - 'text_as' : 0, - 'group_as' : 0, - } - - drawTypes2d = { - 'bmesh' : 1, - 'bcurve': 1, - 'surface':0, - 'bmeta' : 0, - 'text' : 1, - 'empty' : 1, - 'group' : 1, - 'parent' : 1, - #'proxy' : 0, - #'camera': 0, - #'lamp' : 0, - - } - presetConfig_polyline(1) - updateConfig(keywords2d, drawTypes2d) - -def resetDefaultConfig_3D(): #----------------------------------------------- - """Sets settings/config/materials to defaults 3D. - - """ - keywords3d = { - 'projection_on' : 0, - 'fill_on' : 0, - 'text_as' : 0, - 'group_as' : 0, - } - - drawTypes3d = { - 'bmesh' : 1, - 'bcurve': 1, - 'surface':0, - 'bmeta' : 0, - 'text' : 0, - 'empty' : 1, - 'group' : 1, - 'parent' : 1, - #'proxy' : 0, - #'camera': 1, - #'lamp' : 1, - } - presetConfig_polyline(1) - updateConfig(keywords3d, drawTypes3d) - - -def inputGlobalScale(): - """Pop-up UI-Block for global scale factor - """ - global GUI_A - #print 'deb:inputGlobalScale ##########' #------------ - x_scale = Draw.Create(GUI_A['g_scale'].val) - block = [] - #block.append("global translation vector:") - block.append(("", x_scale, 0.0, 10000000.0)) - - retval = Draw.PupBlock("set global scale factor:", block) - - GUI_A['g_scale'].val = float(x_scale.val) - - -def inputOriginVector(): - """Pop-up UI-Block for global translation vector - """ - global GUI_A - #print 'deb:inputOriginVector ##########' #------------ - x_origin = Draw.Create(GUI_A['g_originX'].val) - y_origin = Draw.Create(GUI_A['g_originY'].val) - z_origin = Draw.Create(GUI_A['g_originZ'].val) - block = [] - #block.append("global translation vector:") - block.append(("X: ", x_origin, -100000000.0, 100000000.0)) - block.append(("Y: ", y_origin, -100000000.0, 100000000.0)) - block.append(("Z: ", z_origin, -100000000.0, 100000000.0)) - - retval = Draw.PupBlock("set global translation vector:", block) - - GUI_A['g_originX'].val = x_origin.val - GUI_A['g_originY'].val = y_origin.val - GUI_A['g_originZ'].val = z_origin.val - - -def update_globals(): #----------------------------------------------------------------- - """ update globals if GUI_A changed - """ - global ONLYSELECTED,ONLYVISIBLE, DEBUG,\ - PROJECTION, HIDDEN_LINES, CAMERA, \ - G_SCALE, G_ORIGIN,\ - PREFIX, LAYERNAME_DEF, LAYERCOLOR_DEF, LAYERLTYPE_DEF,\ - APPLY_MODIFIERS, INCLUDE_DUPLIS,\ - OUTPUT_DWG - #global POLYLINES - - ONLYSELECTED = GUI_A['only_selected_on'].val - ONLYVISIBLE = GUI_A['only_visible_on'].val - """ - POLYLINES = GUI_A['to_polyline_on'].val - if GUI_A['curve_as'].val==1: POLYLINES=1 - else: POLYLINES=0 - """ - - if GUI_A['optimization'].val==0: DEBUG = 1 - else: DEBUG = 0 - PROJECTION = GUI_A['projection_on'].val - HIDDEN_LINES = GUI_A['hidden_lines_on'].val - CAMERA = GUI_A['camera_selected'].val - G_SCALE = GUI_A['g_scale'].val - if GUI_A['g_origin_on'].val: - G_ORIGIN[0] = GUI_A['g_originX'].val - G_ORIGIN[1] = GUI_A['g_originY'].val - G_ORIGIN[2] = GUI_A['g_originZ'].val - if GUI_A['g_scale_on'].val: - G_ORIGIN[0] *= G_SCALE - G_ORIGIN[1] *= G_SCALE - G_ORIGIN[2] *= G_SCALE - - PREFIX = GUI_A['prefix_def'].val - LAYERNAME_DEF = GUI_A['layername_def'].val - LAYERCOLOR_DEF = GUI_A['layercolor_def'].val - LAYERLTYPE_DEF = layerltype_def_list[GUI_A['layerltype_def'].val] - - APPLY_MODIFIERS = GUI_A['apply_modifiers_on'].val - INCLUDE_DUPLIS = GUI_A['include_duplis_on'].val - OUTPUT_DWG = GUI_A['outputDWG_on'].val - #print 'deb: GUI HIDDEN_LINES=', HIDDEN_LINES #--------- - #print 'deb: GUI GUI_A: ', GUI_A['hidden_lines_on'].val #--------------- - #print 'deb: GUI GUI_B: ', GUI_B #--------------- - - -def draw_UI(): #----------------------------------------------------------------- - """ Draw startUI and setup Settings. - """ - global GUI_A, GUI_B #__version__ - global user_preset, iniFileName, dxfFileName, config_UI, g_scale_as - global model_space_on - global SCROLL - - global mPAN_X, menu_orgX, mPAN_Xmax - global mPAN_Y, menu_orgY, mPAN_Ymax - global menu__Area, headerArea, screenArea, scrollArea - - size=Buffer(GL_FLOAT, 4) - glGetFloatv(GL_SCISSOR_BOX, size) #window X,Y,sizeX,sizeY - size= size.list - #print '-------------size:', size #-------------------------- - for s in [0,1,2,3]: size[s]=int(size[s]) - window_Area = [0,0,size[2],size[3]-2] - scrollXArea = [0,0,window_Area[2],15] - scrollYArea = [0,0,15,window_Area[3]] - - menu_orgX = -mPAN_X - #menu_orgX = 0 #scrollW - #if menu_pan: menu_orgX -= mPAN_X - if menu_orgX < -mPAN_Xmax: menu_orgX, mPAN_X = -mPAN_Xmax,mPAN_Xmax - if menu_orgX > 0: menu_orgX, mPAN_X = 0,0 - - menu_orgY = -mPAN_Y - #if menu_pan: menu_orgY -= mPAN_Y - if menu_orgY < -mPAN_Ymax: menu_orgY, mPAN_Y = -mPAN_Ymax,mPAN_Ymax - if menu_orgY > 0: menu_orgY, mPAN_Y = 0,0 - - - menu_margin = 10 - butt_margin = 10 - common_column = int((window_Area[2] - (3 * butt_margin) - (2 * menu_margin)-30) / 4.0) - common_column = 70 - # This is for easy layout changes - but_0c = common_column #button 1.column width - but_1c = common_column #button 1.column width - but_2c = common_column #button 2.column - but_3c = common_column #button 3.column - menu_w = (3 * butt_margin) + but_0c + but_1c + but_2c + but_3c #menu width - - simple_menu_h = 260 - extend_menu_h = 345 - menu_h = simple_menu_h # y is menu upper.y - if config_UI.val: - menu_h += extend_menu_h - - mPAN_Xmax = menu_w-window_Area[2]+50 - mPAN_Ymax = menu_h-window_Area[3]+30 - - y = menu_h - x = 0 #menu left.x - x +=menu_orgX+20 - y +=menu_orgY+20 - - - but0c = x + menu_margin #buttons 0.column position.x - but1c = but0c + but_0c + butt_margin - but2c = but1c + but_1c + butt_margin - but3c = but2c + but_2c + butt_margin - but4c = but3c + but_3c - - # Here starts menu ----------------------------------------------------- - #glClear(GL_COLOR_BUFFER_BIT) - #glRasterPos2d(8, 125) - - - ui_box(x, y, x+menu_w+menu_margin*2, y-menu_h) - y -= 20 - Draw.Label("DXF(r12)-Exporter v" + __version__, but0c, y, menu_w, 20) - - if config_UI.val: - b0, b0_ = but0c, but_0c-20 + butt_margin - b1, b1_ = but1c-20, but_1c+20 - y_top = y - - y -= 10 - y -= 20 - Draw.BeginAlign() - GUI_B['bmesh'] = Draw.Toggle('Mesh', EVENT_REDRAW, b0, y, b0_, 20, GUI_B['bmesh'].val, "Export Mesh-Objects on/off") - if GUI_B['bmesh'].val: - GUI_A['mesh_as'] = Draw.Menu(mesh_as_menu, EVENT_NONE, b1, y, b1_, 20, GUI_A['mesh_as'].val, "Select target DXF-object") - Draw.EndAlign() - - y -= 20 - Draw.BeginAlign() - GUI_B['bcurve'] = Draw.Toggle('Curve', EVENT_REDRAW, b0, y, b0_, 20, GUI_B['bcurve'].val, "Export Curve-Objects on/off") - if GUI_B['bcurve'].val: - GUI_A['curve_as'] = Draw.Menu(curve_as_menu, EVENT_NONE, b1, y, b1_, 20, GUI_A['curve_as'].val, "Select target DXF-object") - Draw.EndAlign() - - y -= 20 - Draw.BeginAlign() - GUI_B['surface'] = Draw.Toggle('..Surface', EVENT_REDRAW, b0, y, b0_, 20, GUI_B['surface'].val, "(*todo) Export Surface-Objects on/off") - if GUI_B['surface'].val: - GUI_A['surface_as'] = Draw.Menu(surface_as_menu, EVENT_NONE, b1, y, b1_, 20, GUI_A['surface_as'].val, "Select target DXF-object") - Draw.EndAlign() - - y -= 20 - Draw.BeginAlign() - GUI_B['bmeta'] = Draw.Toggle('..Meta', EVENT_REDRAW, b0, y, b0_, 20, GUI_B['bmeta'].val, "(*todo) Export Meta-Objects on/off") - if GUI_B['bmeta'].val: - GUI_A['meta_as'] = Draw.Menu(meta_as_menu, EVENT_NONE, b1, y, b1_, 20, GUI_A['meta_as'].val, "Select target DXF-object") - Draw.EndAlign() - - y -= 20 - Draw.BeginAlign() - GUI_B['text'] = Draw.Toggle('Text', EVENT_REDRAW, b0, y, b0_, 20, GUI_B['text'].val, "Export Text-Objects on/off") - if GUI_B['text'].val: - GUI_A['text_as'] = Draw.Menu(text_as_menu, EVENT_NONE, b1, y, b1_, 20, GUI_A['text_as'].val, "Select target DXF-object") - Draw.EndAlign() - - y -= 20 - Draw.BeginAlign() - GUI_B['empty'] = Draw.Toggle('Empty', EVENT_REDRAW, b0, y, b0_, 20, GUI_B['empty'].val, "Export Empty-Objects on/off") - if GUI_B['empty'].val: - GUI_A['empty_as'] = Draw.Menu(empty_as_menu, EVENT_NONE, b1, y, b1_, 20, GUI_A['empty_as'].val, "Select target DXF-object") - Draw.EndAlign() - - y_down = y - # ----------------------------------------------- - - y = y_top - b0, b0_ = but2c, but_2c-20 + butt_margin - b1, b1_ = but3c-20, but_3c+20 - - y -= 10 - y -= 20 - Draw.BeginAlign() - GUI_B['group'] = Draw.Toggle('..Group', EVENT_REDRAW, b0, y, b0_, 20, GUI_B['group'].val, "(*todo) Export Group-Relationships on/off") - if GUI_B['group'].val: - GUI_A['group_as'] = Draw.Menu(group_as_menu, EVENT_NONE, b1, y, b1_, 20, GUI_A['group_as'].val, "Select target DXF-object") - Draw.EndAlign() - - y -= 20 - Draw.BeginAlign() - GUI_B['parent'] = Draw.Toggle('..Parent', EVENT_REDRAW, b0, y, b0_, 20, GUI_B['parent'].val, "(*todo) Export Parent-Relationships on/off") - if GUI_B['parent'].val: - GUI_A['parent_as'] = Draw.Menu(parent_as_menu, EVENT_NONE, b1, y, b1_, 20, GUI_A['parent_as'].val, "Select target DXF-object") - Draw.EndAlign() - - y -= 20 - Draw.BeginAlign() - GUI_B['proxy'] = Draw.Toggle('..Proxy', EVENT_REDRAW, b0, y, b0_, 20, GUI_B['proxy'].val, "(*todo) Export Proxy-Objects on/off") - if GUI_B['proxy'].val: - GUI_A['proxy_as'] = Draw.Menu(proxy_as_menu, EVENT_NONE, b1, y, b1_, 20, GUI_A['proxy_as'].val, "Select target DXF-object") - Draw.EndAlign() - - y -= 20 - Draw.BeginAlign() - GUI_B['camera'] = Draw.Toggle('Camera', EVENT_REDRAW, b0, y, b0_, 20, GUI_B['camera'].val, "(*wip) Export Camera-Objects on/off") - if GUI_B['camera'].val: - GUI_A['camera_as'] = Draw.Menu(camera_as_menu, EVENT_NONE, b1, y, b1_, 20, GUI_A['camera_as'].val, "Select target DXF-object") - Draw.EndAlign() - - y -= 20 - Draw.BeginAlign() - GUI_B['lamp'] = Draw.Toggle('Lamp', EVENT_REDRAW, b0, y, b0_, 20, GUI_B['lamp'].val, "(*wip) Export Lamp-Objects on/off") - if GUI_B['lamp'].val: - GUI_A['lamp_as'] = Draw.Menu(lamp_as_menu, EVENT_NONE, b1, y, b1_, 20, GUI_A['lamp_as'].val, "Select target DXF-object") - Draw.EndAlign() - - - if y < y_down: y_down = y - # -----end supported objects-------------------------------------- - - y_top = y_down - y = y_top - y -= 10 - y -= 20 - but_ = menu_w / 6 - b0 = but0c + (menu_w - but_*6)/2 - Draw.BeginAlign() - #GUI_A['dummy_on'] = Draw.Toggle('-', EVENT_NONE, b0+but_*0, y, but_, 20, GUI_A['dummy_on'].val, "placeholder only on/off") - GUI_A['paper_space_on'] = Draw.Toggle('Paper', EVENT_NONE, b0+but_*0, y, but_, 20, GUI_A['paper_space_on'].val, "Export to Paper-Space, otherwise to Model-Space on/off") - GUI_A['layFrozen_on'] = Draw.Toggle ('..frozen', EVENT_NONE, b0+but_*1, y, but_, 20, GUI_A['layFrozen_on'].val, "(*todo) Support LAYER.frozen status on/off") - GUI_A['materialFilter_on'] = Draw.Toggle('..material', EVENT_NONE, b0+but_*2, y, but_, 20, GUI_A['materialFilter_on'].val, "(*todo) Material filtering on/off") - GUI_A['colorFilter_on'] = Draw.Toggle('..color', EVENT_NONE, b0+but_*3, y, but_, 20, GUI_A['colorFilter_on'].val, "(*todo) Color filtering on/off") - GUI_A['groupFilter_on'] = Draw.Toggle('..group', EVENT_NONE, b0+but_*4, y, but_, 20, GUI_A['groupFilter_on'].val, "(*todo) Group filtering on/off") - GUI_A['objectFilter_on'] = Draw.Toggle('..object', EVENT_NONE, b0+but_*5, y, but_, 20, GUI_A['objectFilter_on'].val, "(*todo) Object filtering on/off") - Draw.EndAlign() - - # -----end filters-------------------------------------- - - b0, b0_ = but0c, but_0c + butt_margin - b1, b1_ = but1c, but_1c - - y -= 10 - y -= 20 - Draw.BeginAlign() - GUI_A['g_origin_on'] = Draw.Toggle('Location', EVENT_REDRAW, b0, y, b0_, 20, GUI_A['g_origin_on'].val, "Global relocate all objects on/off") - if GUI_A['g_origin_on'].val: - tmp = Draw.PushButton('=', EVENT_ORIGIN, b1, y, 20, 20, "Edit relocation-vector (x,y,z in DXF units)") - origin_str = '(%.4f, %.4f, %.4f)' % ( - GUI_A['g_originX'].val, - GUI_A['g_originY'].val, - GUI_A['g_originZ'].val - ) - tmp = Draw.Label(origin_str, b1+20, y, 300, 20) - Draw.EndAlign() - - y -= 20 - Draw.BeginAlign() - GUI_A['g_scale_on'] = Draw.Toggle('Scale', EVENT_REDRAW, b0, y, b0_, 20, GUI_A['g_scale_on'].val, "Global scale all objects on/off") - if GUI_A['g_scale_on'].val: - g_scale_as = Draw.Menu(g_scale_list, EVENT_SCALE, b1, y, 45, 20, g_scale_as.val, "Factor for scaling the DXFdata") - if g_scale_as.val == 12: - pass - else: - if g_scale_as.val == 6: #scale inches to meters - GUI_A['g_scale'].val = 0.0254000 - elif g_scale_as.val == 7: #scale feets to meters - GUI_A['g_scale'].val = 0.3048000 - elif g_scale_as.val == 8: #scale yards to meters - GUI_A['g_scale'].val = 0.9144000 - else: - GUI_A['g_scale'].val = 10.0 ** int(g_scale_as.val) - scale_float = GUI_A['g_scale'].val - if scale_float < 0.000001 or scale_float > 1000000: - scale_str = ' = %s' % GUI_A['g_scale'].val - else: - scale_str = ' = %.6f' % GUI_A['g_scale'].val - Draw.Label(scale_str, b1+45, y, 200, 20) - Draw.EndAlign() - - y -= 20 - Draw.BeginAlign() - GUI_A['Z_force_on'] = Draw.Toggle('Elevation', EVENT_REDRAW, b0, y, b0_, 20, GUI_A['Z_force_on'].val, "Overwrite Z-coordinates (flatten geometry) on/off") - if GUI_A['Z_force_on'].val: - GUI_A['Z_elev'] = Draw.Number('', EVENT_NONE, b1, y, b1_, 20, GUI_A['Z_elev'].val, -1000, 1000, "Set value for default Z-coordinate (in DXF units)") - Draw.EndAlign() - - """ - y -= 30 - Draw.BeginAlign() - GUI_A['material_on'] = Draw.Toggle('.material', EVENT_REDRAW, b0, y, b0_-20, 20, GUI_A['material_on'].val, "Support for material assignment on/off") - if GUI_A['material_on'].val: - GUI_A['material_to'] = Draw.Menu(material_to_menu, EVENT_NONE, b1-20, y, b1_+20, 20, GUI_A['material_to'].val, "Material assigned to?") - Draw.EndAlign() - """ - - #b0, b0_ = but0c, but_0c + butt_margin - b0, b0_ = but0c, 50 - b1, b1_ = b0+b0_, but_0c-b0_+ but_1c + butt_margin - b2, b2_ = but2c, but_2c - b3, b3_ = but3c, but_3c - - y -= 30 - Draw.Label('Output:', b0, y, b0_, 20) - Draw.Label('LAYER:', b1, y, b1_, 20) - Draw.Label('COLOR:', b2, y, b2_, 20) - Draw.Label('LINETYPE:', b3, y, b3_, 20) - #Draw.Label('LINESIZE:', b4, y, b4_, 20) - - y -= 20 - Draw.BeginAlign() - GUI_A['prefix_def'] = Draw.String('', EVENT_NONE, b0, y, b0_, 20, GUI_A['prefix_def'].val, 10, "Type Prefix for LAYERs") - GUI_A['layername_def'] = Draw.String('', EVENT_NONE, b1, y, b1_, 20, GUI_A['layername_def'].val, 10, "Type default LAYER name") - GUI_A['layercolor_def'] = Draw.Number('', EVENT_NONE, b2, y, b2_, 20, GUI_A['layercolor_def'].val, 1, 255, "Set default COLOR. (0=BYBLOCK,256=BYLAYER)") - GUI_A['layerltype_def'] = Draw.Menu(layerltype_def_menu, EVENT_NONE, b3, y, b3_, 20, GUI_A['layerltype_def'].val, "Set default LINETYPE") - Draw.EndAlign() - - y -= 25 - Draw.Label('Style:', b0, y, b0_, 20) - Draw.BeginAlign() - GUI_A['entitylayer_from'] = Draw.Menu(entitylayer_from_menu, EVENT_NONE, b1, y, b1_, 20, GUI_A['entitylayer_from'].val, "entity LAYER assigned to?") - GUI_A['entitycolor_from'] = Draw.Menu(entitycolor_from_menu, EVENT_NONE, b2, y, b2_, 20, GUI_A['entitycolor_from'].val, "entity COLOR assigned to?") - GUI_A['entityltype_from'] = Draw.Menu(entityltype_from_menu, EVENT_NONE, b3, y, b3_, 20, GUI_A['entityltype_from'].val, "Set entity LINETYPE") - Draw.EndAlign() - - y -= 10 - - y_down = y - # -----end material,translate,scale------------------------------------------ - - - #-------------------------------------- - y_top = y_down - y = y_top - - y -= 30 - Draw.BeginAlign() - Draw.PushButton('INI file >', EVENT_CHOOSE_INI, but0c, y, but_0c, 20, 'Select INI-file with file selector') - iniFileName = Draw.String(' :', EVENT_NONE, but1c, y, menu_w-but_1c-60, 20, iniFileName.val, FILENAME_MAX, "Write here the name of the INI-file") - but = but4c-60 - Draw.PushButton('#', EVENT_PRESETS, but, y, 20, 20, "Toggle Preset-INI-files") - Draw.PushButton('L', EVENT_LOAD_INI, but+20, y, 20, 20, 'Loads configuration from selected ini-file: %s' % iniFileName.val) - Draw.PushButton('S', EVENT_SAVE_INI, but+40, y, 20, 20, 'Saves configuration to selected ini-file: %s' % iniFileName.val) - Draw.EndAlign() - - bm = butt_margin/2 - - y -= 10 - y -= 20 - Draw.BeginAlign() - Draw.PushButton('DXFfile >', EVENT_CHOOSE_DXF, but0c, y, but_0c, 20, 'Select DXF-file with file selector') - dxfFileName = Draw.String(' :', EVENT_NONE, but1c, y, menu_w-but_0c-menu_margin, 20, dxfFileName.val, FILENAME_MAX, "Type path/name of output DXF-file") - Draw.EndAlign() - - y -= 30 - config_UI = Draw.Toggle('CONFIG', EVENT_REDRAW, but0c, y, but_0c+bm, 20, config_UI.val, 'Advanced configuration on/off' ) - Draw.BeginAlign() - but, but_ = but1c, but_1c+bm - but_ /= 3 - Draw.PushButton('X', EVENT_RESET, but, y, 15, 20, "Reset configuration to defaults") - Draw.PushButton('2D', EVENT_PRESET2D, but+but_, y, but_, 20, 'Set to standard configuration for 2D export') - Draw.PushButton('3D', EVENT_PRESET3D, but+(but_*2), y, but_, 20, 'Set to standard configuration for 3D import') - Draw.EndAlign() - - - y -= 30 - b0, b0_ = but0c, but_0c + butt_margin +but_1c - GUI_A['only_selected_on'] = Draw.Toggle('Export Selection', EVENT_NONE, b0, y, b0_, 20, GUI_A['only_selected_on'].val, "Export only selected geometry on/off") - b0, b0_ = but2c, but_2c + butt_margin + but_3c - Draw.BeginAlign() - GUI_A['projection_on'] = Draw.Toggle('2d Projection', EVENT_REDRAW, b0, y, b0_, 20, GUI_A['projection_on'].val, "Export a 2d Projection according 3d-View or Camera-View on/off") - if GUI_A['projection_on'].val: - GUI_A['camera_selected'] = Draw.Menu(MenuCAMERA, EVENT_CAMERA, b0, y-20, b0_-20, 20, GUI_A['camera_selected'].val, 'Choose the camera to be rendered') - Draw.PushButton('>', EVENT_setCAMERA, b0+b0_-20, y-20, 20, 20, 'switch to selected Camera - make it active') - GUI_A['hidden_lines_on'] = Draw.Toggle('Remove backFaces', EVENT_NONE, b0, y-40, b0_, 20, GUI_A['hidden_lines_on'].val, "Filter out backFaces on/off") - #GUI_A['shadows_on'] = Draw.Toggle('..Shadows', EVENT_REDRAW, b0, y-60, but_2c, 20, GUI_A['shadows_on'].val, "(*todo) Shadow tracing on/off") - #GUI_A['light_on'] = Draw.Menu(MenuLIGHT, EVENT_LIGHT, but3c, y-60, but_3c, 20, GUI_A['light_on'].val, '(*todo) Choose the light source(sun) to be rendered') - Draw.EndAlign() - - y -= 20 - b0, b0_ = but0c, but_0c + butt_margin +but_1c - GUI_A['only_visible_on'] = Draw.Toggle('Visible only', EVENT_PRESETPLINE, b0, y, b0_, 20, GUI_A['only_visible_on'].val, "Export only from visible layers on/off") - #b0, b0_ = but2c, but_2c + butt_margin + but_3c - - y -= 20 - b0, b0_ = but0c, but_0c + butt_margin +but_1c - GUI_A['to_polyline_on'] = Draw.Toggle('POLYLINE-Mode', EVENT_PRESETPLINE, b0, y, b0_, 20, GUI_A['to_polyline_on'].val, "Export to POLYLINE/POLYFACEs, otherwise to LINEs/3DFACEs on/off") - #b0, b0_ = but2c, but_2c + butt_margin + but_3c - - y -= 20 - b0, b0_ = but0c, but_0c + butt_margin +but_1c - GUI_A['instances_on'] = Draw.Toggle('Instances as BLOCKs', EVENT_NONE, b0, y, b0_, 20, GUI_A['instances_on'].val, "Export instances (multi-users) of Mesh/Curve as BLOCK/INSERTs on/off") - #b0, b0_ = but2c, but_2c + butt_margin + but_3c - - y -= 20 - b0, b0_ = but0c, but_0c + butt_margin +but_1c - GUI_A['apply_modifiers_on'] = Draw.Toggle('Apply Modifiers', EVENT_NONE, b0, y, b0_, 20, GUI_A['apply_modifiers_on'].val, "Apply modifier stack to mesh objects before export on/off") - #b0, b0_ = but2c, but_2c + butt_margin + but_3c - - y -= 20 - b0, b0_ = but0c, but_0c + butt_margin +but_1c - GUI_A['include_duplis_on'] = Draw.Toggle('Include Duplis', EVENT_NONE, b0, y, b0_, 20, GUI_A['include_duplis_on'].val, "Export Duplicates (dupliverts, dupliframes, dupligroups) on/off") - #b0, b0_ = but2c, but_2c + butt_margin + but_3c - - - - y -= 30 - Draw.PushButton('EXIT', EVENT_EXIT, but0c, y, but_0c+bm, 20, '' ) - Draw.PushButton('HELP', EVENT_HELP, but1c, y, but_1c+bm, 20, 'goes to online-Manual on wiki.blender.org') - GUI_A['optimization'] = Draw.Number('', EVENT_NONE, but2c, y, 40, 20, GUI_A['optimization'].val, 0, 3, "Optimization Level: 0=Debug/Draw-in, 1=Verbose, 2=ProgressBar, 3=SilentMode") - GUI_A['outputDWG_on'] = Draw.Toggle('DWG*', EVENT_NONE, but2c, y+20, 40, 20, GUI_A['outputDWG_on'].val, "converts DXF to DWG (needs external converter) on/off") - - Draw.BeginAlign() - Draw.PushButton('START EXPORT', EVENT_START, but2c+40, y, but_2c-40+but_3c+butt_margin, 40, 'Start the export process. For Cancel go to console and hit Ctrl-C') - Draw.EndAlign() - - y -= 20 - #Draw.BeginAlign() - #Draw.Label(' ', but0c-menu_margin, y, menu_margin, 20) - #Draw.Label(LAB, but0c, y, menu_w, 20) - Draw.Label(LAB, 30, y, menu_w, 20) - #Draw.Label(' ', but0c+menu_w, y, menu_margin, 20) - #Draw.EndAlign() - - ui_scrollbarX(menu_orgX, menu_w+50, scrollXArea, c_fg, c_bg) - ui_scrollbarY(menu_orgY, menu_h+30, scrollYArea, c_fg, c_bg) - - - - -#-- END GUI Stuf----------------------------------------------------- - -c0=[0.2,0.2,0.2,0.0] -c1=[0.7,0.7,0.9,0.0] -c2=[0.71,0.71,0.71,0.0] -c3=[0.4,0.4,0.4,0.0] -c4=[0.95,0.95,0.9,0.0] -c5=[0.64,0.64,0.64,0] -c6=[0.75,0.75,0.75,0] -c7=[0.6,0.6,0.6,0] -c8=[1.0,0.0,0.0,0] -c9=[0.7,0.0,0.0,0] -c10=[0.64,0.81,0.81,0] -c11=[0.57,0.71,0.71,0] -c_nor= c5[:3] -c_act= c10[:3] -c_sel= c11[:3] -c_tx = c0[:3] -c_fg = c2[:3] -c_bg = c5[:3] - -def ui_rect(coords,color): - [X1,Y1,X2,Y2],[r,g,b] = coords,color - glColor3f(r,g,b) - glRecti(X1,Y1,X2,Y2) -def ui_rectA(coords,color): - [X1,Y1,X2,Y2],[r,g,b,a] = coords,color - glColor4f(r,g,b,a) - glRecti(X1,Y1,X2,Y2) #integer coords - #glRectf(X1,Y1,X2,Y2) #floating coords -def ui_line(coords,color): - [X1,Y1,X2,Y2],[r,g,b] = coords,color - glColor3f(r,g,b) - glBegin(GL_LINES) - glVertex2i(X1,Y1) - glVertex2i(X2,Y2) - glEnd() -def ui_panel(posX,posY,L,H,color): - [r,g,b] = color - ui_rect([posX+4,posY-4,posX+L+4,posY-H-4],[.55,.55,.55]) #1st shadow - ui_rect([posX+3,posY-3,posX+L+3,posY-H-3],[.45,.45,.45]) - ui_rect([posX+3,posY-3,posX+L+2,posY-H-2],[.30,.30,.30]) #2nd shadow - ui_rect([posX,posY-H,posX+L,posY],[r,g,b]) #Main - ui_rect([posX+3,posY-19,posX+L-3,posY-2],[.75*r,.75*g,.75*b]) #Titlebar - ui_line([posX+3,posY-19,posX+3,posY-2],[.25,.25,.25]) - ui_line([posX+4,posY-19,posX+4,posY-2],[(r+.75)/4,(g+.75)/4,(b+.75)/4]) - ui_line([posX+4,posY-2,posX+L-3,posY-2],[(r+.75)/4,(g+.75)/4,(b+.75)/4]) -def ui_box(x,y,xright,bottom): - color = [0.75, 0.75, 0.75] - coords = x+1,y+1,xright-1,bottom-1 - ui_rect(coords,color) - -def ui_scrollbarX(Focus,PanelH,Area, color_fg, color_bg): - # Area = ScrollBarArea - # point1=down/left, point2=top/right - P1X,P1Y,P2X,P2Y = Area - AreaH = P2X-P1X - if PanelH > AreaH: - Slider = int(AreaH * (AreaH / float(PanelH))) - if Slider<3: Slider = 3 #minimal slider heigh - posX = -int(AreaH * (Focus / float(PanelH))) - ui_rect([P1X,P1Y,P2X,P2Y], color_bg) - ui_rect([P1X+posX,P1Y+3,P1X+posX+Slider,P2Y-3], color_fg) - -def ui_scrollbarY(Focus,PanelH,Area, color_fg, color_bg): - # Area = ScrollBarArea - # point1=down/left, point2=top/right - P1X,P1Y,P2X,P2Y = Area - AreaH = P2Y-P1Y - if PanelH > AreaH: - Slider = int(AreaH * (AreaH / float(PanelH))) - if Slider<3: Slider = 3 #minimal slider heigh - posY = -int(AreaH * (Focus / float(PanelH))) - ui_rect([P1X,P1Y,P2X-1,P2Y], color_bg) - #ui_rect([P1X+3,P2Y-posY,P2X-4,P2Y-posY-Slider], color_fg) - ui_rect([P1X+3,P1Y+posY,P2X-4,P1Y+posY+Slider], color_fg) - - -#------------------------------------------------------------ -def dxf_callback(input_filename): - global dxfFileName - dxfFileName.val=input_filename -# dirname == Blender.sys.dirname(Blender.Get('filename')) -# update_RegistryKey('DirName', dirname) -# update_RegistryKey('dxfFileName', input_filename) - -def ini_callback(input_filename): - global iniFileName - iniFileName.val=input_filename - -#------------------------------------------------------------ -def getSpaceRect(): - __UI_RECT__ = Buffer(GL_FLOAT, 4) - glGetFloatv(GL_SCISSOR_BOX, __UI_RECT__) - __UI_RECT__ = __UI_RECT__.list - return (int(__UI_RECT__[0]), int(__UI_RECT__[1]), int(__UI_RECT__[2]), int(__UI_RECT__[3])) - -def getRelMousePos(mco, winRect): - # mco = Blender.Window.GetMouseCoords() - if pointInRect(mco, winRect): - return (mco[0] - winRect[0], mco[1] - winRect[1]) - return None - - -def pointInRect(pt, rect): - if rect[0] < pt[0] < rect[0]+rect[2] and\ - rect[1] < pt[1] < rect[1]+rect[3]: - return True - else: - return False - - - -#--- variables UI menu --------------------------- -mco = [0,0] # mouse coordinaten -mbX, mbY = 0,0 # mouse buffer coordinaten -scrollW = 20 # width of scrollbar -rowH = 20 # height of menu raw -menu__H = 2 * rowH +5 # height of menu bar -headerH = 1 * rowH # height of column header bar -scroll_left = True # position of scrollbar -menu_bottom = False # position of menu -edit_mode = False # indicator/activator -iconlib_mode = False # indicator/activator -icon_maps = [] #[['blenderbuttons.png',12,25,20,21], -#['referenceicons.png',12,25,20,21]] -help_text = False # indicator/activator -menu_pan = False # indicator/activator -compact_DESIGN = True # toggle UI -showLINK = True # toggle Links -filterList=[-1,-1,-1,-1,-1] -dubbleclik_delay = 0.25 - -PAN_X,PAN_Y = 0,0 # pan coordinates in characters -mPAN_X,mPAN_Y = 0,0 # manu pan coordinates in characters -menu_orgX = 0 -menu_orgY = 0 -mPAN_Xmax = 800 -mPAN_Ymax = 800 - - -#------------------------------------------------------------ -def event(evt, val): - global mbX, mbY, UP, UP0, scroll_pan, FOCUS_fix - global menu_bottom, scroll_left, mco - global PAN_X, PAN_Y, PAN_X0, PAN_Y0 - global mPAN_X, mPAN_Y, mPAN_X0, mPAN_Y0, menu_pan - - #if Blender.event: - # print 'Blender.event:%s, evt:%s' %(Blender.event, evt) #------------ - - if evt in (Draw.QKEY, Draw.ESCKEY) and not val: - print 'DXF-Exporter *** end ***' #--------------------- - Draw.Exit() - - elif val: - if evt==Draw.MIDDLEMOUSE: - mco2 = Window.GetMouseCoords() - relativeMouseCo = getRelMousePos(mco2, getSpaceRect()) - if relativeMouseCo != None: - #rect = [menu__X1,menu__Y1,menu__X2,menu__Y2] - if 1: #pointInRect(relativeMouseCo, menu__Area): - menu_pan = True - mPAN_X0 = mPAN_X - mPAN_Y0 = mPAN_Y - mco = mco2 - elif evt == Draw.MOUSEY or evt == Draw.MOUSEX: - if menu_pan: - mco2 = Window.GetMouseCoords() - mbX = mco2[0]-mco[0] - mbY = mco2[1]-mco[1] - mPAN_X = mPAN_X0 - mbX - mPAN_Y = mPAN_Y0 - mbY - #print mbX, mbY #-------------------- - Draw.Redraw() - elif evt == Draw.WHEELDOWNMOUSE: - mPAN_Y -= 80 - Draw.Redraw() - elif evt == Draw.WHEELUPMOUSE: - mPAN_Y += 80 - Draw.Redraw() - else: # = if val==False: - if evt==Draw.LEFTMOUSE: - scroll_pan = False - elif evt==Draw.MIDDLEMOUSE: - menu_pan = False - -def bevent(evt): - global config_UI, user_preset - global CAMERA, GUI_A - - ######### Manages GUI events - if (evt==EVENT_EXIT): - Draw.Exit() - print 'DXF-Exporter *** end ***' #--------------------- - elif (evt==EVENT_CHOOSE_INI): - Window.FileSelector(ini_callback, "INI-file Selection", '*.ini') - elif (evt==EVENT_REDRAW): - Draw.Redraw() - elif (evt==EVENT_RESET): - resetDefaultConfig() - Draw.Redraw() - elif (evt==EVENT_PRESET2D): - resetDefaultConfig_2D() - Draw.Redraw() - elif (evt==EVENT_PRESET3D): - resetDefaultConfig_3D() - Draw.Redraw() - elif evt in (EVENT_CAMERA,EVENT_LIGHT): - CAMERA = GUI_A['camera_selected'].val - if CAMERA==len(CAMERAS)+1: - doAllCameras = True - else: - pass #print 'deb: CAMERAS=',CAMERAS #---------------- - Draw.Redraw() - elif (evt==EVENT_setCAMERA): - if CAMERA<len(CAMERAS)+1: - gotoCAMERA() - - elif (evt==EVENT_SCALE): - if g_scale_as.val == 12: - inputGlobalScale() - if GUI_A['g_scale'].val < 0.00000001: - GUI_A['g_scale'].val = 0.00000001 - Draw.Redraw() - elif (evt==EVENT_ORIGIN): - inputOriginVector() - Draw.Redraw() - elif (evt==EVENT_PRESETPLINE): - presetConfig_polyline(GUI_A['to_polyline_on'].val) - Draw.Redraw() - elif (evt==EVENT_PRESETS): - user_preset += 1 - index = str(user_preset) - if user_preset > 5: user_preset = 0; index = '' - iniFileName.val = INIFILE_DEFAULT_NAME + index + INIFILE_EXTENSION - Draw.Redraw() - elif (evt==EVENT_HELP): - try: - import webbrowser - webbrowser.open('http://wiki.blender.org/index.php?title=Scripts/Manual/Export/autodesk_dxf') - except: - Draw.PupMenu('DXF-Exporter: HELP Alert!%t|no connection to manual-page on Blender-Wiki! try:|\ -http://wiki.blender.org/index.php?title=Scripts/Manual/Export/autodesk_dxf') - Draw.Redraw() - elif (evt==EVENT_LOAD_INI): - loadConfig() - Draw.Redraw() - elif (evt==EVENT_SAVE_INI): - saveConfig() - Draw.Redraw() - elif (evt==EVENT_DXF_DIR): - dxfFile = dxfFileName.val - dxfPathName = '' - if '/' in dxfFile: - dxfPathName = '/'.join(dxfFile.split('/')[:-1]) + '/' - elif '\\' in dxfFile: - dxfPathName = '\\'.join(dxfFile.split('\\')[:-1]) + '\\' - dxfFileName.val = dxfPathName + '*.dxf' -# dirname == Blender.sys.dirname(Blender.Get('filename')) -# update_RegistryKey('DirName', dirname) -# update_RegistryKey('dxfFileName', dxfFileName.val) - GUI_A['only_selected_on'].val = 1 - Draw.Redraw() - elif (evt==EVENT_CHOOSE_DXF): - filename = '' # '*.dxf' - if dxfFileName.val: filename = dxfFileName.val - Window.FileSelector(dxf_callback, "DXF-file Selection", filename) - elif (evt==EVENT_START): - dxfFile = dxfFileName.val - #print 'deb: dxfFile file: ', dxfFile #---------------------- - if E_M: dxfFileName.val, dxfFile = e_mode(dxfFile) #evaluation mode - update_RegistryKey('dxfFileName', dxfFileName.val) - update_globals() - if dxfFile.lower().endswith('*.dxf'): - if Draw.PupMenu('DXF-Exporter: OK?|will write multiple DXF-files, one for each Scene, in:|%s' % dxfFile) == 1: - global UI_MODE - UI_MODE = False - #TODO: multi_export(dxfFile[:-5]) # cut last 5 characters '*.dxf' - Draw.Redraw() - UI_MODE = True - else: - Draw.Redraw() - elif dxfFile.lower()[-4:] in ('.dxf','.dwg'): # and Blender.sys.exists(dxfFile): - print 'preparing for export ---' #Standard Mode: activated - filepath = dxfFile - sce = Scene.GetCurrent() - if ONLYSELECTED: sel_group = sce.objects.selected - else: sel_group = sce.objects - - if ONLYVISIBLE: - sel_group_temp = [] - layerlist = sce.getLayers() - for ob in sel_group: - for lay in ob.layers: - if lay in layerlist: - sel_group_temp.append(ob) - break - sel_group = sel_group_temp - - export_list = getObjectsAndDuplis(sel_group,MATRICES=True) - - if export_list: do_export(export_list, filepath) - else: - print "Abort: selection was empty, no object to export!" - Draw.PupMenu('DXF Exporter: nothing exported!|empty selection!') - else: - Draw.PupMenu('DXF-Exporter: Alert!%t|no valid DXF-file selected!') - print "DXF-Exporter: error, no valid DXF-file selected! try again" - Draw.Redraw() - - - - -def multi_export(DIR): #TODO: - """Imports all DXF-files from directory DIR. - - """ - global SCENE - batchTIME = Blender.sys.time() - #if #DIR == "": DIR = os.path.curdir - if DIR == "": DIR = Blender.sys.dirname(Blender.Get('filename')) - print 'Multifiles Import from %s' %DIR - files = \ - [Blender.sys.join(DIR, f) for f in os.listdir(DIR) if f.lower().endswith('.dxf')] - if not files: - print '...None DXF-files found. Abort!' - return - - i = 0 - for dxfFile in files: - i += 1 - print '\nDXF-file', i, 'of', len(files) #,'\nImporting', dxfFile - if ONLYSELECTED: - _dxf_file = dxfFile.split('/')[-1].split('\\')[-1] - _dxf_file = _dxf_file[:-4] # cut last char:'.dxf' - _dxf_file = _dxf_file[:NAMELENGTH_MAX] #? [-NAMELENGTH_MAX:]) - SCENE = Blender.Scene.New(_dxf_file) - SCENE.makeCurrent() - #or so? Blender.Scene.makeCurrent(_dxf_file) - #sce = bpy.data.scenes.new(_dxf_file) - #bpy.data.scenes.active = sce - else: - SCENE = Blender.Scene.GetCurrent() - SCENE.objects.selected = [] # deselect all - main(dxfFile) - #Blender.Redraw() - - print 'TOTAL TIME: %.6f' % (Blender.sys.time() - batchTIME) - print '\a\r', # beep when done - - -#----------------------------------------------------- -if __name__=='__main__': - - if DXF: - print '\n\n\n' - print 'DXF-Exporter v%s *** start ***' %(__version__) #--------------------- - print 'with Library %s' %(DXF.__version__) #--------------------- - if not DXF.copy: - print "DXF-Exporter: dxfLibrary.py script requires a full Python install" - Draw.PupMenu('Error%t|The dxfLibrary.py script requires a full Python install') - else: - #Window.FileSelector(dxf_export_ui, 'EXPORT DXF', Blender.sys.makename(ext='.dxf')) - # recall last used DXF-file and INI-file names - dxffilename = check_RegistryKey('dxfFileName') - #print 'deb:start dxffilename:', dxffilename #---------------- - if dxffilename: dxfFileName.val = dxffilename - else: - dirname = Blender.sys.dirname(Blender.Get('filename')) - #print 'deb:start dirname:', dirname #---------------- - dxfFileName.val = Blender.sys.join(dirname, '') - inifilename = check_RegistryKey('iniFileName') - if inifilename: iniFileName.val = inifilename - - updateMenuCAMERA() - updateCAMERA() - - Draw.Register(draw_UI, event, bevent) - -
\ No newline at end of file diff --git a/release/scripts/export_fbx.py b/release/scripts/export_fbx.py deleted file mode 100644 index 50357cbfa75..00000000000 --- a/release/scripts/export_fbx.py +++ /dev/null @@ -1,3084 +0,0 @@ -#!BPY -""" -Name: 'Autodesk FBX (.fbx)...' -Blender: 249 -Group: 'Export' -Tooltip: 'Selection to an ASCII Autodesk FBX ' -""" -__author__ = "Campbell Barton" -__url__ = ['www.blender.org', 'blenderartists.org'] -__version__ = "1.2" - -__bpydoc__ = """\ -This script is an exporter to the FBX file format. - -http://wiki.blender.org/index.php/Scripts/Manual/Export/autodesk_fbx -""" -# -------------------------------------------------------------------------- -# FBX Export v0.1 by Campbell Barton (AKA Ideasman) -# -------------------------------------------------------------------------- -# ***** 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 ***** -# -------------------------------------------------------------------------- - -try: - import time - # import os # only needed for batch export, nbot used yet -except: - time = None # use this to check if they have python modules installed - -# for python 2.3 support -try: - set() -except: - try: - from sets import Set as set - except: - set = None # so it complains you dont have a ! - -# os is only needed for batch 'own dir' option -try: - import os -except: - os = None - -import Blender -import bpy -from Blender.Mathutils import Matrix, Vector, RotationMatrix - -import BPyObject -import BPyMesh -import BPySys -import BPyMessages - -## This was used to make V, but faster not to do all that -##valid = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_,.()[]{}' -##v = range(255) -##for c in valid: v.remove(ord(c)) -v = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,42,43,47,58,59,60,61,62,63,64,92,94,96,124,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254] -invalid = ''.join([chr(i) for i in v]) -def cleanName(name): - for ch in invalid: name = name.replace(ch, '_') - return name -del v, i - - -def copy_file(source, dest): - file = open(source, 'rb') - data = file.read() - file.close() - - file = open(dest, 'wb') - file.write(data) - file.close() - - -def copy_images(dest_dir, textures): - if not dest_dir.endswith(Blender.sys.sep): - dest_dir += Blender.sys.sep - - image_paths = set() - for tex in textures: - image_paths.add(Blender.sys.expandpath(tex.filename)) - - # Now copy images - copyCount = 0 - for image_path in image_paths: - if Blender.sys.exists(image_path): - # Make a name for the target path. - dest_image_path = dest_dir + image_path.split('\\')[-1].split('/')[-1] - if not Blender.sys.exists(dest_image_path): # Image isnt alredy there - print '\tCopying "%s" > "%s"' % (image_path, dest_image_path) - try: - copy_file(image_path, dest_image_path) - copyCount+=1 - except: - print '\t\tWarning, file failed to copy, skipping.' - - print '\tCopied %d images' % copyCount - -mtx4_identity = Matrix() - -# testing -mtx_x90 = RotationMatrix( 90, 3, 'x') # used -#mtx_x90n = RotationMatrix(-90, 3, 'x') -#mtx_y90 = RotationMatrix( 90, 3, 'y') -#mtx_y90n = RotationMatrix(-90, 3, 'y') -#mtx_z90 = RotationMatrix( 90, 3, 'z') -#mtx_z90n = RotationMatrix(-90, 3, 'z') - -#mtx4_x90 = RotationMatrix( 90, 4, 'x') -mtx4_x90n = RotationMatrix(-90, 4, 'x') # used -#mtx4_y90 = RotationMatrix( 90, 4, 'y') -mtx4_y90n = RotationMatrix(-90, 4, 'y') # used -mtx4_z90 = RotationMatrix( 90, 4, 'z') # used -mtx4_z90n = RotationMatrix(-90, 4, 'z') # used - -def strip_path(p): - return p.split('\\')[-1].split('/')[-1] - -# Used to add the scene name into the filename without using odd chars -sane_name_mapping_ob = {} -sane_name_mapping_mat = {} -sane_name_mapping_tex = {} -sane_name_mapping_take = {} -sane_name_mapping_group = {} - -# Make sure reserved names are not used -sane_name_mapping_ob['Scene'] = 'Scene_' -sane_name_mapping_ob['blend_root'] = 'blend_root_' - -def increment_string(t): - name = t - num = '' - while name and name[-1].isdigit(): - num = name[-1] + num - name = name[:-1] - if num: return '%s%d' % (name, int(num)+1) - else: return name + '_0' - - - -# todo - Disallow the name 'Scene' and 'blend_root' - it will bugger things up. -def sane_name(data, dct): - #if not data: return None - - if type(data)==tuple: # materials are paired up with images - data, other = data - use_other = True - else: - other = None - use_other = False - - if data: name = data.name - else: name = None - orig_name = name - - if other: - orig_name_other = other.name - name = '%s #%s' % (name, orig_name_other) - else: - orig_name_other = None - - # dont cache, only ever call once for each data type now, - # so as to avoid namespace collision between types - like with objects <-> bones - #try: return dct[name] - #except: pass - - if not name: - name = 'unnamed' # blank string, ASKING FOR TROUBLE! - else: - #name = BPySys.cleanName(name) - name = cleanName(name) # use our own - - while name in dct.itervalues(): name = increment_string(name) - - if use_other: # even if other is None - orig_name_other will be a string or None - dct[orig_name, orig_name_other] = name - else: - dct[orig_name] = name - - return name - -def sane_obname(data): return sane_name(data, sane_name_mapping_ob) -def sane_matname(data): return sane_name(data, sane_name_mapping_mat) -def sane_texname(data): return sane_name(data, sane_name_mapping_tex) -def sane_takename(data): return sane_name(data, sane_name_mapping_take) -def sane_groupname(data): return sane_name(data, sane_name_mapping_group) - -def derived_paths(fname_orig, basepath, FORCE_CWD=False): - ''' - fname_orig - blender path, can be relative - basepath - fname_rel will be relative to this - FORCE_CWD - dont use the basepath, just add a ./ to the filename. - use when we know the file will be in the basepath. - ''' - fname = Blender.sys.expandpath(fname_orig) - fname_strip = strip_path(fname) - if FORCE_CWD: fname_rel = '.' + Blender.sys.sep + fname_strip - else: fname_rel = Blender.sys.relpath(fname, basepath) - if fname_rel.startswith('//'): fname_rel = '.' + Blender.sys.sep + fname_rel[2:] - return fname, fname_strip, fname_rel - - -def mat4x4str(mat): - return '%.15f,%.15f,%.15f,%.15f,%.15f,%.15f,%.15f,%.15f,%.15f,%.15f,%.15f,%.15f,%.15f,%.15f,%.15f,%.15f' % tuple([ f for v in mat for f in v ]) - -def meshNormalizedWeights(me): - try: # account for old bad BPyMesh - groupNames, vWeightList = BPyMesh.meshWeight2List(me) - except: - return [],[] - - if not groupNames: - return [],[] - - for i, vWeights in enumerate(vWeightList): - tot = 0.0 - for w in vWeights: - tot+=w - - if tot: - for j, w in enumerate(vWeights): - vWeights[j] = w/tot - - return groupNames, vWeightList - -header_comment = \ -'''; FBX 6.1.0 project file -; Created by Blender FBX Exporter -; for support mail: ideasman42@gmail.com -; ---------------------------------------------------- - -''' - -# This func can be called with just the filename -def write(filename, batch_objects = None, \ - EXP_OBS_SELECTED = True, - EXP_MESH = True, - EXP_MESH_APPLY_MOD = True, - EXP_MESH_HQ_NORMALS = False, - EXP_ARMATURE = True, - EXP_LAMP = True, - EXP_CAMERA = True, - EXP_EMPTY = True, - EXP_IMAGE_COPY = False, - GLOBAL_MATRIX = Matrix(), - ANIM_ENABLE = True, - ANIM_OPTIMIZE = True, - ANIM_OPTIMIZE_PRECISSION = 6, - ANIM_ACTION_ALL = False, - BATCH_ENABLE = False, - BATCH_GROUP = True, - BATCH_SCENE = False, - BATCH_FILE_PREFIX = '', - BATCH_OWN_DIR = False - ): - - # ----------------- Batch support! - if BATCH_ENABLE: - if os == None: BATCH_OWN_DIR = False - - fbxpath = filename - - # get the path component of filename - tmp_exists = Blender.sys.exists(fbxpath) - - if tmp_exists != 2: # a file, we want a path - while fbxpath and fbxpath[-1] not in ('/', '\\'): - fbxpath = fbxpath[:-1] - if not filename: - Draw.PupMenu('Error%t|Directory does not exist!') - return - - tmp_exists = Blender.sys.exists(fbxpath) - - if tmp_exists != 2: - Draw.PupMenu('Error%t|Directory does not exist!') - return - - if not fbxpath.endswith(Blender.sys.sep): - fbxpath += Blender.sys.sep - del tmp_exists - - - if BATCH_GROUP: - data_seq = bpy.data.groups - else: - data_seq = bpy.data.scenes - - # call this function within a loop with BATCH_ENABLE == False - orig_sce = bpy.data.scenes.active - - - new_fbxpath = fbxpath # own dir option modifies, we need to keep an original - for data in data_seq: # scene or group - newname = BATCH_FILE_PREFIX + BPySys.cleanName(data.name) - - - if BATCH_OWN_DIR: - new_fbxpath = fbxpath + newname + Blender.sys.sep - # path may alredy exist - # TODO - might exist but be a file. unlikely but should probably account for it. - - if Blender.sys.exists(new_fbxpath) == 0: - os.mkdir(new_fbxpath) - - - filename = new_fbxpath + newname + '.fbx' - - print '\nBatch exporting %s as...\n\t"%s"' % (data, filename) - - if BATCH_GROUP: #group - # group, so objects update properly, add a dummy scene. - sce = bpy.data.scenes.new() - sce.Layers = (1<<20) -1 - bpy.data.scenes.active = sce - for ob_base in data.objects: - sce.objects.link(ob_base) - - sce.update(1) - - # TODO - BUMMER! Armatures not in the group wont animate the mesh - - else:# scene - - - data_seq.active = data - - - # Call self with modified args - # Dont pass batch options since we alredy usedt them - write(filename, data.objects, - False, - EXP_MESH, - EXP_MESH_APPLY_MOD, - EXP_MESH_HQ_NORMALS, - EXP_ARMATURE, - EXP_LAMP, - EXP_CAMERA, - EXP_EMPTY, - EXP_IMAGE_COPY, - GLOBAL_MATRIX, - ANIM_ENABLE, - ANIM_OPTIMIZE, - ANIM_OPTIMIZE_PRECISSION, - ANIM_ACTION_ALL - ) - - if BATCH_GROUP: - # remove temp group scene - bpy.data.scenes.unlink(sce) - - bpy.data.scenes.active = orig_sce - - return # so the script wont run after we have batch exported. - - # end batch support - - # Use this for working out paths relative to the export location - basepath = Blender.sys.dirname(filename) - - # ---------------------------------------------- - # storage classes - class my_bone_class: - __slots__ =(\ - 'blenName',\ - 'blenBone',\ - 'blenMeshes',\ - 'restMatrix',\ - 'parent',\ - 'blenName',\ - 'fbxName',\ - 'fbxArm',\ - '__pose_bone',\ - '__anim_poselist') - - def __init__(self, blenBone, fbxArm): - - # This is so 2 armatures dont have naming conflicts since FBX bones use object namespace - self.fbxName = sane_obname(blenBone) - - self.blenName = blenBone.name - self.blenBone = blenBone - self.blenMeshes = {} # fbxMeshObName : mesh - self.fbxArm = fbxArm - self.restMatrix = blenBone.matrix['ARMATURESPACE'] - - # not used yet - # self.restMatrixInv = self.restMatrix.copy().invert() - # self.restMatrixLocal = None # set later, need parent matrix - - self.parent = None - - # not public - pose = fbxArm.blenObject.getPose() - self.__pose_bone = pose.bones[self.blenName] - - # store a list if matricies here, (poseMatrix, head, tail) - # {frame:posematrix, frame:posematrix, ...} - self.__anim_poselist = {} - - ''' - def calcRestMatrixLocal(self): - if self.parent: - self.restMatrixLocal = self.restMatrix * self.parent.restMatrix.copy().invert() - else: - self.restMatrixLocal = self.restMatrix.copy() - ''' - def setPoseFrame(self, f): - # cache pose info here, frame must be set beforehand - - # Didnt end up needing head or tail, if we do - here it is. - ''' - self.__anim_poselist[f] = (\ - self.__pose_bone.poseMatrix.copy(),\ - self.__pose_bone.head.copy(),\ - self.__pose_bone.tail.copy() ) - ''' - - self.__anim_poselist[f] = self.__pose_bone.poseMatrix.copy() - - # get pose from frame. - def getPoseMatrix(self, f):# ---------------------------------------------- - return self.__anim_poselist[f] - ''' - def getPoseHead(self, f): - #return self.__pose_bone.head.copy() - return self.__anim_poselist[f][1].copy() - def getPoseTail(self, f): - #return self.__pose_bone.tail.copy() - return self.__anim_poselist[f][2].copy() - ''' - # end - - def getAnimParRelMatrix(self, frame): - #arm_mat = self.fbxArm.matrixWorld - #arm_mat = self.fbxArm.parRelMatrix() - if not self.parent: - #return mtx4_z90 * (self.getPoseMatrix(frame) * arm_mat) # dont apply arm matrix anymore - return mtx4_z90 * self.getPoseMatrix(frame) - else: - #return (mtx4_z90 * ((self.getPoseMatrix(frame) * arm_mat))) * (mtx4_z90 * (self.parent.getPoseMatrix(frame) * arm_mat)).invert() - return (mtx4_z90 * (self.getPoseMatrix(frame))) * (mtx4_z90 * self.parent.getPoseMatrix(frame)).invert() - - # we need thes because cameras and lights modified rotations - def getAnimParRelMatrixRot(self, frame): - return self.getAnimParRelMatrix(frame) - - def flushAnimData(self): - self.__anim_poselist.clear() - - - class my_object_generic: - # Other settings can be applied for each type - mesh, armature etc. - def __init__(self, ob, matrixWorld = None): - self.fbxName = sane_obname(ob) - self.blenObject = ob - self.fbxGroupNames = [] - self.fbxParent = None # set later on IF the parent is in the selection. - if matrixWorld: self.matrixWorld = matrixWorld * GLOBAL_MATRIX - else: self.matrixWorld = ob.matrixWorld * GLOBAL_MATRIX - self.__anim_poselist = {} # we should only access this - - def parRelMatrix(self): - if self.fbxParent: - return self.matrixWorld * self.fbxParent.matrixWorld.copy().invert() - else: - return self.matrixWorld - - def setPoseFrame(self, f): - self.__anim_poselist[f] = self.blenObject.matrixWorld.copy() - - def getAnimParRelMatrix(self, frame): - if self.fbxParent: - #return (self.__anim_poselist[frame] * self.fbxParent.__anim_poselist[frame].copy().invert() ) * GLOBAL_MATRIX - return (self.__anim_poselist[frame] * GLOBAL_MATRIX) * (self.fbxParent.__anim_poselist[frame] * GLOBAL_MATRIX).invert() - else: - return self.__anim_poselist[frame] * GLOBAL_MATRIX - - def getAnimParRelMatrixRot(self, frame): - type = self.blenObject.type - if self.fbxParent: - matrix_rot = (((self.__anim_poselist[frame] * GLOBAL_MATRIX) * (self.fbxParent.__anim_poselist[frame] * GLOBAL_MATRIX).invert())).rotationPart() - else: - matrix_rot = (self.__anim_poselist[frame] * GLOBAL_MATRIX).rotationPart() - - # Lamps need to be rotated - if type =='Lamp': - matrix_rot = mtx_x90 * matrix_rot - elif ob and type =='Camera': - y = Vector(0,1,0) * matrix_rot - matrix_rot = matrix_rot * RotationMatrix(90, 3, 'r', y) - - return matrix_rot - - # ---------------------------------------------- - - - - - - print '\nFBX export starting...', filename - start_time = Blender.sys.time() - try: - file = open(filename, 'w') - except: - return False - - sce = bpy.data.scenes.active - world = sce.world - - - # ---------------------------- Write the header first - file.write(header_comment) - if time: - curtime = time.localtime()[0:6] - else: - curtime = (0,0,0,0,0,0) - # - file.write(\ -'''FBXHeaderExtension: { - FBXHeaderVersion: 1003 - FBXVersion: 6100 - CreationTimeStamp: { - Version: 1000 - Year: %.4i - Month: %.2i - Day: %.2i - Hour: %.2i - Minute: %.2i - Second: %.2i - Millisecond: 0 - } - Creator: "FBX SDK/FBX Plugins build 20070228" - OtherFlags: { - FlagPLE: 0 - } -}''' % (curtime)) - - file.write('\nCreationTime: "%.4i-%.2i-%.2i %.2i:%.2i:%.2i:000"' % curtime) - file.write('\nCreator: "Blender3D version %.2f"' % Blender.Get('version')) - - pose_items = [] # list of (fbxName, matrix) to write pose data for, easier to collect allong the way - - # --------------- funcs for exporting - def object_tx(ob, loc, matrix, matrix_mod = None): - ''' - Matrix mod is so armature objects can modify their bone matricies - ''' - if isinstance(ob, Blender.Types.BoneType): - - # we know we have a matrix - # matrix = mtx4_z90 * (ob.matrix['ARMATURESPACE'] * matrix_mod) - matrix = mtx4_z90 * ob.matrix['ARMATURESPACE'] # dont apply armature matrix anymore - - parent = ob.parent - if parent: - #par_matrix = mtx4_z90 * (parent.matrix['ARMATURESPACE'] * matrix_mod) - par_matrix = mtx4_z90 * parent.matrix['ARMATURESPACE'] # dont apply armature matrix anymore - matrix = matrix * par_matrix.copy().invert() - - matrix_rot = matrix.rotationPart() - - loc = tuple(matrix.translationPart()) - scale = tuple(matrix.scalePart()) - rot = tuple(matrix_rot.toEuler()) - - else: - # This is bad because we need the parent relative matrix from the fbx parent (if we have one), dont use anymore - #if ob and not matrix: matrix = ob.matrixWorld * GLOBAL_MATRIX - if ob and not matrix: raise "error: this should never happen!" - - matrix_rot = matrix - #if matrix: - # matrix = matrix_scale * matrix - - if matrix: - loc = tuple(matrix.translationPart()) - scale = tuple(matrix.scalePart()) - - matrix_rot = matrix.rotationPart() - # Lamps need to be rotated - if ob and ob.type =='Lamp': - matrix_rot = mtx_x90 * matrix_rot - rot = tuple(matrix_rot.toEuler()) - elif ob and ob.type =='Camera': - y = Vector(0,1,0) * matrix_rot - matrix_rot = matrix_rot * RotationMatrix(90, 3, 'r', y) - rot = tuple(matrix_rot.toEuler()) - else: - rot = tuple(matrix_rot.toEuler()) - else: - if not loc: - loc = 0,0,0 - scale = 1,1,1 - rot = 0,0,0 - - return loc, rot, scale, matrix, matrix_rot - - def write_object_tx(ob, loc, matrix, matrix_mod= None): - ''' - We have loc to set the location if non blender objects that have a location - - matrix_mod is only used for bones at the moment - ''' - loc, rot, scale, matrix, matrix_rot = object_tx(ob, loc, matrix, matrix_mod) - - file.write('\n\t\t\tProperty: "Lcl Translation", "Lcl Translation", "A+",%.15f,%.15f,%.15f' % loc) - file.write('\n\t\t\tProperty: "Lcl Rotation", "Lcl Rotation", "A+",%.15f,%.15f,%.15f' % rot) - file.write('\n\t\t\tProperty: "Lcl Scaling", "Lcl Scaling", "A+",%.15f,%.15f,%.15f' % scale) - return loc, rot, scale, matrix, matrix_rot - - def write_object_props(ob=None, loc=None, matrix=None, matrix_mod=None): - # if the type is 0 its an empty otherwise its a mesh - # only difference at the moment is one has a color - file.write(''' - Properties60: { - Property: "QuaternionInterpolate", "bool", "",0 - Property: "Visibility", "Visibility", "A+",1''') - - loc, rot, scale, matrix, matrix_rot = write_object_tx(ob, loc, matrix, matrix_mod) - - # Rotation order, note, for FBX files Iv loaded normal order is 1 - # setting to zero. - # eEULER_XYZ = 0 - # eEULER_XZY - # eEULER_YZX - # eEULER_YXZ - # eEULER_ZXY - # eEULER_ZYX - - file.write(''' - Property: "RotationOffset", "Vector3D", "",0,0,0 - Property: "RotationPivot", "Vector3D", "",0,0,0 - Property: "ScalingOffset", "Vector3D", "",0,0,0 - Property: "ScalingPivot", "Vector3D", "",0,0,0 - Property: "TranslationActive", "bool", "",0 - Property: "TranslationMin", "Vector3D", "",0,0,0 - Property: "TranslationMax", "Vector3D", "",0,0,0 - Property: "TranslationMinX", "bool", "",0 - Property: "TranslationMinY", "bool", "",0 - Property: "TranslationMinZ", "bool", "",0 - Property: "TranslationMaxX", "bool", "",0 - Property: "TranslationMaxY", "bool", "",0 - Property: "TranslationMaxZ", "bool", "",0 - Property: "RotationOrder", "enum", "",0 - Property: "RotationSpaceForLimitOnly", "bool", "",0 - Property: "AxisLen", "double", "",10 - Property: "PreRotation", "Vector3D", "",0,0,0 - Property: "PostRotation", "Vector3D", "",0,0,0 - Property: "RotationActive", "bool", "",0 - Property: "RotationMin", "Vector3D", "",0,0,0 - Property: "RotationMax", "Vector3D", "",0,0,0 - Property: "RotationMinX", "bool", "",0 - Property: "RotationMinY", "bool", "",0 - Property: "RotationMinZ", "bool", "",0 - Property: "RotationMaxX", "bool", "",0 - Property: "RotationMaxY", "bool", "",0 - Property: "RotationMaxZ", "bool", "",0 - Property: "RotationStiffnessX", "double", "",0 - Property: "RotationStiffnessY", "double", "",0 - Property: "RotationStiffnessZ", "double", "",0 - Property: "MinDampRangeX", "double", "",0 - Property: "MinDampRangeY", "double", "",0 - Property: "MinDampRangeZ", "double", "",0 - Property: "MaxDampRangeX", "double", "",0 - Property: "MaxDampRangeY", "double", "",0 - Property: "MaxDampRangeZ", "double", "",0 - Property: "MinDampStrengthX", "double", "",0 - Property: "MinDampStrengthY", "double", "",0 - Property: "MinDampStrengthZ", "double", "",0 - Property: "MaxDampStrengthX", "double", "",0 - Property: "MaxDampStrengthY", "double", "",0 - Property: "MaxDampStrengthZ", "double", "",0 - Property: "PreferedAngleX", "double", "",0 - Property: "PreferedAngleY", "double", "",0 - Property: "PreferedAngleZ", "double", "",0 - Property: "InheritType", "enum", "",0 - Property: "ScalingActive", "bool", "",0 - Property: "ScalingMin", "Vector3D", "",1,1,1 - Property: "ScalingMax", "Vector3D", "",1,1,1 - Property: "ScalingMinX", "bool", "",0 - Property: "ScalingMinY", "bool", "",0 - Property: "ScalingMinZ", "bool", "",0 - Property: "ScalingMaxX", "bool", "",0 - Property: "ScalingMaxY", "bool", "",0 - Property: "ScalingMaxZ", "bool", "",0 - Property: "GeometricTranslation", "Vector3D", "",0,0,0 - Property: "GeometricRotation", "Vector3D", "",0,0,0 - Property: "GeometricScaling", "Vector3D", "",1,1,1 - Property: "LookAtProperty", "object", "" - Property: "UpVectorProperty", "object", "" - Property: "Show", "bool", "",1 - Property: "NegativePercentShapeSupport", "bool", "",1 - Property: "DefaultAttributeIndex", "int", "",0''') - if ob and type(ob) != Blender.Types.BoneType: - # Only mesh objects have color - file.write('\n\t\t\tProperty: "Color", "Color", "A",0.8,0.8,0.8') - file.write('\n\t\t\tProperty: "Size", "double", "",100') - file.write('\n\t\t\tProperty: "Look", "enum", "",1') - - return loc, rot, scale, matrix, matrix_rot - - - # -------------------------------------------- Armatures - #def write_bone(bone, name, matrix_mod): - def write_bone(my_bone): - file.write('\n\tModel: "Model::%s", "Limb" {' % my_bone.fbxName) - file.write('\n\t\tVersion: 232') - - #poseMatrix = write_object_props(my_bone.blenBone, None, None, my_bone.fbxArm.parRelMatrix())[3] - poseMatrix = write_object_props(my_bone.blenBone)[3] # dont apply bone matricies anymore - pose_items.append( (my_bone.fbxName, poseMatrix) ) - - - # file.write('\n\t\t\tProperty: "Size", "double", "",%.6f' % ((my_bone.blenData.head['ARMATURESPACE'] - my_bone.blenData.tail['ARMATURESPACE']) * my_bone.fbxArm.parRelMatrix()).length) - file.write('\n\t\t\tProperty: "Size", "double", "",1') - - #((my_bone.blenData.head['ARMATURESPACE'] * my_bone.fbxArm.matrixWorld) - (my_bone.blenData.tail['ARMATURESPACE'] * my_bone.fbxArm.parRelMatrix())).length) - - """ - file.write('\n\t\t\tProperty: "LimbLength", "double", "",%.6f' %\ - ((my_bone.blenBone.head['ARMATURESPACE'] - my_bone.blenBone.tail['ARMATURESPACE']) * my_bone.fbxArm.parRelMatrix()).length) - """ - - file.write('\n\t\t\tProperty: "LimbLength", "double", "",%.6f' %\ - (my_bone.blenBone.head['ARMATURESPACE'] - my_bone.blenBone.tail['ARMATURESPACE']).length) - - #file.write('\n\t\t\tProperty: "LimbLength", "double", "",1') - file.write('\n\t\t\tProperty: "Color", "ColorRGB", "",0.8,0.8,0.8') - file.write('\n\t\t\tProperty: "Color", "Color", "A",0.8,0.8,0.8') - file.write('\n\t\t}') - file.write('\n\t\tMultiLayer: 0') - file.write('\n\t\tMultiTake: 1') - file.write('\n\t\tShading: Y') - file.write('\n\t\tCulling: "CullingOff"') - file.write('\n\t\tTypeFlags: "Skeleton"') - file.write('\n\t}') - - def write_camera_switch(): - file.write(''' - Model: "Model::Camera Switcher", "CameraSwitcher" { - Version: 232''') - - write_object_props() - file.write(''' - Property: "Color", "Color", "A",0.8,0.8,0.8 - Property: "Camera Index", "Integer", "A+",100 - } - MultiLayer: 0 - MultiTake: 1 - Hidden: "True" - Shading: W - Culling: "CullingOff" - Version: 101 - Name: "Model::Camera Switcher" - CameraId: 0 - CameraName: 100 - CameraIndexName: - }''') - - def write_camera_dummy(name, loc, near, far, proj_type, up): - file.write('\n\tModel: "Model::%s", "Camera" {' % name ) - file.write('\n\t\tVersion: 232') - write_object_props(None, loc) - - file.write('\n\t\t\tProperty: "Color", "Color", "A",0.8,0.8,0.8') - file.write('\n\t\t\tProperty: "Roll", "Roll", "A+",0') - file.write('\n\t\t\tProperty: "FieldOfView", "FieldOfView", "A+",40') - file.write('\n\t\t\tProperty: "FieldOfViewX", "FieldOfView", "A+",1') - file.write('\n\t\t\tProperty: "FieldOfViewY", "FieldOfView", "A+",1') - file.write('\n\t\t\tProperty: "OpticalCenterX", "Real", "A+",0') - file.write('\n\t\t\tProperty: "OpticalCenterY", "Real", "A+",0') - file.write('\n\t\t\tProperty: "BackgroundColor", "Color", "A+",0.63,0.63,0.63') - file.write('\n\t\t\tProperty: "TurnTable", "Real", "A+",0') - file.write('\n\t\t\tProperty: "DisplayTurnTableIcon", "bool", "",1') - file.write('\n\t\t\tProperty: "Motion Blur Intensity", "Real", "A+",1') - file.write('\n\t\t\tProperty: "UseMotionBlur", "bool", "",0') - file.write('\n\t\t\tProperty: "UseRealTimeMotionBlur", "bool", "",1') - file.write('\n\t\t\tProperty: "ResolutionMode", "enum", "",0') - file.write('\n\t\t\tProperty: "ApertureMode", "enum", "",2') - file.write('\n\t\t\tProperty: "GateFit", "enum", "",0') - file.write('\n\t\t\tProperty: "FocalLength", "Real", "A+",21.3544940948486') - file.write('\n\t\t\tProperty: "CameraFormat", "enum", "",0') - file.write('\n\t\t\tProperty: "AspectW", "double", "",320') - file.write('\n\t\t\tProperty: "AspectH", "double", "",200') - file.write('\n\t\t\tProperty: "PixelAspectRatio", "double", "",1') - file.write('\n\t\t\tProperty: "UseFrameColor", "bool", "",0') - file.write('\n\t\t\tProperty: "FrameColor", "ColorRGB", "",0.3,0.3,0.3') - file.write('\n\t\t\tProperty: "ShowName", "bool", "",1') - file.write('\n\t\t\tProperty: "ShowGrid", "bool", "",1') - file.write('\n\t\t\tProperty: "ShowOpticalCenter", "bool", "",0') - file.write('\n\t\t\tProperty: "ShowAzimut", "bool", "",1') - file.write('\n\t\t\tProperty: "ShowTimeCode", "bool", "",0') - file.write('\n\t\t\tProperty: "NearPlane", "double", "",%.6f' % near) - file.write('\n\t\t\tProperty: "FarPlane", "double", "",%.6f' % far) - file.write('\n\t\t\tProperty: "FilmWidth", "double", "",0.816') - file.write('\n\t\t\tProperty: "FilmHeight", "double", "",0.612') - file.write('\n\t\t\tProperty: "FilmAspectRatio", "double", "",1.33333333333333') - file.write('\n\t\t\tProperty: "FilmSqueezeRatio", "double", "",1') - file.write('\n\t\t\tProperty: "FilmFormatIndex", "enum", "",4') - file.write('\n\t\t\tProperty: "ViewFrustum", "bool", "",1') - file.write('\n\t\t\tProperty: "ViewFrustumNearFarPlane", "bool", "",0') - file.write('\n\t\t\tProperty: "ViewFrustumBackPlaneMode", "enum", "",2') - file.write('\n\t\t\tProperty: "BackPlaneDistance", "double", "",100') - file.write('\n\t\t\tProperty: "BackPlaneDistanceMode", "enum", "",0') - file.write('\n\t\t\tProperty: "ViewCameraToLookAt", "bool", "",1') - file.write('\n\t\t\tProperty: "LockMode", "bool", "",0') - file.write('\n\t\t\tProperty: "LockInterestNavigation", "bool", "",0') - file.write('\n\t\t\tProperty: "FitImage", "bool", "",0') - file.write('\n\t\t\tProperty: "Crop", "bool", "",0') - file.write('\n\t\t\tProperty: "Center", "bool", "",1') - file.write('\n\t\t\tProperty: "KeepRatio", "bool", "",1') - file.write('\n\t\t\tProperty: "BackgroundMode", "enum", "",0') - file.write('\n\t\t\tProperty: "BackgroundAlphaTreshold", "double", "",0.5') - file.write('\n\t\t\tProperty: "ForegroundTransparent", "bool", "",1') - file.write('\n\t\t\tProperty: "DisplaySafeArea", "bool", "",0') - file.write('\n\t\t\tProperty: "SafeAreaDisplayStyle", "enum", "",1') - file.write('\n\t\t\tProperty: "SafeAreaAspectRatio", "double", "",1.33333333333333') - file.write('\n\t\t\tProperty: "Use2DMagnifierZoom", "bool", "",0') - file.write('\n\t\t\tProperty: "2D Magnifier Zoom", "Real", "A+",100') - file.write('\n\t\t\tProperty: "2D Magnifier X", "Real", "A+",50') - file.write('\n\t\t\tProperty: "2D Magnifier Y", "Real", "A+",50') - file.write('\n\t\t\tProperty: "CameraProjectionType", "enum", "",%i' % proj_type) - file.write('\n\t\t\tProperty: "UseRealTimeDOFAndAA", "bool", "",0') - file.write('\n\t\t\tProperty: "UseDepthOfField", "bool", "",0') - file.write('\n\t\t\tProperty: "FocusSource", "enum", "",0') - file.write('\n\t\t\tProperty: "FocusAngle", "double", "",3.5') - file.write('\n\t\t\tProperty: "FocusDistance", "double", "",200') - file.write('\n\t\t\tProperty: "UseAntialiasing", "bool", "",0') - file.write('\n\t\t\tProperty: "AntialiasingIntensity", "double", "",0.77777') - file.write('\n\t\t\tProperty: "UseAccumulationBuffer", "bool", "",0') - file.write('\n\t\t\tProperty: "FrameSamplingCount", "int", "",7') - file.write('\n\t\t}') - file.write('\n\t\tMultiLayer: 0') - file.write('\n\t\tMultiTake: 0') - file.write('\n\t\tHidden: "True"') - file.write('\n\t\tShading: Y') - file.write('\n\t\tCulling: "CullingOff"') - file.write('\n\t\tTypeFlags: "Camera"') - file.write('\n\t\tGeometryVersion: 124') - file.write('\n\t\tPosition: %.6f,%.6f,%.6f' % loc) - file.write('\n\t\tUp: %i,%i,%i' % up) - file.write('\n\t\tLookAt: 0,0,0') - file.write('\n\t\tShowInfoOnMoving: 1') - file.write('\n\t\tShowAudio: 0') - file.write('\n\t\tAudioColor: 0,1,0') - file.write('\n\t\tCameraOrthoZoom: 1') - file.write('\n\t}') - - def write_camera_default(): - # This sucks but to match FBX converter its easier to - # write the cameras though they are not needed. - write_camera_dummy('Producer Perspective', (0,71.3,287.5), 10, 4000, 0, (0,1,0)) - write_camera_dummy('Producer Top', (0,4000,0), 1, 30000, 1, (0,0,-1)) - write_camera_dummy('Producer Bottom', (0,-4000,0), 1, 30000, 1, (0,0,-1)) - write_camera_dummy('Producer Front', (0,0,4000), 1, 30000, 1, (0,1,0)) - write_camera_dummy('Producer Back', (0,0,-4000), 1, 30000, 1, (0,1,0)) - write_camera_dummy('Producer Right', (4000,0,0), 1, 30000, 1, (0,1,0)) - write_camera_dummy('Producer Left', (-4000,0,0), 1, 30000, 1, (0,1,0)) - - def write_camera(my_cam): - ''' - Write a blender camera - ''' - render = sce.render - width = render.sizeX - height = render.sizeY - aspect = float(width)/height - - data = my_cam.blenObject.data - - file.write('\n\tModel: "Model::%s", "Camera" {' % my_cam.fbxName ) - file.write('\n\t\tVersion: 232') - loc, rot, scale, matrix, matrix_rot = write_object_props(my_cam.blenObject, None, my_cam.parRelMatrix()) - - file.write('\n\t\t\tProperty: "Roll", "Roll", "A+",0') - file.write('\n\t\t\tProperty: "FieldOfView", "FieldOfView", "A+",%.6f' % data.angle) - file.write('\n\t\t\tProperty: "FieldOfViewX", "FieldOfView", "A+",1') - file.write('\n\t\t\tProperty: "FieldOfViewY", "FieldOfView", "A+",1') - file.write('\n\t\t\tProperty: "FocalLength", "Real", "A+",14.0323972702026') - file.write('\n\t\t\tProperty: "OpticalCenterX", "Real", "A+",%.6f' % data.shiftX) # not sure if this is in the correct units? - file.write('\n\t\t\tProperty: "OpticalCenterY", "Real", "A+",%.6f' % data.shiftY) # ditto - file.write('\n\t\t\tProperty: "BackgroundColor", "Color", "A+",0,0,0') - file.write('\n\t\t\tProperty: "TurnTable", "Real", "A+",0') - file.write('\n\t\t\tProperty: "DisplayTurnTableIcon", "bool", "",1') - file.write('\n\t\t\tProperty: "Motion Blur Intensity", "Real", "A+",1') - file.write('\n\t\t\tProperty: "UseMotionBlur", "bool", "",0') - file.write('\n\t\t\tProperty: "UseRealTimeMotionBlur", "bool", "",1') - file.write('\n\t\t\tProperty: "ResolutionMode", "enum", "",0') - file.write('\n\t\t\tProperty: "ApertureMode", "enum", "",2') - file.write('\n\t\t\tProperty: "GateFit", "enum", "",0') - file.write('\n\t\t\tProperty: "CameraFormat", "enum", "",0') - file.write('\n\t\t\tProperty: "AspectW", "double", "",%i' % width) - file.write('\n\t\t\tProperty: "AspectH", "double", "",%i' % height) - - '''Camera aspect ratio modes. - 0 If the ratio mode is eWINDOW_SIZE, both width and height values aren't relevant. - 1 If the ratio mode is eFIXED_RATIO, the height value is set to 1.0 and the width value is relative to the height value. - 2 If the ratio mode is eFIXED_RESOLUTION, both width and height values are in pixels. - 3 If the ratio mode is eFIXED_WIDTH, the width value is in pixels and the height value is relative to the width value. - 4 If the ratio mode is eFIXED_HEIGHT, the height value is in pixels and the width value is relative to the height value. - - Definition at line 234 of file kfbxcamera.h. ''' - - file.write('\n\t\t\tProperty: "PixelAspectRatio", "double", "",2') - - file.write('\n\t\t\tProperty: "UseFrameColor", "bool", "",0') - file.write('\n\t\t\tProperty: "FrameColor", "ColorRGB", "",0.3,0.3,0.3') - file.write('\n\t\t\tProperty: "ShowName", "bool", "",1') - file.write('\n\t\t\tProperty: "ShowGrid", "bool", "",1') - file.write('\n\t\t\tProperty: "ShowOpticalCenter", "bool", "",0') - file.write('\n\t\t\tProperty: "ShowAzimut", "bool", "",1') - file.write('\n\t\t\tProperty: "ShowTimeCode", "bool", "",0') - file.write('\n\t\t\tProperty: "NearPlane", "double", "",%.6f' % data.clipStart) - file.write('\n\t\t\tProperty: "FarPlane", "double", "",%.6f' % data.clipStart) - file.write('\n\t\t\tProperty: "FilmWidth", "double", "",1.0') - file.write('\n\t\t\tProperty: "FilmHeight", "double", "",1.0') - file.write('\n\t\t\tProperty: "FilmAspectRatio", "double", "",%.6f' % aspect) - file.write('\n\t\t\tProperty: "FilmSqueezeRatio", "double", "",1') - file.write('\n\t\t\tProperty: "FilmFormatIndex", "enum", "",0') - file.write('\n\t\t\tProperty: "ViewFrustum", "bool", "",1') - file.write('\n\t\t\tProperty: "ViewFrustumNearFarPlane", "bool", "",0') - file.write('\n\t\t\tProperty: "ViewFrustumBackPlaneMode", "enum", "",2') - file.write('\n\t\t\tProperty: "BackPlaneDistance", "double", "",100') - file.write('\n\t\t\tProperty: "BackPlaneDistanceMode", "enum", "",0') - file.write('\n\t\t\tProperty: "ViewCameraToLookAt", "bool", "",1') - file.write('\n\t\t\tProperty: "LockMode", "bool", "",0') - file.write('\n\t\t\tProperty: "LockInterestNavigation", "bool", "",0') - file.write('\n\t\t\tProperty: "FitImage", "bool", "",0') - file.write('\n\t\t\tProperty: "Crop", "bool", "",0') - file.write('\n\t\t\tProperty: "Center", "bool", "",1') - file.write('\n\t\t\tProperty: "KeepRatio", "bool", "",1') - file.write('\n\t\t\tProperty: "BackgroundMode", "enum", "",0') - file.write('\n\t\t\tProperty: "BackgroundAlphaTreshold", "double", "",0.5') - file.write('\n\t\t\tProperty: "ForegroundTransparent", "bool", "",1') - file.write('\n\t\t\tProperty: "DisplaySafeArea", "bool", "",0') - file.write('\n\t\t\tProperty: "SafeAreaDisplayStyle", "enum", "",1') - file.write('\n\t\t\tProperty: "SafeAreaAspectRatio", "double", "",%.6f' % aspect) - file.write('\n\t\t\tProperty: "Use2DMagnifierZoom", "bool", "",0') - file.write('\n\t\t\tProperty: "2D Magnifier Zoom", "Real", "A+",100') - file.write('\n\t\t\tProperty: "2D Magnifier X", "Real", "A+",50') - file.write('\n\t\t\tProperty: "2D Magnifier Y", "Real", "A+",50') - file.write('\n\t\t\tProperty: "CameraProjectionType", "enum", "",0') - file.write('\n\t\t\tProperty: "UseRealTimeDOFAndAA", "bool", "",0') - file.write('\n\t\t\tProperty: "UseDepthOfField", "bool", "",0') - file.write('\n\t\t\tProperty: "FocusSource", "enum", "",0') - file.write('\n\t\t\tProperty: "FocusAngle", "double", "",3.5') - file.write('\n\t\t\tProperty: "FocusDistance", "double", "",200') - file.write('\n\t\t\tProperty: "UseAntialiasing", "bool", "",0') - file.write('\n\t\t\tProperty: "AntialiasingIntensity", "double", "",0.77777') - file.write('\n\t\t\tProperty: "UseAccumulationBuffer", "bool", "",0') - file.write('\n\t\t\tProperty: "FrameSamplingCount", "int", "",7') - - file.write('\n\t\t}') - file.write('\n\t\tMultiLayer: 0') - file.write('\n\t\tMultiTake: 0') - file.write('\n\t\tShading: Y') - file.write('\n\t\tCulling: "CullingOff"') - file.write('\n\t\tTypeFlags: "Camera"') - file.write('\n\t\tGeometryVersion: 124') - file.write('\n\t\tPosition: %.6f,%.6f,%.6f' % loc) - file.write('\n\t\tUp: %.6f,%.6f,%.6f' % tuple(Vector(0,1,0) * matrix_rot) ) - file.write('\n\t\tLookAt: %.6f,%.6f,%.6f' % tuple(Vector(0,0,-1)*matrix_rot) ) - - #file.write('\n\t\tUp: 0,0,0' ) - #file.write('\n\t\tLookAt: 0,0,0' ) - - file.write('\n\t\tShowInfoOnMoving: 1') - file.write('\n\t\tShowAudio: 0') - file.write('\n\t\tAudioColor: 0,1,0') - file.write('\n\t\tCameraOrthoZoom: 1') - file.write('\n\t}') - - def write_light(my_light): - light = my_light.blenObject.data - file.write('\n\tModel: "Model::%s", "Light" {' % my_light.fbxName) - file.write('\n\t\tVersion: 232') - - write_object_props(my_light.blenObject, None, my_light.parRelMatrix()) - - # Why are these values here twice?????? - oh well, follow the holy sdk's output - - # Blender light types match FBX's, funny coincidence, we just need to - # be sure that all unsupported types are made into a point light - #ePOINT, - #eDIRECTIONAL - #eSPOT - light_type = light.type - if light_type > 2: light_type = 1 # hemi and area lights become directional - - mode = light.mode - if mode & Blender.Lamp.Modes.RayShadow or mode & Blender.Lamp.Modes.Shadows: - do_shadow = 1 - else: - do_shadow = 0 - - if mode & Blender.Lamp.Modes.OnlyShadow or (mode & Blender.Lamp.Modes.NoDiffuse and mode & Blender.Lamp.Modes.NoSpecular): - do_light = 0 - else: - do_light = 1 - - scale = abs(GLOBAL_MATRIX.scalePart()[0]) # scale is always uniform in this case - - file.write('\n\t\t\tProperty: "LightType", "enum", "",%i' % light_type) - file.write('\n\t\t\tProperty: "CastLightOnObject", "bool", "",1') - file.write('\n\t\t\tProperty: "DrawVolumetricLight", "bool", "",1') - file.write('\n\t\t\tProperty: "DrawGroundProjection", "bool", "",1') - file.write('\n\t\t\tProperty: "DrawFrontFacingVolumetricLight", "bool", "",0') - file.write('\n\t\t\tProperty: "GoboProperty", "object", ""') - file.write('\n\t\t\tProperty: "Color", "Color", "A+",1,1,1') - file.write('\n\t\t\tProperty: "Intensity", "Intensity", "A+",%.2f' % (min(light.energy*100, 200))) # clamp below 200 - file.write('\n\t\t\tProperty: "Cone angle", "Cone angle", "A+",%.2f' % (light.spotSize * scale)) - file.write('\n\t\t\tProperty: "Fog", "Fog", "A+",50') - file.write('\n\t\t\tProperty: "Color", "Color", "A",%.2f,%.2f,%.2f' % tuple(light.col)) - file.write('\n\t\t\tProperty: "Intensity", "Intensity", "A+",%.2f' % (min(light.energy*100, 200))) # clamp below 200 - file.write('\n\t\t\tProperty: "Cone angle", "Cone angle", "A+",%.2f' % (light.spotSize * scale)) - file.write('\n\t\t\tProperty: "Fog", "Fog", "A+",50') - file.write('\n\t\t\tProperty: "LightType", "enum", "",%i' % light_type) - file.write('\n\t\t\tProperty: "CastLightOnObject", "bool", "",%i' % do_light) - file.write('\n\t\t\tProperty: "DrawGroundProjection", "bool", "",1') - file.write('\n\t\t\tProperty: "DrawFrontFacingVolumetricLight", "bool", "",0') - file.write('\n\t\t\tProperty: "DrawVolumetricLight", "bool", "",1') - file.write('\n\t\t\tProperty: "GoboProperty", "object", ""') - file.write('\n\t\t\tProperty: "DecayType", "enum", "",0') - file.write('\n\t\t\tProperty: "DecayStart", "double", "",%.2f' % light.dist) - file.write('\n\t\t\tProperty: "EnableNearAttenuation", "bool", "",0') - file.write('\n\t\t\tProperty: "NearAttenuationStart", "double", "",0') - file.write('\n\t\t\tProperty: "NearAttenuationEnd", "double", "",0') - file.write('\n\t\t\tProperty: "EnableFarAttenuation", "bool", "",0') - file.write('\n\t\t\tProperty: "FarAttenuationStart", "double", "",0') - file.write('\n\t\t\tProperty: "FarAttenuationEnd", "double", "",0') - file.write('\n\t\t\tProperty: "CastShadows", "bool", "",%i' % do_shadow) - file.write('\n\t\t\tProperty: "ShadowColor", "ColorRGBA", "",0,0,0,1') - file.write('\n\t\t}') - file.write('\n\t\tMultiLayer: 0') - file.write('\n\t\tMultiTake: 0') - file.write('\n\t\tShading: Y') - file.write('\n\t\tCulling: "CullingOff"') - file.write('\n\t\tTypeFlags: "Light"') - file.write('\n\t\tGeometryVersion: 124') - file.write('\n\t}') - - # matrixOnly is not used at the moment - def write_null(my_null = None, fbxName = None, matrixOnly = None): - # ob can be null - if not fbxName: fbxName = my_null.fbxName - - file.write('\n\tModel: "Model::%s", "Null" {' % fbxName) - file.write('\n\t\tVersion: 232') - - # only use this for the root matrix at the moment - if matrixOnly: - poseMatrix = write_object_props(None, None, matrixOnly)[3] - - else: # all other Null's - if my_null: poseMatrix = write_object_props(my_null.blenObject, None, my_null.parRelMatrix())[3] - else: poseMatrix = write_object_props()[3] - - pose_items.append((fbxName, poseMatrix)) - - file.write(''' - } - MultiLayer: 0 - MultiTake: 1 - Shading: Y - Culling: "CullingOff" - TypeFlags: "Null" - }''') - - # Material Settings - if world: world_amb = world.getAmb() - else: world_amb = (0,0,0) # Default value - - def write_material(matname, mat): - file.write('\n\tMaterial: "Material::%s", "" {' % matname) - - # Todo, add more material Properties. - if mat: - mat_cold = tuple(mat.rgbCol) - mat_cols = tuple(mat.specCol) - #mat_colm = tuple(mat.mirCol) # we wont use the mirror color - mat_colamb = tuple([c for c in world_amb]) - - mat_dif = mat.ref - mat_amb = mat.amb - mat_hard = (float(mat.hard)-1)/5.10 - mat_spec = mat.spec/2.0 - mat_alpha = mat.alpha - mat_emit = mat.emit - mat_shadeless = mat.mode & Blender.Material.Modes.SHADELESS - if mat_shadeless: - mat_shader = 'Lambert' - else: - if mat.diffuseShader == Blender.Material.Shaders.DIFFUSE_LAMBERT: - mat_shader = 'Lambert' - else: - mat_shader = 'Phong' - else: - mat_cols = mat_cold = 0.8, 0.8, 0.8 - mat_colamb = 0.0,0.0,0.0 - # mat_colm - mat_dif = 1.0 - mat_amb = 0.5 - mat_hard = 20.0 - mat_spec = 0.2 - mat_alpha = 1.0 - mat_emit = 0.0 - mat_shadeless = False - mat_shader = 'Phong' - - file.write('\n\t\tVersion: 102') - file.write('\n\t\tShadingModel: "%s"' % mat_shader.lower()) - file.write('\n\t\tMultiLayer: 0') - - file.write('\n\t\tProperties60: {') - file.write('\n\t\t\tProperty: "ShadingModel", "KString", "", "%s"' % mat_shader) - file.write('\n\t\t\tProperty: "MultiLayer", "bool", "",0') - file.write('\n\t\t\tProperty: "EmissiveColor", "ColorRGB", "",%.4f,%.4f,%.4f' % mat_cold) # emit and diffuse color are he same in blender - file.write('\n\t\t\tProperty: "EmissiveFactor", "double", "",%.4f' % mat_emit) - - file.write('\n\t\t\tProperty: "AmbientColor", "ColorRGB", "",%.4f,%.4f,%.4f' % mat_colamb) - file.write('\n\t\t\tProperty: "AmbientFactor", "double", "",%.4f' % mat_amb) - file.write('\n\t\t\tProperty: "DiffuseColor", "ColorRGB", "",%.4f,%.4f,%.4f' % mat_cold) - file.write('\n\t\t\tProperty: "DiffuseFactor", "double", "",%.4f' % mat_dif) - file.write('\n\t\t\tProperty: "Bump", "Vector3D", "",0,0,0') - file.write('\n\t\t\tProperty: "TransparentColor", "ColorRGB", "",1,1,1') - file.write('\n\t\t\tProperty: "TransparencyFactor", "double", "",%.4f' % (1.0 - mat_alpha)) - if not mat_shadeless: - file.write('\n\t\t\tProperty: "SpecularColor", "ColorRGB", "",%.4f,%.4f,%.4f' % mat_cols) - file.write('\n\t\t\tProperty: "SpecularFactor", "double", "",%.4f' % mat_spec) - file.write('\n\t\t\tProperty: "ShininessExponent", "double", "",80.0') - file.write('\n\t\t\tProperty: "ReflectionColor", "ColorRGB", "",0,0,0') - file.write('\n\t\t\tProperty: "ReflectionFactor", "double", "",1') - file.write('\n\t\t\tProperty: "Emissive", "ColorRGB", "",0,0,0') - file.write('\n\t\t\tProperty: "Ambient", "ColorRGB", "",%.1f,%.1f,%.1f' % mat_colamb) - file.write('\n\t\t\tProperty: "Diffuse", "ColorRGB", "",%.1f,%.1f,%.1f' % mat_cold) - if not mat_shadeless: - file.write('\n\t\t\tProperty: "Specular", "ColorRGB", "",%.1f,%.1f,%.1f' % mat_cols) - file.write('\n\t\t\tProperty: "Shininess", "double", "",%.1f' % mat_hard) - file.write('\n\t\t\tProperty: "Opacity", "double", "",%.1f' % mat_alpha) - if not mat_shadeless: - file.write('\n\t\t\tProperty: "Reflectivity", "double", "",0') - - file.write('\n\t\t}') - file.write('\n\t}') - - def write_video(texname, tex): - # Same as texture really! - file.write('\n\tVideo: "Video::%s", "Clip" {' % texname) - - file.write(''' - Type: "Clip" - Properties60: { - Property: "FrameRate", "double", "",0 - Property: "LastFrame", "int", "",0 - Property: "Width", "int", "",0 - Property: "Height", "int", "",0''') - if tex: - fname, fname_strip, fname_rel = derived_paths(tex.filename, basepath, EXP_IMAGE_COPY) - else: - fname = fname_strip = fname_rel = '' - - file.write('\n\t\t\tProperty: "Path", "charptr", "", "%s"' % fname_strip) - - - file.write(''' - Property: "StartFrame", "int", "",0 - Property: "StopFrame", "int", "",0 - Property: "PlaySpeed", "double", "",1 - Property: "Offset", "KTime", "",0 - Property: "InterlaceMode", "enum", "",0 - Property: "FreeRunning", "bool", "",0 - Property: "Loop", "bool", "",0 - Property: "AccessMode", "enum", "",0 - } - UseMipMap: 0''') - - file.write('\n\t\tFilename: "%s"' % fname_strip) - if fname_strip: fname_strip = '/' + fname_strip - file.write('\n\t\tRelativeFilename: "%s"' % fname_rel) # make relative - file.write('\n\t}') - - - def write_texture(texname, tex, num): - # if tex == None then this is a dummy tex - file.write('\n\tTexture: "Texture::%s", "TextureVideoClip" {' % texname) - file.write('\n\t\tType: "TextureVideoClip"') - file.write('\n\t\tVersion: 202') - # TODO, rare case _empty_ exists as a name. - file.write('\n\t\tTextureName: "Texture::%s"' % texname) - - file.write(''' - Properties60: { - Property: "Translation", "Vector", "A+",0,0,0 - Property: "Rotation", "Vector", "A+",0,0,0 - Property: "Scaling", "Vector", "A+",1,1,1''') - file.write('\n\t\t\tProperty: "Texture alpha", "Number", "A+",%i' % num) - - - # WrapModeU/V 0==rep, 1==clamp, TODO add support - file.write(''' - Property: "TextureTypeUse", "enum", "",0 - Property: "CurrentTextureBlendMode", "enum", "",1 - Property: "UseMaterial", "bool", "",0 - Property: "UseMipMap", "bool", "",0 - Property: "CurrentMappingType", "enum", "",0 - Property: "UVSwap", "bool", "",0''') - - file.write('\n\t\t\tProperty: "WrapModeU", "enum", "",%i' % tex.clampX) - file.write('\n\t\t\tProperty: "WrapModeV", "enum", "",%i' % tex.clampY) - - file.write(''' - Property: "TextureRotationPivot", "Vector3D", "",0,0,0 - Property: "TextureScalingPivot", "Vector3D", "",0,0,0 - Property: "VideoProperty", "object", "" - }''') - - file.write('\n\t\tMedia: "Video::%s"' % texname) - - if tex: - fname, fname_strip, fname_rel = derived_paths(tex.filename, basepath, EXP_IMAGE_COPY) - else: - fname = fname_strip = fname_rel = '' - - file.write('\n\t\tFileName: "%s"' % fname_strip) - file.write('\n\t\tRelativeFilename: "%s"' % fname_rel) # need some make relative command - - file.write(''' - ModelUVTranslation: 0,0 - ModelUVScaling: 1,1 - Texture_Alpha_Source: "None" - Cropping: 0,0,0,0 - }''') - - def write_deformer_skin(obname): - ''' - Each mesh has its own deformer - ''' - file.write('\n\tDeformer: "Deformer::Skin %s", "Skin" {' % obname) - file.write(''' - Version: 100 - MultiLayer: 0 - Type: "Skin" - Properties60: { - } - Link_DeformAcuracy: 50 - }''') - - # in the example was 'Bip01 L Thigh_2' - def write_sub_deformer_skin(my_mesh, my_bone, weights): - - ''' - Each subdeformer is spesific to a mesh, but the bone it links to can be used by many sub-deformers - So the SubDeformer needs the mesh-object name as a prefix to make it unique - - Its possible that there is no matching vgroup in this mesh, in that case no verts are in the subdeformer, - a but silly but dosnt really matter - ''' - file.write('\n\tDeformer: "SubDeformer::Cluster %s %s", "Cluster" {' % (my_mesh.fbxName, my_bone.fbxName)) - - file.write(''' - Version: 100 - MultiLayer: 0 - Type: "Cluster" - Properties60: { - Property: "SrcModel", "object", "" - Property: "SrcModelReference", "object", "" - } - UserData: "", ""''') - - # Support for bone parents - if my_mesh.fbxBoneParent: - if my_mesh.fbxBoneParent == my_bone: - # TODO - this is a bit lazy, we could have a simple write loop - # for this case because all weights are 1.0 but for now this is ok - # Parent Bones arent used all that much anyway. - vgroup_data = [(j, 1.0) for j in xrange(len(my_mesh.blenData.verts))] - else: - # This bone is not a parent of this mesh object, no weights - vgroup_data = [] - - else: - # Normal weight painted mesh - if my_bone.blenName in weights[0]: - # Before we used normalized wright list - #vgroup_data = me.getVertsFromGroup(bone.name, 1) - group_index = weights[0].index(my_bone.blenName) - vgroup_data = [(j, weight[group_index]) for j, weight in enumerate(weights[1]) if weight[group_index]] - else: - vgroup_data = [] - - file.write('\n\t\tIndexes: ') - - i = -1 - for vg in vgroup_data: - if i == -1: - file.write('%i' % vg[0]) - i=0 - else: - if i==23: - file.write('\n\t\t') - i=0 - file.write(',%i' % vg[0]) - i+=1 - - file.write('\n\t\tWeights: ') - i = -1 - for vg in vgroup_data: - if i == -1: - file.write('%.8f' % vg[1]) - i=0 - else: - if i==38: - file.write('\n\t\t') - i=0 - file.write(',%.8f' % vg[1]) - i+=1 - - if my_mesh.fbxParent: - # TODO FIXME, this case is broken in some cases. skinned meshes just shouldnt have parents where possible! - m = mtx4_z90 * (my_bone.restMatrix * my_bone.fbxArm.matrixWorld.copy() * my_mesh.matrixWorld.copy().invert() ) - else: - # Yes! this is it... - but dosnt work when the mesh is a. - m = mtx4_z90 * (my_bone.restMatrix * my_bone.fbxArm.matrixWorld.copy() * my_mesh.matrixWorld.copy().invert() ) - - #m = mtx4_z90 * my_bone.restMatrix - matstr = mat4x4str(m) - matstr_i = mat4x4str(m.invert()) - - file.write('\n\t\tTransform: %s' % matstr_i) # THIS IS __NOT__ THE GLOBAL MATRIX AS DOCUMENTED :/ - file.write('\n\t\tTransformLink: %s' % matstr) - file.write('\n\t}') - - def write_mesh(my_mesh): - - me = my_mesh.blenData - - # if there are non NULL materials on this mesh - if my_mesh.blenMaterials: do_materials = True - else: do_materials = False - - if my_mesh.blenTextures: do_textures = True - else: do_textures = False - - do_uvs = me.faceUV - - - file.write('\n\tModel: "Model::%s", "Mesh" {' % my_mesh.fbxName) - file.write('\n\t\tVersion: 232') # newline is added in write_object_props - - poseMatrix = write_object_props(my_mesh.blenObject, None, my_mesh.parRelMatrix())[3] - pose_items.append((my_mesh.fbxName, poseMatrix)) - - file.write('\n\t\t}') - file.write('\n\t\tMultiLayer: 0') - file.write('\n\t\tMultiTake: 1') - file.write('\n\t\tShading: Y') - file.write('\n\t\tCulling: "CullingOff"') - - - # Write the Real Mesh data here - file.write('\n\t\tVertices: ') - i=-1 - - for v in me.verts: - if i==-1: - file.write('%.6f,%.6f,%.6f' % tuple(v.co)); i=0 - else: - if i==7: - file.write('\n\t\t'); i=0 - file.write(',%.6f,%.6f,%.6f'% tuple(v.co)) - i+=1 - - file.write('\n\t\tPolygonVertexIndex: ') - i=-1 - for f in me.faces: - fi = [v.index for v in f] - # flip the last index, odd but it looks like - # this is how fbx tells one face from another - fi[-1] = -(fi[-1]+1) - fi = tuple(fi) - if i==-1: - if len(f) == 3: file.write('%i,%i,%i' % fi ) - else: file.write('%i,%i,%i,%i' % fi ) - i=0 - else: - if i==13: - file.write('\n\t\t') - i=0 - if len(f) == 3: file.write(',%i,%i,%i' % fi ) - else: file.write(',%i,%i,%i,%i' % fi ) - i+=1 - - file.write('\n\t\tEdges: ') - i=-1 - for ed in me.edges: - if i==-1: - file.write('%i,%i' % (ed.v1.index, ed.v2.index)) - i=0 - else: - if i==13: - file.write('\n\t\t') - i=0 - file.write(',%i,%i' % (ed.v1.index, ed.v2.index)) - i+=1 - - file.write('\n\t\tGeometryVersion: 124') - - file.write(''' - LayerElementNormal: 0 { - Version: 101 - Name: "" - MappingInformationType: "ByVertice" - ReferenceInformationType: "Direct" - Normals: ''') - - i=-1 - for v in me.verts: - if i==-1: - file.write('%.15f,%.15f,%.15f' % tuple(v.no)); i=0 - else: - if i==2: - file.write('\n '); i=0 - file.write(',%.15f,%.15f,%.15f' % tuple(v.no)) - i+=1 - file.write('\n\t\t}') - - # Write Face Smoothing - file.write(''' - LayerElementSmoothing: 0 { - Version: 102 - Name: "" - MappingInformationType: "ByPolygon" - ReferenceInformationType: "Direct" - Smoothing: ''') - - i=-1 - for f in me.faces: - if i==-1: - file.write('%i' % f.smooth); i=0 - else: - if i==54: - file.write('\n '); i=0 - file.write(',%i' % f.smooth) - i+=1 - - file.write('\n\t\t}') - - # Write Edge Smoothing - file.write(''' - LayerElementSmoothing: 1 { - Version: 101 - Name: "" - MappingInformationType: "ByEdge" - ReferenceInformationType: "Direct" - Smoothing: ''') - - SHARP = Blender.Mesh.EdgeFlags.SHARP - i=-1 - for ed in me.edges: - if i==-1: - file.write('%i' % ((ed.flag&SHARP)!=0)); i=0 - else: - if i==54: - file.write('\n '); i=0 - file.write(',%i' % ((ed.flag&SHARP)!=0)) - i+=1 - - file.write('\n\t\t}') - del SHARP - - - # Write VertexColor Layers - # note, no programs seem to use this info :/ - collayers = [] - if me.vertexColors: - collayers = me.getColorLayerNames() - collayer_orig = me.activeColorLayer - for colindex, collayer in enumerate(collayers): - me.activeColorLayer = collayer - file.write('\n\t\tLayerElementColor: %i {' % colindex) - file.write('\n\t\t\tVersion: 101') - file.write('\n\t\t\tName: "%s"' % collayer) - - file.write(''' - MappingInformationType: "ByPolygonVertex" - ReferenceInformationType: "IndexToDirect" - Colors: ''') - - i = -1 - ii = 0 # Count how many Colors we write - - for f in me.faces: - for col in f.col: - if i==-1: - file.write('%.4f,%.4f,%.4f,1' % (col[0]/255.0, col[1]/255.0, col[2]/255.0)) - i=0 - else: - if i==7: - file.write('\n\t\t\t\t') - i=0 - file.write(',%.4f,%.4f,%.4f,1' % (col[0]/255.0, col[1]/255.0, col[2]/255.0)) - i+=1 - ii+=1 # One more Color - - file.write('\n\t\t\tColorIndex: ') - i = -1 - for j in xrange(ii): - if i == -1: - file.write('%i' % j) - i=0 - else: - if i==55: - file.write('\n\t\t\t\t') - i=0 - file.write(',%i' % j) - i+=1 - - file.write('\n\t\t}') - - - - # Write UV and texture layers. - uvlayers = [] - if do_uvs: - uvlayers = me.getUVLayerNames() - uvlayer_orig = me.activeUVLayer - for uvindex, uvlayer in enumerate(uvlayers): - me.activeUVLayer = uvlayer - file.write('\n\t\tLayerElementUV: %i {' % uvindex) - file.write('\n\t\t\tVersion: 101') - file.write('\n\t\t\tName: "%s"' % uvlayer) - - file.write(''' - MappingInformationType: "ByPolygonVertex" - ReferenceInformationType: "IndexToDirect" - UV: ''') - - i = -1 - ii = 0 # Count how many UVs we write - - for f in me.faces: - for uv in f.uv: - if i==-1: - file.write('%.6f,%.6f' % tuple(uv)) - i=0 - else: - if i==7: - file.write('\n ') - i=0 - file.write(',%.6f,%.6f' % tuple(uv)) - i+=1 - ii+=1 # One more UV - - file.write('\n\t\t\tUVIndex: ') - i = -1 - for j in xrange(ii): - if i == -1: - file.write('%i' % j) - i=0 - else: - if i==55: - file.write('\n\t\t\t\t') - i=0 - file.write(',%i' % j) - i+=1 - - file.write('\n\t\t}') - - if do_textures: - file.write('\n\t\tLayerElementTexture: %i {' % uvindex) - file.write('\n\t\t\tVersion: 101') - file.write('\n\t\t\tName: "%s"' % uvlayer) - - if len(my_mesh.blenTextures) == 1: - file.write('\n\t\t\tMappingInformationType: "AllSame"') - else: - file.write('\n\t\t\tMappingInformationType: "ByPolygon"') - - file.write('\n\t\t\tReferenceInformationType: "IndexToDirect"') - file.write('\n\t\t\tBlendMode: "Translucent"') - file.write('\n\t\t\tTextureAlpha: 1') - file.write('\n\t\t\tTextureId: ') - - if len(my_mesh.blenTextures) == 1: - file.write('0') - else: - texture_mapping_local = {None:-1} - - i = 0 # 1 for dummy - for tex in my_mesh.blenTextures: - if tex: # None is set above - texture_mapping_local[tex] = i - i+=1 - - i=-1 - for f in me.faces: - img_key = f.image - - if i==-1: - i=0 - file.write( '%s' % texture_mapping_local[img_key]) - else: - if i==55: - file.write('\n ') - i=0 - - file.write(',%s' % texture_mapping_local[img_key]) - i+=1 - - else: - file.write(''' - LayerElementTexture: 0 { - Version: 101 - Name: "" - MappingInformationType: "NoMappingInformation" - ReferenceInformationType: "IndexToDirect" - BlendMode: "Translucent" - TextureAlpha: 1 - TextureId: ''') - file.write('\n\t\t}') - - me.activeUVLayer = uvlayer_orig - - # Done with UV/textures. - - if do_materials: - file.write('\n\t\tLayerElementMaterial: 0 {') - file.write('\n\t\t\tVersion: 101') - file.write('\n\t\t\tName: ""') - - if len(my_mesh.blenMaterials) == 1: - file.write('\n\t\t\tMappingInformationType: "AllSame"') - else: - file.write('\n\t\t\tMappingInformationType: "ByPolygon"') - - file.write('\n\t\t\tReferenceInformationType: "IndexToDirect"') - file.write('\n\t\t\tMaterials: ') - - if len(my_mesh.blenMaterials) == 1: - file.write('0') - else: - # Build a material mapping for this - material_mapping_local = {} # local-mat & tex : global index. - - for j, mat_tex_pair in enumerate(my_mesh.blenMaterials): - material_mapping_local[mat_tex_pair] = j - - len_material_mapping_local = len(material_mapping_local) - - mats = my_mesh.blenMaterialList - - i=-1 - for f in me.faces: - try: mat = mats[f.mat] - except:mat = None - - if do_uvs: tex = f.image # WARNING - MULTI UV LAYER IMAGES NOT SUPPORTED :/ - else: tex = None - - if i==-1: - i=0 - file.write( '%s' % (material_mapping_local[mat, tex])) # None for mat or tex is ok - else: - if i==55: - file.write('\n\t\t\t\t') - i=0 - - file.write(',%s' % (material_mapping_local[mat, tex])) - i+=1 - - file.write('\n\t\t}') - - file.write(''' - Layer: 0 { - Version: 100 - LayerElement: { - Type: "LayerElementNormal" - TypedIndex: 0 - }''') - - if do_materials: - file.write(''' - LayerElement: { - Type: "LayerElementMaterial" - TypedIndex: 0 - }''') - - # Always write this - if do_textures: - file.write(''' - LayerElement: { - Type: "LayerElementTexture" - TypedIndex: 0 - }''') - - if me.vertexColors: - file.write(''' - LayerElement: { - Type: "LayerElementColor" - TypedIndex: 0 - }''') - - if do_uvs: # same as me.faceUV - file.write(''' - LayerElement: { - Type: "LayerElementUV" - TypedIndex: 0 - }''') - - - file.write('\n\t\t}') - - if len(uvlayers) > 1: - for i in xrange(1, len(uvlayers)): - - file.write('\n\t\tLayer: %i {' % i) - file.write('\n\t\t\tVersion: 100') - - file.write(''' - LayerElement: { - Type: "LayerElementUV"''') - - file.write('\n\t\t\t\tTypedIndex: %i' % i) - file.write('\n\t\t\t}') - - if do_textures: - - file.write(''' - LayerElement: { - Type: "LayerElementTexture"''') - - file.write('\n\t\t\t\tTypedIndex: %i' % i) - file.write('\n\t\t\t}') - - file.write('\n\t\t}') - - if len(collayers) > 1: - # Take into account any UV layers - layer_offset = 0 - if uvlayers: layer_offset = len(uvlayers)-1 - - for i in xrange(layer_offset, len(collayers)+layer_offset): - file.write('\n\t\tLayer: %i {' % i) - file.write('\n\t\t\tVersion: 100') - - file.write(''' - LayerElement: { - Type: "LayerElementColor"''') - - file.write('\n\t\t\t\tTypedIndex: %i' % i) - file.write('\n\t\t\t}') - file.write('\n\t\t}') - file.write('\n\t}') - - def write_group(name): - file.write('\n\tGroupSelection: "GroupSelection::%s", "Default" {' % name) - - file.write(''' - Properties60: { - Property: "MultiLayer", "bool", "",0 - Property: "Pickable", "bool", "",1 - Property: "Transformable", "bool", "",1 - Property: "Show", "bool", "",1 - } - MultiLayer: 0 - }''') - - - # add meshes here to clear because they are not used anywhere. - meshes_to_clear = [] - - ob_meshes = [] - ob_lights = [] - ob_cameras = [] - # in fbx we export bones as children of the mesh - # armatures not a part of a mesh, will be added to ob_arms - ob_bones = [] - ob_arms = [] - ob_null = [] # emptys - - # List of types that have blender objects (not bones) - ob_all_typegroups = [ob_meshes, ob_lights, ob_cameras, ob_arms, ob_null] - - groups = [] # blender groups, only add ones that have objects in the selections - materials = {} # (mat, image) keys, should be a set() - textures = {} # should be a set() - - tmp_ob_type = ob_type = None # incase no objects are exported, so as not to raise an error - - # if EXP_OBS_SELECTED is false, use sceens objects - if not batch_objects: - if EXP_OBS_SELECTED: tmp_objects = sce.objects.context - else: tmp_objects = sce.objects - else: - tmp_objects = batch_objects - - if EXP_ARMATURE: - # This is needed so applying modifiers dosnt apply the armature deformation, its also needed - # ...so mesh objects return their rest worldspace matrix when bone-parents are exported as weighted meshes. - # set every armature to its rest, backup the original values so we done mess up the scene - ob_arms_orig_rest = [arm.restPosition for arm in bpy.data.armatures] - - for arm in bpy.data.armatures: - arm.restPosition = True - - if ob_arms_orig_rest: - for ob_base in bpy.data.objects: - #if ob_base.type == 'Armature': - ob_base.makeDisplayList() - - # This causes the makeDisplayList command to effect the mesh - Blender.Set('curframe', Blender.Get('curframe')) - - - for ob_base in tmp_objects: - for ob, mtx in BPyObject.getDerivedObjects(ob_base): - #for ob in [ob_base,]: - tmp_ob_type = ob.type - if tmp_ob_type == 'Camera': - if EXP_CAMERA: - ob_cameras.append(my_object_generic(ob, mtx)) - elif tmp_ob_type == 'Lamp': - if EXP_LAMP: - ob_lights.append(my_object_generic(ob, mtx)) - elif tmp_ob_type == 'Armature': - if EXP_ARMATURE: - # TODO - armatures dont work in dupligroups! - if ob not in ob_arms: ob_arms.append(ob) - # ob_arms.append(ob) # replace later. was "ob_arms.append(sane_obname(ob), ob)" - elif tmp_ob_type == 'Empty': - if EXP_EMPTY: - ob_null.append(my_object_generic(ob, mtx)) - elif EXP_MESH: - origData = True - if tmp_ob_type != 'Mesh': - me = bpy.data.meshes.new() - try: me.getFromObject(ob) - except: me = None - if me: - meshes_to_clear.append( me ) - mats = me.materials - origData = False - else: - # Mesh Type! - if EXP_MESH_APPLY_MOD: - me = bpy.data.meshes.new() - me.getFromObject(ob) - - # so we keep the vert groups - if EXP_ARMATURE: - orig_mesh = ob.getData(mesh=1) - if orig_mesh.getVertGroupNames(): - ob.copy().link(me) - # If new mesh has no vgroups we can try add if verts are teh same - if not me.getVertGroupNames(): # vgroups were not kept by the modifier - if len(me.verts) == len(orig_mesh.verts): - groupNames, vWeightDict = BPyMesh.meshWeight2Dict(orig_mesh) - BPyMesh.dict2MeshWeight(me, groupNames, vWeightDict) - - # print ob, me, me.getVertGroupNames() - meshes_to_clear.append( me ) - origData = False - mats = me.materials - else: - me = ob.getData(mesh=1) - mats = me.materials - - # Support object colors - tmp_colbits = ob.colbits - if tmp_colbits: - tmp_ob_mats = ob.getMaterials(1) # 1 so we get None's too. - for i in xrange(16): - if tmp_colbits & (1<<i): - mats[i] = tmp_ob_mats[i] - del tmp_ob_mats - del tmp_colbits - - - if me: - # This WILL modify meshes in blender if EXP_MESH_APPLY_MOD is disabled. - # so strictly this is bad. but only in rare cases would it have negative results - # say with dupliverts the objects would rotate a bit differently - if EXP_MESH_HQ_NORMALS: - BPyMesh.meshCalcNormals(me) # high quality normals nice for realtime engines. - - texture_mapping_local = {} - material_mapping_local = {} - if me.faceUV: - uvlayer_orig = me.activeUVLayer - for uvlayer in me.getUVLayerNames(): - me.activeUVLayer = uvlayer - for f in me.faces: - tex = f.image - textures[tex] = texture_mapping_local[tex] = None - - try: mat = mats[f.mat] - except: mat = None - - materials[mat, tex] = material_mapping_local[mat, tex] = None # should use sets, wait for blender 2.5 - - - me.activeUVLayer = uvlayer_orig - else: - for mat in mats: - # 2.44 use mat.lib too for uniqueness - materials[mat, None] = material_mapping_local[mat, None] = None - else: - materials[None, None] = None - - if EXP_ARMATURE: - armob = BPyObject.getObjectArmature(ob) - blenParentBoneName = None - - # parent bone - special case - if (not armob) and ob.parent and ob.parent.type == 'Armature' and ob.parentType == Blender.Object.ParentTypes.BONE: - armob = ob.parent - blenParentBoneName = ob.parentbonename - - - if armob and armob not in ob_arms: - ob_arms.append(armob) - - else: - blenParentBoneName = armob = None - - my_mesh = my_object_generic(ob, mtx) - my_mesh.blenData = me - my_mesh.origData = origData - my_mesh.blenMaterials = material_mapping_local.keys() - my_mesh.blenMaterialList = mats - my_mesh.blenTextures = texture_mapping_local.keys() - - # if only 1 null texture then empty the list - if len(my_mesh.blenTextures) == 1 and my_mesh.blenTextures[0] == None: - my_mesh.blenTextures = [] - - my_mesh.fbxArm = armob # replace with my_object_generic armature instance later - my_mesh.fbxBoneParent = blenParentBoneName # replace with my_bone instance later - - ob_meshes.append( my_mesh ) - - if EXP_ARMATURE: - # now we have the meshes, restore the rest arm position - for i, arm in enumerate(bpy.data.armatures): - arm.restPosition = ob_arms_orig_rest[i] - - if ob_arms_orig_rest: - for ob_base in bpy.data.objects: - if ob_base.type == 'Armature': - ob_base.makeDisplayList() - # This causes the makeDisplayList command to effect the mesh - Blender.Set('curframe', Blender.Get('curframe')) - - del tmp_ob_type, tmp_objects - - # now we have collected all armatures, add bones - for i, ob in enumerate(ob_arms): - - ob_arms[i] = my_arm = my_object_generic(ob) - - my_arm.fbxBones = [] - my_arm.blenData = ob.data - my_arm.blenAction = ob.action - my_arm.blenActionList = [] - - # fbxName, blenderObject, my_bones, blenderActions - #ob_arms[i] = fbxArmObName, ob, arm_my_bones, (ob.action, []) - - for bone in my_arm.blenData.bones.values(): - my_bone = my_bone_class(bone, my_arm) - my_arm.fbxBones.append( my_bone ) - ob_bones.append( my_bone ) - - # add the meshes to the bones and replace the meshes armature with own armature class - #for obname, ob, mtx, me, mats, arm, armname in ob_meshes: - for my_mesh in ob_meshes: - # Replace - # ...this could be sped up with dictionary mapping but its unlikely for - # it ever to be a bottleneck - (would need 100+ meshes using armatures) - if my_mesh.fbxArm: - for my_arm in ob_arms: - if my_arm.blenObject == my_mesh.fbxArm: - my_mesh.fbxArm = my_arm - break - - for my_bone in ob_bones: - - # The mesh uses this bones armature! - if my_bone.fbxArm == my_mesh.fbxArm: - my_bone.blenMeshes[my_mesh.fbxName] = me - - - # parent bone: replace bone names with our class instances - # my_mesh.fbxBoneParent is None or a blender bone name initialy, replacing if the names match. - if my_mesh.fbxBoneParent == my_bone.blenName: - my_mesh.fbxBoneParent = my_bone - - bone_deformer_count = 0 # count how many bones deform a mesh - my_bone_blenParent = None - for my_bone in ob_bones: - my_bone_blenParent = my_bone.blenBone.parent - if my_bone_blenParent: - for my_bone_parent in ob_bones: - # Note 2.45rc2 you can compare bones normally - if my_bone_blenParent.name == my_bone_parent.blenName and my_bone.fbxArm == my_bone_parent.fbxArm: - my_bone.parent = my_bone_parent - break - - # Not used at the moment - # my_bone.calcRestMatrixLocal() - bone_deformer_count += len(my_bone.blenMeshes) - - del my_bone_blenParent - - - # Build blenObject -> fbxObject mapping - # this is needed for groups as well as fbxParenting - bpy.data.objects.tag = False - tmp_obmapping = {} - for ob_generic in ob_all_typegroups: - for ob_base in ob_generic: - ob_base.blenObject.tag = True - tmp_obmapping[ob_base.blenObject] = ob_base - - # Build Groups from objects we export - for blenGroup in bpy.data.groups: - fbxGroupName = None - for ob in blenGroup.objects: - if ob.tag: - if fbxGroupName == None: - fbxGroupName = sane_groupname(blenGroup) - groups.append((fbxGroupName, blenGroup)) - - tmp_obmapping[ob].fbxGroupNames.append(fbxGroupName) # also adds to the objects fbxGroupNames - - groups.sort() # not really needed - - # Assign parents using this mapping - for ob_generic in ob_all_typegroups: - for my_ob in ob_generic: - parent = my_ob.blenObject.parent - if parent and parent.tag: # does it exist and is it in the mapping - my_ob.fbxParent = tmp_obmapping[parent] - - - del tmp_obmapping - # Finished finding groups we use - - - materials = [(sane_matname(mat_tex_pair), mat_tex_pair) for mat_tex_pair in materials.iterkeys()] - textures = [(sane_texname(tex), tex) for tex in textures.iterkeys() if tex] - materials.sort() # sort by name - textures.sort() - - camera_count = 8 - file.write(''' - -; Object definitions -;------------------------------------------------------------------ - -Definitions: { - Version: 100 - Count: %i''' % (\ - 1+1+camera_count+\ - len(ob_meshes)+\ - len(ob_lights)+\ - len(ob_cameras)+\ - len(ob_arms)+\ - len(ob_null)+\ - len(ob_bones)+\ - bone_deformer_count+\ - len(materials)+\ - (len(textures)*2))) # add 1 for the root model 1 for global settings - - del bone_deformer_count - - file.write(''' - ObjectType: "Model" { - Count: %i - }''' % (\ - 1+camera_count+\ - len(ob_meshes)+\ - len(ob_lights)+\ - len(ob_cameras)+\ - len(ob_arms)+\ - len(ob_null)+\ - len(ob_bones))) # add 1 for the root model - - file.write(''' - ObjectType: "Geometry" { - Count: %i - }''' % len(ob_meshes)) - - if materials: - file.write(''' - ObjectType: "Material" { - Count: %i - }''' % len(materials)) - - if textures: - file.write(''' - ObjectType: "Texture" { - Count: %i - }''' % len(textures)) # add 1 for an empty tex - file.write(''' - ObjectType: "Video" { - Count: %i - }''' % len(textures)) # add 1 for an empty tex - - tmp = 0 - # Add deformer nodes - for my_mesh in ob_meshes: - if my_mesh.fbxArm: - tmp+=1 - - # Add subdeformers - for my_bone in ob_bones: - tmp += len(my_bone.blenMeshes) - - if tmp: - file.write(''' - ObjectType: "Deformer" { - Count: %i - }''' % tmp) - del tmp - - # we could avoid writing this possibly but for now just write it - - file.write(''' - ObjectType: "Pose" { - Count: 1 - }''') - - if groups: - file.write(''' - ObjectType: "GroupSelection" { - Count: %i - }''' % len(groups)) - - file.write(''' - ObjectType: "GlobalSettings" { - Count: 1 - } -}''') - - file.write(''' - -; Object properties -;------------------------------------------------------------------ - -Objects: {''') - - # To comply with other FBX FILES - write_camera_switch() - - # Write the null object - write_null(None, 'blend_root')# , GLOBAL_MATRIX) - - for my_null in ob_null: - write_null(my_null) - - for my_arm in ob_arms: - write_null(my_arm) - - for my_cam in ob_cameras: - write_camera(my_cam) - - for my_light in ob_lights: - write_light(my_light) - - for my_mesh in ob_meshes: - write_mesh(my_mesh) - - #for bonename, bone, obname, me, armob in ob_bones: - for my_bone in ob_bones: - write_bone(my_bone) - - write_camera_default() - - for matname, (mat, tex) in materials: - write_material(matname, mat) # We only need to have a material per image pair, but no need to write any image info into the material (dumb fbx standard) - - # each texture uses a video, odd - for texname, tex in textures: - write_video(texname, tex) - i = 0 - for texname, tex in textures: - write_texture(texname, tex, i) - i+=1 - - for groupname, group in groups: - write_group(groupname) - - # NOTE - c4d and motionbuilder dont need normalized weights, but deep-exploration 5 does and (max?) do. - - # Write armature modifiers - # TODO - add another MODEL? - because of this skin definition. - for my_mesh in ob_meshes: - if my_mesh.fbxArm: - write_deformer_skin(my_mesh.fbxName) - - # Get normalized weights for temorary use - if my_mesh.fbxBoneParent: - weights = None - else: - weights = meshNormalizedWeights(my_mesh.blenData) - - #for bonename, bone, obname, bone_mesh, armob in ob_bones: - for my_bone in ob_bones: - if me in my_bone.blenMeshes.itervalues(): - write_sub_deformer_skin(my_mesh, my_bone, weights) - - # Write pose's really weired, only needed when an armature and mesh are used together - # each by themselves dont need pose data. for now only pose meshes and bones - - file.write(''' - Pose: "Pose::BIND_POSES", "BindPose" { - Type: "BindPose" - Version: 100 - Properties60: { - } - NbPoseNodes: ''') - file.write(str(len(pose_items))) - - - for fbxName, matrix in pose_items: - file.write('\n\t\tPoseNode: {') - file.write('\n\t\t\tNode: "Model::%s"' % fbxName ) - if matrix: file.write('\n\t\t\tMatrix: %s' % mat4x4str(matrix)) - else: file.write('\n\t\t\tMatrix: %s' % mat4x4str(mtx4_identity)) - file.write('\n\t\t}') - - file.write('\n\t}') - - - # Finish Writing Objects - # Write global settings - file.write(''' - GlobalSettings: { - Version: 1000 - Properties60: { - Property: "UpAxis", "int", "",1 - Property: "UpAxisSign", "int", "",1 - Property: "FrontAxis", "int", "",2 - Property: "FrontAxisSign", "int", "",1 - Property: "CoordAxis", "int", "",0 - Property: "CoordAxisSign", "int", "",1 - Property: "UnitScaleFactor", "double", "",100 - } - } -''') - file.write('}') - - file.write(''' - -; Object relations -;------------------------------------------------------------------ - -Relations: {''') - - file.write('\n\tModel: "Model::blend_root", "Null" {\n\t}') - - for my_null in ob_null: - file.write('\n\tModel: "Model::%s", "Null" {\n\t}' % my_null.fbxName) - - for my_arm in ob_arms: - file.write('\n\tModel: "Model::%s", "Null" {\n\t}' % my_arm.fbxName) - - for my_mesh in ob_meshes: - file.write('\n\tModel: "Model::%s", "Mesh" {\n\t}' % my_mesh.fbxName) - - # TODO - limbs can have the same name for multiple armatures, should prefix. - #for bonename, bone, obname, me, armob in ob_bones: - for my_bone in ob_bones: - file.write('\n\tModel: "Model::%s", "Limb" {\n\t}' % my_bone.fbxName) - - for my_cam in ob_cameras: - file.write('\n\tModel: "Model::%s", "Camera" {\n\t}' % my_cam.fbxName) - - for my_light in ob_lights: - file.write('\n\tModel: "Model::%s", "Light" {\n\t}' % my_light.fbxName) - - file.write(''' - Model: "Model::Producer Perspective", "Camera" { - } - Model: "Model::Producer Top", "Camera" { - } - Model: "Model::Producer Bottom", "Camera" { - } - Model: "Model::Producer Front", "Camera" { - } - Model: "Model::Producer Back", "Camera" { - } - Model: "Model::Producer Right", "Camera" { - } - Model: "Model::Producer Left", "Camera" { - } - Model: "Model::Camera Switcher", "CameraSwitcher" { - }''') - - for matname, (mat, tex) in materials: - file.write('\n\tMaterial: "Material::%s", "" {\n\t}' % matname) - - if textures: - for texname, tex in textures: - file.write('\n\tTexture: "Texture::%s", "TextureVideoClip" {\n\t}' % texname) - for texname, tex in textures: - file.write('\n\tVideo: "Video::%s", "Clip" {\n\t}' % texname) - - # deformers - modifiers - for my_mesh in ob_meshes: - if my_mesh.fbxArm: - file.write('\n\tDeformer: "Deformer::Skin %s", "Skin" {\n\t}' % my_mesh.fbxName) - - #for bonename, bone, obname, me, armob in ob_bones: - for my_bone in ob_bones: - for fbxMeshObName in my_bone.blenMeshes: # .keys() - fbxMeshObName - # is this bone effecting a mesh? - file.write('\n\tDeformer: "SubDeformer::Cluster %s %s", "Cluster" {\n\t}' % (fbxMeshObName, my_bone.fbxName)) - - # This should be at the end - # file.write('\n\tPose: "Pose::BIND_POSES", "BindPose" {\n\t}') - - for groupname, group in groups: - file.write('\n\tGroupSelection: "GroupSelection::%s", "Default" {\n\t}' % groupname) - - file.write('\n}') - file.write(''' - -; Object connections -;------------------------------------------------------------------ - -Connections: {''') - - # NOTE - The FBX SDK dosnt care about the order but some importers DO! - # for instance, defining the material->mesh connection - # before the mesh->blend_root crashes cinema4d - - - # write the fake root node - file.write('\n\tConnect: "OO", "Model::blend_root", "Model::Scene"') - - for ob_generic in ob_all_typegroups: # all blender 'Object's we support - for my_ob in ob_generic: - if my_ob.fbxParent: - file.write('\n\tConnect: "OO", "Model::%s", "Model::%s"' % (my_ob.fbxName, my_ob.fbxParent.fbxName)) - else: - file.write('\n\tConnect: "OO", "Model::%s", "Model::blend_root"' % my_ob.fbxName) - - if materials: - for my_mesh in ob_meshes: - # Connect all materials to all objects, not good form but ok for now. - for mat, tex in my_mesh.blenMaterials: - if mat: mat_name = mat.name - else: mat_name = None - - if tex: tex_name = tex.name - else: tex_name = None - - file.write('\n\tConnect: "OO", "Material::%s", "Model::%s"' % (sane_name_mapping_mat[mat_name, tex_name], my_mesh.fbxName)) - - if textures: - for my_mesh in ob_meshes: - if my_mesh.blenTextures: - # file.write('\n\tConnect: "OO", "Texture::_empty_", "Model::%s"' % my_mesh.fbxName) - for tex in my_mesh.blenTextures: - if tex: - file.write('\n\tConnect: "OO", "Texture::%s", "Model::%s"' % (sane_name_mapping_tex[tex.name], my_mesh.fbxName)) - - for texname, tex in textures: - file.write('\n\tConnect: "OO", "Video::%s", "Texture::%s"' % (texname, texname)) - - for my_mesh in ob_meshes: - if my_mesh.fbxArm: - file.write('\n\tConnect: "OO", "Deformer::Skin %s", "Model::%s"' % (my_mesh.fbxName, my_mesh.fbxName)) - - #for bonename, bone, obname, me, armob in ob_bones: - for my_bone in ob_bones: - for fbxMeshObName in my_bone.blenMeshes: # .keys() - file.write('\n\tConnect: "OO", "SubDeformer::Cluster %s %s", "Deformer::Skin %s"' % (fbxMeshObName, my_bone.fbxName, fbxMeshObName)) - - # limbs -> deformers - # for bonename, bone, obname, me, armob in ob_bones: - for my_bone in ob_bones: - for fbxMeshObName in my_bone.blenMeshes: # .keys() - file.write('\n\tConnect: "OO", "Model::%s", "SubDeformer::Cluster %s %s"' % (my_bone.fbxName, fbxMeshObName, my_bone.fbxName)) - - - #for bonename, bone, obname, me, armob in ob_bones: - for my_bone in ob_bones: - # Always parent to armature now - if my_bone.parent: - file.write('\n\tConnect: "OO", "Model::%s", "Model::%s"' % (my_bone.fbxName, my_bone.parent.fbxName) ) - else: - # the armature object is written as an empty and all root level bones connect to it - file.write('\n\tConnect: "OO", "Model::%s", "Model::%s"' % (my_bone.fbxName, my_bone.fbxArm.fbxName) ) - - # groups - if groups: - for ob_generic in ob_all_typegroups: - for ob_base in ob_generic: - for fbxGroupName in ob_base.fbxGroupNames: - file.write('\n\tConnect: "OO", "Model::%s", "GroupSelection::%s"' % (ob_base.fbxName, fbxGroupName)) - - for my_arm in ob_arms: - file.write('\n\tConnect: "OO", "Model::%s", "Model::blend_root"' % my_arm.fbxName) - - file.write('\n}') - - - # Needed for scene footer as well as animation - render = sce.render - - # from the FBX sdk - #define KTIME_ONE_SECOND KTime (K_LONGLONG(46186158000)) - def fbx_time(t): - # 0.5 + val is the same as rounding. - return int(0.5 + ((t/fps) * 46186158000)) - - fps = float(render.fps) - start = render.sFrame - end = render.eFrame - if end < start: start, end = end, start - if start==end: ANIM_ENABLE = False - - # animations for these object types - ob_anim_lists = ob_bones, ob_meshes, ob_null, ob_cameras, ob_lights, ob_arms - - if ANIM_ENABLE and [tmp for tmp in ob_anim_lists if tmp]: - - frame_orig = Blender.Get('curframe') - - if ANIM_OPTIMIZE: - ANIM_OPTIMIZE_PRECISSION_FLOAT = 0.1 ** ANIM_OPTIMIZE_PRECISSION - - # default action, when no actions are avaioable - tmp_actions = [None] # None is the default action - blenActionDefault = None - action_lastcompat = None - - if ANIM_ACTION_ALL: - bpy.data.actions.tag = False - tmp_actions = list(bpy.data.actions) - - - # find which actions are compatible with the armatures - # blenActions is not yet initialized so do it now. - tmp_act_count = 0 - for my_arm in ob_arms: - - # get the default name - if not blenActionDefault: - blenActionDefault = my_arm.blenAction - - arm_bone_names = set([my_bone.blenName for my_bone in my_arm.fbxBones]) - - for action in tmp_actions: - - action_chan_names = arm_bone_names.intersection( set(action.getChannelNames()) ) - - if action_chan_names: # at least one channel matches. - my_arm.blenActionList.append(action) - action.tag = True - tmp_act_count += 1 - - # incase there is no actions applied to armatures - action_lastcompat = action - - if tmp_act_count: - # unlikely to ever happen but if no actions applied to armatures, just use the last compatible armature. - if not blenActionDefault: - blenActionDefault = action_lastcompat - - del action_lastcompat - - file.write(''' -;Takes and animation section -;---------------------------------------------------- - -Takes: {''') - - if blenActionDefault: - file.write('\n\tCurrent: "%s"' % sane_takename(blenActionDefault)) - else: - file.write('\n\tCurrent: "Default Take"') - - for blenAction in tmp_actions: - # we have tagged all actious that are used be selected armatures - if blenAction: - if blenAction.tag: - print '\taction: "%s" exporting...' % blenAction.name - else: - print '\taction: "%s" has no armature using it, skipping' % blenAction.name - continue - - if blenAction == None: - # Warning, this only accounts for tmp_actions being [None] - file.write('\n\tTake: "Default Take" {') - act_start = start - act_end = end - else: - # use existing name - if blenAction == blenActionDefault: # have we alredy got the name - file.write('\n\tTake: "%s" {' % sane_name_mapping_take[blenAction.name]) - else: - file.write('\n\tTake: "%s" {' % sane_takename(blenAction)) - - tmp = blenAction.getFrameNumbers() - if tmp: - act_start = min(tmp) - act_end = max(tmp) - del tmp - else: - # Fallback on this, theres not much else we can do? :/ - # when an action has no length - act_start = start - act_end = end - - # Set the action active - for my_bone in ob_arms: - if blenAction in my_bone.blenActionList: - ob.action = blenAction - # print '\t\tSetting Action!', blenAction - # sce.update(1) - - file.write('\n\t\tFileName: "Default_Take.tak"') # ??? - not sure why this is needed - file.write('\n\t\tLocalTime: %i,%i' % (fbx_time(act_start-1), fbx_time(act_end-1))) # ??? - not sure why this is needed - file.write('\n\t\tReferenceTime: %i,%i' % (fbx_time(act_start-1), fbx_time(act_end-1))) # ??? - not sure why this is needed - - file.write(''' - - ;Models animation - ;----------------------------------------------------''') - - - # set pose data for all bones - # do this here incase the action changes - ''' - for my_bone in ob_bones: - my_bone.flushAnimData() - ''' - i = act_start - while i <= act_end: - Blender.Set('curframe', i) - for ob_generic in ob_anim_lists: - for my_ob in ob_generic: - #Blender.Window.RedrawAll() - if ob_generic == ob_meshes and my_ob.fbxArm: - # We cant animate armature meshes! - pass - else: - my_ob.setPoseFrame(i) - - i+=1 - - - #for bonename, bone, obname, me, armob in ob_bones: - for ob_generic in (ob_bones, ob_meshes, ob_null, ob_cameras, ob_lights, ob_arms): - - for my_ob in ob_generic: - - if ob_generic == ob_meshes and my_ob.fbxArm: - # do nothing, - pass - else: - - file.write('\n\t\tModel: "Model::%s" {' % my_ob.fbxName) # ??? - not sure why this is needed - file.write('\n\t\t\tVersion: 1.1') - file.write('\n\t\t\tChannel: "Transform" {') - - context_bone_anim_mats = [ (my_ob.getAnimParRelMatrix(frame), my_ob.getAnimParRelMatrixRot(frame)) for frame in xrange(act_start, act_end+1) ] - - # ---------------- - # ---------------- - for TX_LAYER, TX_CHAN in enumerate('TRS'): # transform, rotate, scale - - if TX_CHAN=='T': context_bone_anim_vecs = [mtx[0].translationPart() for mtx in context_bone_anim_mats] - elif TX_CHAN=='S': context_bone_anim_vecs = [mtx[0].scalePart() for mtx in context_bone_anim_mats] - elif TX_CHAN=='R': - # Was.... - # elif TX_CHAN=='R': context_bone_anim_vecs = [mtx[1].toEuler() for mtx in context_bone_anim_mats] - # - # ...but we need to use the previous euler for compatible conversion. - context_bone_anim_vecs = [] - prev_eul = None - for mtx in context_bone_anim_mats: - if prev_eul: prev_eul = mtx[1].toEuler(prev_eul) - else: prev_eul = mtx[1].toEuler() - context_bone_anim_vecs.append(prev_eul) - - file.write('\n\t\t\t\tChannel: "%s" {' % TX_CHAN) # translation - - for i in xrange(3): - # Loop on each axis of the bone - file.write('\n\t\t\t\t\tChannel: "%s" {'% ('XYZ'[i])) # translation - file.write('\n\t\t\t\t\t\tDefault: %.15f' % context_bone_anim_vecs[0][i] ) - file.write('\n\t\t\t\t\t\tKeyVer: 4005') - - if not ANIM_OPTIMIZE: - # Just write all frames, simple but in-eficient - file.write('\n\t\t\t\t\t\tKeyCount: %i' % (1 + act_end - act_start)) - file.write('\n\t\t\t\t\t\tKey: ') - frame = act_start - while frame <= act_end: - if frame!=act_start: - file.write(',') - - # Curve types are 'C,n' for constant, 'L' for linear - # C,n is for bezier? - linear is best for now so we can do simple keyframe removal - file.write('\n\t\t\t\t\t\t\t%i,%.15f,L' % (fbx_time(frame-1), context_bone_anim_vecs[frame-act_start][i] )) - frame+=1 - else: - # remove unneeded keys, j is the frame, needed when some frames are removed. - context_bone_anim_keys = [ (vec[i], j) for j, vec in enumerate(context_bone_anim_vecs) ] - - # last frame to fisrt frame, missing 1 frame on either side. - # removeing in a backwards loop is faster - #for j in xrange( (act_end-act_start)-1, 0, -1 ): - # j = (act_end-act_start)-1 - j = len(context_bone_anim_keys)-2 - while j > 0 and len(context_bone_anim_keys) > 2: - # print j, len(context_bone_anim_keys) - # Is this key the same as the ones next to it? - - # co-linear horizontal... - if abs(context_bone_anim_keys[j][0] - context_bone_anim_keys[j-1][0]) < ANIM_OPTIMIZE_PRECISSION_FLOAT and\ - abs(context_bone_anim_keys[j][0] - context_bone_anim_keys[j+1][0]) < ANIM_OPTIMIZE_PRECISSION_FLOAT: - - del context_bone_anim_keys[j] - - else: - frame_range = float(context_bone_anim_keys[j+1][1] - context_bone_anim_keys[j-1][1]) - frame_range_fac1 = (context_bone_anim_keys[j+1][1] - context_bone_anim_keys[j][1]) / frame_range - frame_range_fac2 = 1.0 - frame_range_fac1 - - if abs(((context_bone_anim_keys[j-1][0]*frame_range_fac1 + context_bone_anim_keys[j+1][0]*frame_range_fac2)) - context_bone_anim_keys[j][0]) < ANIM_OPTIMIZE_PRECISSION_FLOAT: - del context_bone_anim_keys[j] - else: - j-=1 - - # keep the index below the list length - if j > len(context_bone_anim_keys)-2: - j = len(context_bone_anim_keys)-2 - - if len(context_bone_anim_keys) == 2 and context_bone_anim_keys[0][0] == context_bone_anim_keys[1][0]: - # This axis has no moton, its okay to skip KeyCount and Keys in this case - pass - else: - # We only need to write these if there is at least one - file.write('\n\t\t\t\t\t\tKeyCount: %i' % len(context_bone_anim_keys)) - file.write('\n\t\t\t\t\t\tKey: ') - for val, frame in context_bone_anim_keys: - if frame != context_bone_anim_keys[0][1]: # not the first - file.write(',') - # frame is alredy one less then blenders frame - file.write('\n\t\t\t\t\t\t\t%i,%.15f,L' % (fbx_time(frame), val )) - - if i==0: file.write('\n\t\t\t\t\t\tColor: 1,0,0') - elif i==1: file.write('\n\t\t\t\t\t\tColor: 0,1,0') - elif i==2: file.write('\n\t\t\t\t\t\tColor: 0,0,1') - - file.write('\n\t\t\t\t\t}') - file.write('\n\t\t\t\t\tLayerType: %i' % (TX_LAYER+1) ) - file.write('\n\t\t\t\t}') - - # --------------- - - file.write('\n\t\t\t}') - file.write('\n\t\t}') - - # end the take - file.write('\n\t}') - - # end action loop. set original actions - # do this after every loop incase actions effect eachother. - for my_bone in ob_arms: - my_bone.blenObject.action = my_bone.blenAction - - file.write('\n}') - - Blender.Set('curframe', frame_orig) - - else: - # no animation - file.write('\n;Takes and animation section') - file.write('\n;----------------------------------------------------') - file.write('\n') - file.write('\nTakes: {') - file.write('\n\tCurrent: ""') - file.write('\n}') - - - # write meshes animation - #for obname, ob, mtx, me, mats, arm, armname in ob_meshes: - - - # Clear mesh data Only when writing with modifiers applied - for me in meshes_to_clear: - me.verts = None - - - - # --------------------------- Footer - if world: - has_mist = world.mode & 1 - mist_intense, mist_start, mist_end, mist_height = world.mist - world_hor = world.hor - else: - has_mist = mist_intense = mist_start = mist_end = mist_height = 0 - world_hor = 0,0,0 - - file.write('\n;Version 5 settings') - file.write('\n;------------------------------------------------------------------') - file.write('\n') - file.write('\nVersion5: {') - file.write('\n\tAmbientRenderSettings: {') - file.write('\n\t\tVersion: 101') - file.write('\n\t\tAmbientLightColor: %.1f,%.1f,%.1f,0' % tuple(world_amb)) - file.write('\n\t}') - file.write('\n\tFogOptions: {') - file.write('\n\t\tFlogEnable: %i' % has_mist) - file.write('\n\t\tFogMode: 0') - file.write('\n\t\tFogDensity: %.3f' % mist_intense) - file.write('\n\t\tFogStart: %.3f' % mist_start) - file.write('\n\t\tFogEnd: %.3f' % mist_end) - file.write('\n\t\tFogColor: %.1f,%.1f,%.1f,1' % tuple(world_hor)) - file.write('\n\t}') - file.write('\n\tSettings: {') - file.write('\n\t\tFrameRate: "%i"' % int(fps)) - file.write('\n\t\tTimeFormat: 1') - file.write('\n\t\tSnapOnFrames: 0') - file.write('\n\t\tReferenceTimeIndex: -1') - file.write('\n\t\tTimeLineStartTime: %i' % fbx_time(start-1)) - file.write('\n\t\tTimeLineStopTime: %i' % fbx_time(end-1)) - file.write('\n\t}') - file.write('\n\tRendererSetting: {') - file.write('\n\t\tDefaultCamera: "Producer Perspective"') - file.write('\n\t\tDefaultViewingMode: 0') - file.write('\n\t}') - file.write('\n}') - file.write('\n') - - # Incase sombody imports this, clean up by clearing global dicts - sane_name_mapping_ob.clear() - sane_name_mapping_mat.clear() - sane_name_mapping_tex.clear() - - ob_arms[:] = [] - ob_bones[:] = [] - ob_cameras[:] = [] - ob_lights[:] = [] - ob_meshes[:] = [] - ob_null[:] = [] - - - # copy images if enabled - if EXP_IMAGE_COPY: - copy_images( basepath, [ tex[1] for tex in textures if tex[1] != None ]) - - print 'export finished in %.4f sec.' % (Blender.sys.time() - start_time) - return True - - -# -------------------------------------------- -# UI Function - not a part of the exporter. -# this is to seperate the user interface from the rest of the exporter. -from Blender import Draw, Window -EVENT_NONE = 0 -EVENT_EXIT = 1 -EVENT_REDRAW = 2 -EVENT_FILESEL = 3 - -GLOBALS = {} - -# export opts - -def do_redraw(e,v): GLOBALS['EVENT'] = e - -# toggle between these 2, only allow one on at once -def do_obs_sel(e,v): - GLOBALS['EVENT'] = e - GLOBALS['EXP_OBS_SCENE'].val = 0 - GLOBALS['EXP_OBS_SELECTED'].val = 1 - -def do_obs_sce(e,v): - GLOBALS['EVENT'] = e - GLOBALS['EXP_OBS_SCENE'].val = 1 - GLOBALS['EXP_OBS_SELECTED'].val = 0 - -def do_obs_sce(e,v): - GLOBALS['EVENT'] = e - GLOBALS['EXP_OBS_SCENE'].val = 1 - GLOBALS['EXP_OBS_SELECTED'].val = 0 - -def do_batch_type_grp(e,v): - GLOBALS['EVENT'] = e - GLOBALS['BATCH_GROUP'].val = 1 - GLOBALS['BATCH_SCENE'].val = 0 - -def do_batch_type_sce(e,v): - GLOBALS['EVENT'] = e - GLOBALS['BATCH_GROUP'].val = 0 - GLOBALS['BATCH_SCENE'].val = 1 - -def do_anim_act_all(e,v): - GLOBALS['EVENT'] = e - GLOBALS['ANIM_ACTION_ALL'][0].val = 1 - GLOBALS['ANIM_ACTION_ALL'][1].val = 0 - -def do_anim_act_cur(e,v): - if GLOBALS['BATCH_ENABLE'].val and GLOBALS['BATCH_GROUP'].val: - Draw.PupMenu('Warning%t|Cant use this with batch export group option') - else: - GLOBALS['EVENT'] = e - GLOBALS['ANIM_ACTION_ALL'][0].val = 0 - GLOBALS['ANIM_ACTION_ALL'][1].val = 1 - -def fbx_ui_exit(e,v): - GLOBALS['EVENT'] = e - -def do_help(e,v): - url = 'http://wiki.blender.org/index.php/Scripts/Manual/Export/autodesk_fbx' - print 'Trying to open web browser with documentation at this address...' - print '\t' + url - - try: - import webbrowser - webbrowser.open(url) - except: - Blender.Draw.PupMenu("Error%t|Opening a webbrowser requires a full python installation") - print '...could not open a browser window.' - - - -# run when export is pressed -#def fbx_ui_write(e,v): -def fbx_ui_write(filename): - - # Dont allow overwriting files when saving normally - if not GLOBALS['BATCH_ENABLE'].val: - if not BPyMessages.Warning_SaveOver(filename): - return - - GLOBALS['EVENT'] = EVENT_EXIT - - # Keep the order the same as above for simplicity - # the [] is a dummy arg used for objects - - Blender.Window.WaitCursor(1) - - # Make the matrix - GLOBAL_MATRIX = mtx4_identity - GLOBAL_MATRIX[0][0] = GLOBAL_MATRIX[1][1] = GLOBAL_MATRIX[2][2] = GLOBALS['_SCALE'].val - if GLOBALS['_XROT90'].val: GLOBAL_MATRIX = GLOBAL_MATRIX * mtx4_x90n - if GLOBALS['_YROT90'].val: GLOBAL_MATRIX = GLOBAL_MATRIX * mtx4_y90n - if GLOBALS['_ZROT90'].val: GLOBAL_MATRIX = GLOBAL_MATRIX * mtx4_z90n - - ret = write(\ - filename, None,\ - GLOBALS['EXP_OBS_SELECTED'].val,\ - GLOBALS['EXP_MESH'].val,\ - GLOBALS['EXP_MESH_APPLY_MOD'].val,\ - GLOBALS['EXP_MESH_HQ_NORMALS'].val,\ - GLOBALS['EXP_ARMATURE'].val,\ - GLOBALS['EXP_LAMP'].val,\ - GLOBALS['EXP_CAMERA'].val,\ - GLOBALS['EXP_EMPTY'].val,\ - GLOBALS['EXP_IMAGE_COPY'].val,\ - GLOBAL_MATRIX,\ - GLOBALS['ANIM_ENABLE'].val,\ - GLOBALS['ANIM_OPTIMIZE'].val,\ - GLOBALS['ANIM_OPTIMIZE_PRECISSION'].val,\ - GLOBALS['ANIM_ACTION_ALL'][0].val,\ - GLOBALS['BATCH_ENABLE'].val,\ - GLOBALS['BATCH_GROUP'].val,\ - GLOBALS['BATCH_SCENE'].val,\ - GLOBALS['BATCH_FILE_PREFIX'].val,\ - GLOBALS['BATCH_OWN_DIR'].val,\ - ) - - Blender.Window.WaitCursor(0) - GLOBALS.clear() - - if ret == False: - Draw.PupMenu('Error%t|Path cannot be written to!') - - -def fbx_ui(): - # Only to center the UI - x,y = GLOBALS['MOUSE'] - x-=180; y-=0 # offset... just to get it centered - - Draw.Label('Export Objects...', x+20,y+165, 200, 20) - - if not GLOBALS['BATCH_ENABLE'].val: - Draw.BeginAlign() - GLOBALS['EXP_OBS_SELECTED'] = Draw.Toggle('Selected Objects', EVENT_REDRAW, x+20, y+145, 160, 20, GLOBALS['EXP_OBS_SELECTED'].val, 'Export selected objects on visible layers', do_obs_sel) - GLOBALS['EXP_OBS_SCENE'] = Draw.Toggle('Scene Objects', EVENT_REDRAW, x+180, y+145, 160, 20, GLOBALS['EXP_OBS_SCENE'].val, 'Export all objects in this scene', do_obs_sce) - Draw.EndAlign() - - Draw.BeginAlign() - GLOBALS['_SCALE'] = Draw.Number('Scale:', EVENT_NONE, x+20, y+120, 140, 20, GLOBALS['_SCALE'].val, 0.01, 1000.0, 'Scale all data, (Note! some imports dont support scaled armatures)') - GLOBALS['_XROT90'] = Draw.Toggle('Rot X90', EVENT_NONE, x+160, y+120, 60, 20, GLOBALS['_XROT90'].val, 'Rotate all objects 90 degrese about the X axis') - GLOBALS['_YROT90'] = Draw.Toggle('Rot Y90', EVENT_NONE, x+220, y+120, 60, 20, GLOBALS['_YROT90'].val, 'Rotate all objects 90 degrese about the Y axis') - GLOBALS['_ZROT90'] = Draw.Toggle('Rot Z90', EVENT_NONE, x+280, y+120, 60, 20, GLOBALS['_ZROT90'].val, 'Rotate all objects 90 degrese about the Z axis') - Draw.EndAlign() - - y -= 35 - - Draw.BeginAlign() - GLOBALS['EXP_EMPTY'] = Draw.Toggle('Empty', EVENT_NONE, x+20, y+120, 60, 20, GLOBALS['EXP_EMPTY'].val, 'Export empty objects') - GLOBALS['EXP_CAMERA'] = Draw.Toggle('Camera', EVENT_NONE, x+80, y+120, 60, 20, GLOBALS['EXP_CAMERA'].val, 'Export camera objects') - GLOBALS['EXP_LAMP'] = Draw.Toggle('Lamp', EVENT_NONE, x+140, y+120, 60, 20, GLOBALS['EXP_LAMP'].val, 'Export lamp objects') - GLOBALS['EXP_ARMATURE'] = Draw.Toggle('Armature', EVENT_NONE, x+200, y+120, 60, 20, GLOBALS['EXP_ARMATURE'].val, 'Export armature objects') - GLOBALS['EXP_MESH'] = Draw.Toggle('Mesh', EVENT_REDRAW, x+260, y+120, 80, 20, GLOBALS['EXP_MESH'].val, 'Export mesh objects', do_redraw) #, do_axis_z) - Draw.EndAlign() - - if GLOBALS['EXP_MESH'].val: - # below mesh but - Draw.BeginAlign() - GLOBALS['EXP_MESH_APPLY_MOD'] = Draw.Toggle('Modifiers', EVENT_NONE, x+260, y+100, 80, 20, GLOBALS['EXP_MESH_APPLY_MOD'].val, 'Apply modifiers to mesh objects') #, do_axis_z) - GLOBALS['EXP_MESH_HQ_NORMALS'] = Draw.Toggle('HQ Normals', EVENT_NONE, x+260, y+80, 80, 20, GLOBALS['EXP_MESH_HQ_NORMALS'].val, 'Generate high quality normals') #, do_axis_z) - Draw.EndAlign() - - GLOBALS['EXP_IMAGE_COPY'] = Draw.Toggle('Copy Image Files', EVENT_NONE, x+20, y+80, 160, 20, GLOBALS['EXP_IMAGE_COPY'].val, 'Copy image files to the destination path') #, do_axis_z) - - - Draw.Label('Export Armature Animation...', x+20,y+45, 300, 20) - - GLOBALS['ANIM_ENABLE'] = Draw.Toggle('Enable Animation', EVENT_REDRAW, x+20, y+25, 160, 20, GLOBALS['ANIM_ENABLE'].val, 'Export keyframe animation', do_redraw) - if GLOBALS['ANIM_ENABLE'].val: - Draw.BeginAlign() - GLOBALS['ANIM_OPTIMIZE'] = Draw.Toggle('Optimize Keyframes', EVENT_REDRAW, x+20, y+0, 160, 20, GLOBALS['ANIM_OPTIMIZE'].val, 'Remove double keyframes', do_redraw) - if GLOBALS['ANIM_OPTIMIZE'].val: - GLOBALS['ANIM_OPTIMIZE_PRECISSION'] = Draw.Number('Precission: ', EVENT_NONE, x+180, y+0, 160, 20, GLOBALS['ANIM_OPTIMIZE_PRECISSION'].val, 1, 16, 'Tolerence for comparing double keyframes (higher for greater accuracy)') - Draw.EndAlign() - - Draw.BeginAlign() - GLOBALS['ANIM_ACTION_ALL'][1] = Draw.Toggle('Current Action', EVENT_REDRAW, x+20, y-25, 160, 20, GLOBALS['ANIM_ACTION_ALL'][1].val, 'Use actions currently applied to the armatures (use scene start/end frame)', do_anim_act_cur) - GLOBALS['ANIM_ACTION_ALL'][0] = Draw.Toggle('All Actions', EVENT_REDRAW, x+180,y-25, 160, 20, GLOBALS['ANIM_ACTION_ALL'][0].val, 'Use all actions for armatures', do_anim_act_all) - Draw.EndAlign() - - - Draw.Label('Export Batch...', x+20,y-60, 300, 20) - GLOBALS['BATCH_ENABLE'] = Draw.Toggle('Enable Batch', EVENT_REDRAW, x+20, y-80, 160, 20, GLOBALS['BATCH_ENABLE'].val, 'Automate exporting multiple scenes or groups to files', do_redraw) - - if GLOBALS['BATCH_ENABLE'].val: - Draw.BeginAlign() - GLOBALS['BATCH_GROUP'] = Draw.Toggle('Group > File', EVENT_REDRAW, x+20, y-105, 160, 20, GLOBALS['BATCH_GROUP'].val, 'Export each group as an FBX file', do_batch_type_grp) - GLOBALS['BATCH_SCENE'] = Draw.Toggle('Scene > File', EVENT_REDRAW, x+180, y-105, 160, 20, GLOBALS['BATCH_SCENE'].val, 'Export each scene as an FBX file', do_batch_type_sce) - - # Own dir requires OS module - if os: - GLOBALS['BATCH_OWN_DIR'] = Draw.Toggle('Own Dir', EVENT_NONE, x+20, y-125, 80, 20, GLOBALS['BATCH_OWN_DIR'].val, 'Create a dir for each exported file') - GLOBALS['BATCH_FILE_PREFIX'] = Draw.String('Prefix: ', EVENT_NONE, x+100, y-125, 240, 20, GLOBALS['BATCH_FILE_PREFIX'].val, 64, 'Prefix each file with this name ') - else: - GLOBALS['BATCH_FILE_PREFIX'] = Draw.String('Prefix: ', EVENT_NONE, x+20, y-125, 320, 20, GLOBALS['BATCH_FILE_PREFIX'].val, 64, 'Prefix each file with this name ') - - - Draw.EndAlign() - - #y+=80 - - ''' - Draw.BeginAlign() - GLOBALS['FILENAME'] = Draw.String('path: ', EVENT_NONE, x+20, y-170, 300, 20, GLOBALS['FILENAME'].val, 64, 'Prefix each file with this name ') - Draw.PushButton('..', EVENT_FILESEL, x+320, y-170, 20, 20, 'Select the path', do_redraw) - ''' - # Until batch is added - # - - - #Draw.BeginAlign() - Draw.PushButton('Online Help', EVENT_REDRAW, x+20, y-160, 100, 20, 'Open online help in a browser window', do_help) - Draw.PushButton('Cancel', EVENT_EXIT, x+130, y-160, 100, 20, 'Exit the exporter', fbx_ui_exit) - Draw.PushButton('Export', EVENT_FILESEL, x+240, y-160, 100, 20, 'Export the fbx file', do_redraw) - - #Draw.PushButton('Export', EVENT_EXIT, x+180, y-160, 160, 20, 'Export the fbx file', fbx_ui_write) - #Draw.EndAlign() - - # exit when mouse out of the view? - # GLOBALS['EVENT'] = EVENT_EXIT - -#def write_ui(filename): -def write_ui(): - - # globals - GLOBALS['EVENT'] = EVENT_REDRAW - #GLOBALS['MOUSE'] = Window.GetMouseCoords() - GLOBALS['MOUSE'] = [i/2 for i in Window.GetScreenSize()] - GLOBALS['FILENAME'] = '' - ''' - # IF called from the fileselector - if filename == None: - GLOBALS['FILENAME'] = filename # Draw.Create(Blender.sys.makename(ext='.fbx')) - else: - GLOBALS['FILENAME'].val = filename - ''' - GLOBALS['EXP_OBS_SELECTED'] = Draw.Create(1) # dont need 2 variables but just do this for clarity - GLOBALS['EXP_OBS_SCENE'] = Draw.Create(0) - - GLOBALS['EXP_MESH'] = Draw.Create(1) - GLOBALS['EXP_MESH_APPLY_MOD'] = Draw.Create(1) - GLOBALS['EXP_MESH_HQ_NORMALS'] = Draw.Create(0) - GLOBALS['EXP_ARMATURE'] = Draw.Create(1) - GLOBALS['EXP_LAMP'] = Draw.Create(1) - GLOBALS['EXP_CAMERA'] = Draw.Create(1) - GLOBALS['EXP_EMPTY'] = Draw.Create(1) - GLOBALS['EXP_IMAGE_COPY'] = Draw.Create(0) - # animation opts - GLOBALS['ANIM_ENABLE'] = Draw.Create(1) - GLOBALS['ANIM_OPTIMIZE'] = Draw.Create(1) - GLOBALS['ANIM_OPTIMIZE_PRECISSION'] = Draw.Create(4) # decimal places - GLOBALS['ANIM_ACTION_ALL'] = [Draw.Create(0), Draw.Create(1)] # not just the current action - - # batch export options - GLOBALS['BATCH_ENABLE'] = Draw.Create(0) - GLOBALS['BATCH_GROUP'] = Draw.Create(1) # cant have both of these enabled at once. - GLOBALS['BATCH_SCENE'] = Draw.Create(0) # see above - GLOBALS['BATCH_FILE_PREFIX'] = Draw.Create(Blender.sys.makename(ext='_').split('\\')[-1].split('/')[-1]) - GLOBALS['BATCH_OWN_DIR'] = Draw.Create(0) - # done setting globals - - # Used by the user interface - GLOBALS['_SCALE'] = Draw.Create(1.0) - GLOBALS['_XROT90'] = Draw.Create(True) - GLOBALS['_YROT90'] = Draw.Create(False) - GLOBALS['_ZROT90'] = Draw.Create(False) - - # best not do move the cursor - # Window.SetMouseCoords(*[i/2 for i in Window.GetScreenSize()]) - - # hack so the toggle buttons redraw. this is not nice at all - while GLOBALS['EVENT'] != EVENT_EXIT: - - if GLOBALS['BATCH_ENABLE'].val and GLOBALS['BATCH_GROUP'].val and GLOBALS['ANIM_ACTION_ALL'][1].val: - #Draw.PupMenu("Warning%t|Cant batch export groups with 'Current Action' ") - GLOBALS['ANIM_ACTION_ALL'][0].val = 1 - GLOBALS['ANIM_ACTION_ALL'][1].val = 0 - - if GLOBALS['EVENT'] == EVENT_FILESEL: - if GLOBALS['BATCH_ENABLE'].val: - txt = 'Batch FBX Dir' - name = Blender.sys.expandpath('//') - else: - txt = 'Export FBX' - name = Blender.sys.makename(ext='.fbx') - - Blender.Window.FileSelector(fbx_ui_write, txt, name) - #fbx_ui_write('/test.fbx') - break - - Draw.UIBlock(fbx_ui, 0) - - - # GLOBALS.clear() -#test = [write_ui] -if __name__ == '__main__': - # Cant call the file selector first because of a bug in the interface that crashes it. - # Blender.Window.FileSelector(write_ui, 'Export FBX', Blender.sys.makename(ext='.fbx')) - #write('/scratch/test.fbx') - #write_ui('/scratch/test.fbx') - - if not set: - Draw.PupMenu('Error%t|A full install of python2.3 or python 2.4+ is needed to run this script.') - else: - write_ui() diff --git a/release/scripts/export_lightwave_motion.py b/release/scripts/export_lightwave_motion.py deleted file mode 100644 index 562e44f3a2b..00000000000 --- a/release/scripts/export_lightwave_motion.py +++ /dev/null @@ -1,157 +0,0 @@ -#!BPY - -""" Registration info for Blender menus: <- these words are ignored -Name: 'Lightwave Motion (.mot)...' -Blender: 241 -Group: 'Export' -Tip: 'Export Loc Rot Size chanels to a Lightwave .mot file' -""" - -__author__ = "Daniel Salazar (ZanQdo)" -__url__ = ("blender", "blenderartists.org", -"e-mail: zanqdo@gmail.com") -__version__ = "16/04/08" - -__bpydoc__ = """\ -This script exports the selected object's motion channels to Lightwave -motion files (.mot). - -Usage: -Run the script with one or more objects selected (any kind), frames exported -are between Start and End frames in Render buttons. - -""" - -# $Id$ -# -------------------------------------------------------------------------- -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Copyright (C) 2003, 2004: A Vanpoucke -# -# 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 ***** -# -------------------------------------------------------------------------- -import Blender as B -import math as M -#------------------------------------ -#Declarados: -TotalCanales = 9 -#------------------------------------ - -def FuncionPrincipal (Dir): - B.Window.WaitCursor(1) - ObjSelect = B.Object.GetSelected() - - if not ObjSelect: - B.Draw.PupMenu('Select 1 or more objects, aborting.') - return - - if not Dir.lower().endswith('.mot'): - Dir += '.mot' - - - SC = B.Scene.GetCurrent() - SCR = SC.getRenderingContext() - - for ob in ObjSelect: - origName= NombreObjeto= ob.name - print '----\nExporting Object "%s" motion file...' % origName - - FrameA = B.Get('curframe') - FrameP = B.Get('staframe') - FrameF = B.Get('endframe') - - FrameRate = float(SCR.framesPerSec()) - - #--------------------------------------------- - - # Replace danger characters by '_' - for ch in ' /\\~!@#$%^&*()+=[];\':",./<>?\t\r\n': - NombreObjeto = NombreObjeto.replace(ch, '_') - - # Check for file path extension - if len(ObjSelect) > 1: - DirN= '%s_%s.mot' % (Dir[:-4], NombreObjeto) - else: - DirN= Dir - - # Open the file - File = open(DirN,'w') - File.write ('LWMO\n3\n\n') # 3 is the version number. - - # number of channels - File.write ('NumChannels %i\n' % TotalCanales) - - # ---------------------------- - # Main Cycle - - def CicloPrimario(NumCanal): - B.Set('curframe', FrameP) - - File.write ('Channel %i\n{ Envelope\n %i\n' % (NumCanal, (FrameF - FrameP + 1))) - - FrameA = FrameP - while FrameA < (FrameF + 1): - - B.Set('curframe', FrameA) - - mat= ob.mat # Worldspace matrix - - if NumCanal == 0: - Val = mat.translationPart().x - elif NumCanal == 1: - Val = mat.translationPart().z - elif NumCanal == 2: - Val = mat.translationPart().y - elif NumCanal == 3: - Val = M.radians (-mat.toEuler().z) - elif NumCanal == 4: - Val = M.radians (-mat.toEuler().x) - elif NumCanal == 5: - Val = M.radians (-mat.toEuler().y) - elif NumCanal == 6: - Val = mat.scalePart().x - elif NumCanal == 7: - Val = mat.scalePart().z - elif NumCanal == 8: - Val = mat.scalePart().y - File.write (' Key %f %f 3 0 0 0 0 0 0\n' % (Val, (FrameA/FrameRate))) - - FrameA += 1 - # Ending Stuff - File.write (' Behaviors 1 1\n}\n') - - NumObjetoActual = len(ObjSelect) - Iteraciones = 0 - ProgBarVal = 0.0 - while Iteraciones < TotalCanales: - CicloPrimario(Iteraciones) - - # Start Progress Bar - B.Window.DrawProgressBar(ProgBarVal, origName) - ProgBarVal = (float(Iteraciones) / TotalCanales) * 0.98 - Iteraciones += 1 - - B.Window.DrawProgressBar(1.0, '') # Done - print '\nDone, %s motion file location is:\n%s\n' % (origName, DirN) - B.Window.WaitCursor(0) - -# Check if there are selected objects -def main(): - B.Window.FileSelector(FuncionPrincipal, "Write .mot File", B.sys.makename(ext='.mot')) - -if __name__=='__main__': - main() diff --git a/release/scripts/export_m3g.py b/release/scripts/export_m3g.py deleted file mode 100644 index c74e7acbcd3..00000000000 --- a/release/scripts/export_m3g.py +++ /dev/null @@ -1,3074 +0,0 @@ -#!BPY -# coding: utf-8 -""" Registration info for Blender menus: -Name: 'M3G (.m3g, .java)...' -Blender: 244 -Group: 'Export' -Tooltip: 'Export to M3G' -""" -#------------------------------------------------------------------------ -# M3G exporter for blender 2.37 or above -# -# Source: http://www.nelson-games.de/bl2m3g/source -# -# $Id$ -# -# Author: Gerhard Völkl -# -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Copyright (C) 2005: gerhard völkl gkvoelkl@yahoo.de -# -# 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 ***** -# -# To use script: -# 1.) load this file in the text window. -# (press SHIFT+F11, Open New via Datablock button) -# 2.) make sure your mouse is over the text edit window and -# run this script. (press ALT+P) -# Or: -# copy to the scripts directory and it will appear in the -# export list. (Needs 2.32 or higher) -# -# Based on informations from: -# wrl2export.py from Rick Kimball and others -# --------------------------------------------------------------------------# -# History 0.2 -# * maximal Precision in VertexArray (with algorithms from Kalle Raita) -# * IPO Animation with mesh: Rotation, Translation and Size -# History 0.3 -# * to find a 3d object in your java programm you can assign a userID -# your blender object has name 'cube#01' your 3d object will have ID 01 -# the number after '#' is taken -# * more than one material per mesh can be used -# * uv texture support (implemented by Aki Koskinen and Juha Laitinen) -# The image which is bound to the faces will be exportet within m3g-file -# Limitations by M3G-API: -# The width and height of the image must be non-negative powers of two, -# but they need not to be equal. Maximum value is 256. -# *.java export: Only PNG images can be used. -# History 0.4 -# * check limitation of texture images (credit to MASTER_ZION for Brasil) -# * Better light: The light modeles of Blender and M3G are naturally -# different. So the export script trys to translate as much as possible -# -# M3G Light type Blender Light type -# -------------------------------------------------------------- -# AMIENT Light Not available as light type in Blender -# DIRECTIONAL Light SUN -# OMNIdirectional light LAMP -# SPOT light SPOT -# not translated HEMI -# not translated AREA -# -# Attributs of M3G Lights: -# -# Attenuation (OMNI,SPOT): -# Intensity of light changes with distance -# The attenuation factor is 1 / (c + l d + q d2) -# where d is the distance between the light and the vertex being lighted -# and c, l, q are the constant, linear, and quadratic coefficients. -# In Blender exists much complex posibilies. To simplify exporter uses -# only button Dist: distance at which the light intensity is half -# the Energy -# Color (ALL) -# Color of light -# Intensity (ALL) -# The RGB color of this Light is multiplied component-wise with the -# intensity. In Blender : energy -# SpotAngle (SPOT) -# the spot cone angle for this Light -# In Blender: spotSize -# SpotExponent (SPOT) -# The spot exponent controls the distribution of the intensity of -# this Light within the spot cone, such that larger values yield -# a more concentrated cone. In Blender: SpotBl -# -# * Some GUI for options -# First prototype of GUI was created using RipSting's Blender-Python -# GUI designer. Download at Http://oregonstate.edu/~dennisa/Blender/BPG/ -# -# * Ambiente light -# Information is taken by world ambiente attribute -# -# * Parenting Part 1 -# In Blender the Empty object is used to group objects. All objects -# which have the same empty as parent are the member of the same group. -# -# empty <-- Parent of -- element 1 -# <-- Parent of -- element 2 -# -# is translated in M3G -# -# group-Node -- Member --> element 1 -# -- Member --> element 2 -# -# In Blender every object can be the parent of every other object -# In M3G that is not possible. Only a group object can be parent. -# (Or the world object which is derived from group). -# That will come later as Parenting Part 2 -# -# * Backface Culling -# you can use backface culling, if option "use backface culloing" is on. -# Culling will be set in PolygonMode object of every mesh. The correct -# winding is controlled. -# History 0.5 -#* Bone Animation - Armature (Part 1) -# -# Armature is the skeleton for skinned meshes. It stores the bones in -# rest position (more information http://www.blender.org/cms/How_Armatures_work.634.0.html) -# You can work in Blender with bones and meshes in different ways. In -# this first attempt only the use of vertex groups is assisted. -# -# Blender-Objekts translated into M3G-Objects -# -# MESH SkinnedMesh -# | | -# v v -# ARMATURE Group -# | | -# v v -# BONE_1 Group -# Group_second -# | | -# V v -# BONE_2 Group -# Group_secound -# -# Every bone is translated into two groups at the moment, because -# the second bone is needed to do the animation in an easy way. -# -# The animations in Blender for meshes are stored in action objects. -# -# Blender Objects translated into M3G-Objects -# -# ARMATURE -# | activ -# v -# ACTION ANIMATIONCONTROLLER -# | 1..n ^ -# v ANIMATIONTRACK --> Group_second -# IPOs | -# v -# KEYSEQUENZE -# -# One action is translated into one animationcontroller. One IPO is -# translated in one KEYSEQUENZE and one ANIMATIONTRACK. -# -# At the moment only the active action of the armature object is translated. -# -#* Print Info, if type of light is used that is not supported -# -# History 0.5 -# -#* New Option exportAllAction (default value: false) -# If that option is true, all actions will be exported - not only the active -# action. -# At the moment you can only assign one action to one armature. -# To know which action is used with which armature the action -# needs a special name : -# <Action Name>#A<M3G ID of Armature>E<End Frame>#<ID of Action> - -# Example: Name of action : walk#A10E250#02 -# Name of armature : man#10 -# End Frame: 250 -# -# History 0.6 -# Include the same image only one time into the m3g-file -# -# All the following changes of this version was made by Claus Hoefele -# -#* Until now all vertices of the faces was been written. -# Now the vertices will be used again if possible: -# normal and texture coordinates of to vertices have to be the same -# -#* Smooth/solid shading can now be defined for every single material: -# in Editing panel (F9)>Link and Materials -# -#* This script uses now correctly the TexFace and Shadless Buttons in -# Shading panel (F5)>Material buttons>Material box. -# TexFace switches on/off the Export of texture coordinates. -# Shadeless does the some with the normal coordinates -# -#* The GUI was redesigned in a PupBlock -# -#* Options: -# -#** Texturing Enabled: Switches on/off export of textures and texture -# coordinates. Attention: the TextFace button switches only -# for one mesh -#** Texturing External: the textures will be included it mg3-file or -# exported in seperate file -#** Lighting Enabled: turns on/off export of lights and normal completly -# Attention: Shadeless only for one mesh -#** Persp. Correction: turns on/off perspective correction in PolygonMode. -#** Smooth Shading: turns on/off smooth shading in PolygonMode. -# -#* Textures in external references are used again (with ImageFactory) -# -#* Blender function: Double Sided button in Editing Context -# (F9)>Mesh panel) -# turn on/off PolygonMode.CULL_BACK anzuschalten. -# -#* Script ingnores meshes that have no faces -# -# History 0.7 -# -# * Exporter can work with texture coordinates greater 1 and smaller 0 -# -# * Adler32 did not work always correct. New implementation made. -# -# * Modul shutil is not needed any longer. Exporter has its own copy_file. -# (realized and inspired by ideasman_42 and Martin Neumann) -# -# History 0.8 -# -# * Blender works with SpotAngles 1..180 but M3G works only with 0..90 -# M3G use the 'half angle' (cut off angle) (Thanks to Martin Storsjö) -# -# * Error fixed: Texture coordinates was not calculated correct. -# (Thanks to Milan Piskla, Vlad, Max Gilead, Regis Cosnier ...) -# -# * New options in GUI: -# M3G Version 2.0 : Will export M3G files Vers. 2.0 in future -# Game Physics: Adds Game Physics infos for NOPE API -# -# --------------------------------------------------------------------------# -# TODO: Export only selected mesh -# TODO: Optimize Bones <--> Vertex Group mapping -# TODO: Compressed File -# TODO: MTex - Support -# TODO: By Rotating use SQUAD instead of Beziere. It's smoother -import Blender -from Blender import Types,Lamp,Material,Texture,Window,Registry,Draw -from Blender.BGL import * -from Blender.Object import * -from Blender.Camera import * -from Blender.Mesh import * -from array import array -import sys, struct, zlib -from inspect import * -from types import * -from Blender.Mathutils import * -from os.path import * -#import rpdb2 - -# ---- Helper Functions -------------------------------------------------------# -def copy_file(source, dest): - file = open(source, 'rb') - data = file.read() - file.close() - - file = open(dest, 'wb') - file.write(data) - file.close() - -def tracer(frame, event, arg): - '''Global trace function''' - if event=='call': - tmp = getargvalues(frame) - print event, frame.f_code.co_name, frame.f_lineno, \ - formatargvalues(tmp[0],tmp[1],tmp[2],tmp[3]) - elif event=='line': - print event, frame.f_code.co_name, frame.f_lineno - #print event, frame.f_code.co_name, frame.f_lineno, \ - # getsourcelines(frame.f_code)[frame.f_lineno] - elif event=='return': - print event, frame.f_code.co_name, frame.f_lineno, "->", arg - return tracer - -def doSearchDeep(inList,outList): - '''Does deepsearch for all elements in inList''' - for element in inList: - if element != None : outList = element.searchDeep(outList) - return outList - - -def getId(aObject): - ''' returns 0 if Object is None: M3G value for null''' - if aObject == None: return 0 - return aObject.id - -def toJavaBoolean(aValue): - ''' returns java equivalent to boolean''' - if aValue: - return 'true' - else : - return 'false' - -def sign(a): - if a<0 : return -1 - elif a>0 : return 1 - else : return 0 - -def isOrderClockWise(v,normal): - ''' returns true, if order of vertices is clockwise. Important for - culling ''' - # (v2-v0)x(v2-v1)=surface_normal - # - if type(v[0]) is Types.MVertType: - mNormal = TriangleNormal(Vector(v[0].co),Vector(v[1].co),Vector(v[2].co)) - else: - mNormal = TriangleNormal(Vector(v[0]),Vectot(v[1]),Vector(v[2])) - #print "normal ",mNormal.normalize() - #print "BNormal ",normal.normalize() - - # Do not use any longer. Blender does it correct - - result = (sign(normal.x)==sign(mNormal.x) and - sign(normal.y)==sign(mNormal.y) and - sign(normal.z)==sign(mNormal.z)) - #print "Result ",result - - return True - - -# ---- M3G Types --------------------------------------------------------------# -class M3GVertexList: - def __init__(self, wrapList): - self.mlist = wrapList - - def __getitem__(self, key): - item = self.mlist[key] - if type(item) is Types.MVertType: - result =(item.co[0],item.co[1],item.co[2]) - else: - result = item - return result - -class M3GBoneReference: - def __init__(self,first,count): - self.firstVertex=first #UInt32 - self.vertexCount=count #UInt32 - - -class M3GBone: - def __init__(self): - self.verts=[] #List of influenced verts - self.transformNode=None #ObjectIndex - self.references = [] #References to Verts that are needed - self.weight=0 #Int32 - - - def setVerts(self,aVerts): - self.verts = aVerts - self.createReferences() - - def createReferences(self): - #print "createReference::len(verts) ",len(self.verts) - if len(self.verts)==0: return #No Verts available - self.verts.sort() - ref = [] - list = [] - last = self.verts[0]-1 - count = 0 - for vert in self.verts: - #print "vert ",vert - if vert==last+1: - list.append(vert) - else: - ref.append(M3GBoneReference(list[0],len(list))) - #print list[0],len(list) - list=[vert] - last=vert - #print "list ",list - if len(list)>0: - ref.append(M3GBoneReference(list[0],len(list))) - self.references = ref - - -class M3GVector3D: - def __init__(self,ax=0.0,ay=0.0,az=0.0): - self.x = ax #Float32 - self.y = ay #Float32 - self.z = az #Float32 - - def writeJava(self): - return str(self.x)+"f, "+str(self.y)+"f, "+str(self.z)+"f" - - def getData(self): - return struct.pack("<3f",self.x,self.y,self.z) - - def getDataLength(self): - return struct.calcsize("<3f") - -class M3GMatrix: - """ A 4x4 generalized matrix. The 16 elements of the - matrix are output in the same order as they are - retrieved using the API Transform.get method. In - other words, in this order: - 0 1 2 3 - 4 5 6 7 - 8 9 10 11 - 12 13 14 15 """ - def __init__(self): - self.elements=16 * [0.0] #Float32 - - def identity(self): - self.elements[ 0] = 1.0 - self.elements[ 5] = 1.0 - self.elements[10] = 1.0 - self.elements[15] = 1.0 - - def getData(self): - return struct.pack('<16f',self.elements[0],self.elements[1], - self.elements[2],self.elements[3], - self.elements[4],self.elements[5], - self.elements[6],self.elements[7], - self.elements[8],self.elements[9], - self.elements[10],self.elements[11], - self.elements[12],self.elements[13], - self.elements[14],self.elements[15]) - - def getDataLength(self): - return struct.calcsize('<16f') - - -class M3GColorRGB: - """ A color, with no alpha information. Each compo- - nent is scaled so that 0x00 is 0.0, and 0xFF is 1.0. - """ - def __init__(self,ared=0,agreen=0,ablue=0): - self.red = ared #Byte - self.green = agreen #Byte - self.blue = ablue #Byte - - def writeJava(self): - return "0x"+("%02X%02X%02X%02X" % (0.0, self.red, self.green, self.blue)) - - def getData(self): - return struct.pack('3B',self.red,self.green,self.blue) - - def getDataLength(self): - return struct.calcsize('3B') - - -class M3GColorRGBA: - """ A color, with alpha information. Each component - is scaled so that 0x00 is 0.0, and 0xFF is 1.0. The - alpha value is scaled so that 0x00 is completely - transparent, and 0xFF is completely opaque. - """ - def __init__(self,ared=0,agreen=0,ablue=0,aalpha=0): - self.red = ared #Byte - self.green = agreen #Byte - self.blue = ablue #Byte - self.alpha = aalpha #Byte - - def writeJava(self): - return "0x"+("%02X%02X%02X%02X" % (self.alpha, self.red, self.green, self.blue)) - - def getData(self): - return struct.pack('4B',self.red,self.green,self.blue,self.alpha) - - def getDataLength(self): - return struct.calcsize('4B') - - -#ObjectIndex -#The index of a previously encountered object in -#the file. Although this is serialized as a single -#unsigned integer, it is included in the compound -#type list because of the additional semantic infor- -#mation embodied in its type. A value of 0 is -#reserved to indicate a null reference; actual object indices start from 1. Object indices must refer -#only to null or to an object which has already been -#created during the input deserialization of a file - -#they must be less than or equal to the index of the -#object in which they appear. Other values are dis- -#allowed and must be treated as errors. -#UInt32 -#index; - -# ---- M3G Proxy --------------------------------------------------------------- # -class M3GProxy: - def __init__(self): - self.name = "" - self.id=0 - self.ObjectType=0 - self.binaryFormat='' - - def __repr__(self): - return "<"+str(self.__class__)[9:] + ":" + str(self.name) + ":" + str(self.id) + ">" - - -class M3GHeaderObject(M3GProxy): - def __init__(self): - M3GProxy.__init__(self) - self.M3GHeaderObject_binaryFormat = '<BBBII' - self.ObjectType=0 - self.id = 1 #Special Object: always 1 - self.VersionNumber=[1,0] #Byte[2] - self.hasExternalReferences=False #Boolean External Files needed? eg. Textures - self.TotalFileSize=0 #UInt32 - self.ApproximateContentSize=0 #UInt32 Only a hint! External sources included - self.AuthoringField='Blender M3G Export' #String - - def getData(self): - data = struct.pack(self.M3GHeaderObject_binaryFormat, - self.VersionNumber[0], - self.VersionNumber[1], - self.hasExternalReferences, - self.TotalFileSize, - self.ApproximateContentSize) - data += struct.pack(str(len(self.AuthoringField)+1)+'s',self.AuthoringField) - return data - - def getDataLength(self): - value = struct.calcsize(self.M3GHeaderObject_binaryFormat) - return value + struct.calcsize(str(len(self.AuthoringField)+1)+'s') - -class M3GExternalReference(M3GProxy): - def __init__(self): - M3GProxy.__init__(self) - self.ObjectType=0xFF - self.URI='' #reference URI - - def getData(self): - data = struct.pack(str(len(self.URI)+1) + 's', self.URI) - return data - - def getDataLength(self): - return struct.calcsize(str(len(self.URI)+1)+'s') - - def searchDeep(self,alist): - if not(self in alist): alist.append(self) - return alist - - def __repr__(self): - return M3GProxy.__repr__(self) + " (" + self.URI + ")" - - -class M3GObject3D(M3GProxy): - def __init__(self): - M3GProxy.__init__(self) - self.userID=0 #UInt32 - field may be any value - self.animationTracks=[] #ObjectIndex[] - self.userParameterCount=0 #UInt32 - No user parameter used - - def searchDeep(self,alist): - alist = doSearchDeep(self.animationTracks,alist) - if not(self in alist): alist.append(self) - return alist - - def getData(self): - data = struct.pack('<I',self.userID) - print "write userID",self.userID,self.name,str(self), self.getDataLength() - data += struct.pack('<I',len(self.animationTracks)) - for element in self.animationTracks: - data += struct.pack('<I',getId(element)) - data += struct.pack('<I',self.userParameterCount) - return data - - def getDataLength(self): - value = struct.calcsize('<3I') - if len(self.animationTracks) > 0: - value += struct.calcsize('<'+str(len(self.animationTracks))+'I') - return value - - def writeJava(self,aWriter,aCreate): - if aCreate : pass #Abstract! Could not be created - if len(self.animationTracks) > 0 : - aWriter.write(2) - for iTrack in self.animationTracks: - aWriter.write(2,"BL%i.addAnimationTrack(BL%i);" % (self.id,iTrack.id)) - - -class M3GTransformable(M3GObject3D): - def __init__(self): - M3GObject3D.__init__(self) - self.hasComponentTransform=False #Boolean - #IF hasComponentTransform==TRUE, THEN - self.translation=M3GVector3D(0,0,0) #Vector3D - self.scale=M3GVector3D(1,1,1) #Vector3D - self.orientationAngle=0 #Float32 - self.orientationAxis=M3GVector3D(0,0,0) #Vector3D undefined - #END - self.hasGeneralTransform=False #Boolean - #IF hasGeneralTransform==TRUE, THEN - self.transform = M3GMatrix() #Matrix identity - self.transform.identity() - #END - #If either hasComponentTransform or hasGeneralTransform is false, the omitted fields will be - #initialized to their default values (equivalent to an identity transform in both cases). - - def writeJava(self,aWriter,aCreate): - if aCreate: pass #Abstract Base Class! Cant't be created - M3GObject3D.writeJava(self,aWriter,False) - if self.hasGeneralTransform : - aWriter.write(2,"float[] BL%i_matrix = {" % (self.id)) - aWriter.writeList(self.transform.elements,4,"f") - aWriter.write(2,"};") - aWriter.write(2) - aWriter.write(2,"Transform BL%i_transform = new Transform();" % (self.id)) - aWriter.write(2,"BL%i_transform.set(BL%i_matrix);" % (self.id,self.id)) - aWriter.write(2,"BL%i.setTransform(BL%i_transform);" % (self.id,self.id)) - aWriter.write(2) - if self.hasComponentTransform: - aWriter.write(2,("BL%i.setTranslation("+self.translation.writeJava()+");") - %(self.id)) - - def getData(self): - data = M3GObject3D.getData(self) - data += struct.pack("<B",self.hasComponentTransform) - if self.hasComponentTransform==True: - data += self.translation.getData() - data += self.scale.getData() - data += struct.pack('<f',self.orientationAngle) - data += self.orientationAxis.getData() - data += struct.pack("<B",self.hasGeneralTransform) - if self.hasGeneralTransform==True: - data += self.transform.getData() - return data - - def getDataLength(self): - value = M3GObject3D.getDataLength(self) - value += struct.calcsize("<B") - if self.hasComponentTransform==True: - value += self.translation.getDataLength() - value += self.scale.getDataLength() - value += struct.calcsize('<f') - value += self.orientationAxis.getDataLength() - value += struct.calcsize("<B") - if self.hasGeneralTransform==True: - value += self.transform.getDataLength() - return value - - -class M3GNode(M3GTransformable): - def __init__(self): - M3GTransformable.__init__(self) - self.blenderObj = None #Pointer to corrsponding BlenderObj - self.parentBlenderObj = None #Pointer to Parent in Blender - self.blenderMatrixWorld = None #BlenderObj matrixWorld - self.M3GNode_binaryFormat = '<BBBIB' - self.enableRendering=True #Boolean - self.enablePicking=True #Boolean - self.alphaFactor=255 #Byte 0x00 is equivalent to 0.0 (fully transparent), and 255 is equivalent to 1.0 (fully opaque); - self.scope=4294967295 #-1 #UInt32 - self.hasAlignment = False #Boolean - #IF hasAlignment==TRUE, THEN - self.M3GNode_binaryFormat_2 = '<BBII' - self.zTarget=0 #Byte The zTarget and yTarget fields must each hold a valid enumerated value, - self.yTarget=0 #Byte as specified in the class definition. Other values must be treated as errors. - self.zReference=None #ObjectIndex - self.yReference=None #ObjectIndex - #END - #If the hasAlignment field is false, the omitted fields are initialized to their default values. - - - def getData(self): - data = M3GTransformable.getData(self) - #print "Binary ",self.binaryFormat - data += struct.pack(self.M3GNode_binaryFormat, - self.enableRendering, - self.enablePicking, - self.alphaFactor, - self.scope, - self.hasAlignment) - - if self.hasAlignment: - data += pack(self.M3GNode_binaryFormat_2, - self.zTarget, - self.yTarget, - getId(self.zReference), - getId(self.yReference)) - return data - - def getDataLength(self): - value = M3GTransformable.getDataLength(self) + \ - struct.calcsize(self.M3GNode_binaryFormat) - if self.hasAlignment: - value += struct.calcsize(self.M3GNode_binaryFormat_2) - return value - - def writeJava(self,aWriter,aCreate): - if aCreate: pass #Abstract Base Class! Cant't be created - M3GTransformable.writeJava(self,aWriter,False) - -class M3GGroup(M3GNode): - def __init__(self): - M3GNode.__init__(self) - self.ObjectType=9 - self.children = [] #ObjectIndex[] - - def searchDeep(self,alist): - for element in self.children: - alist = element.searchDeep(alist) - return M3GNode.searchDeep(self,alist) - - def writeJava(self,aWriter,aCreate): - if aCreate: - aWriter.write(2,"//Group:"+self.name ) - aWriter.write(2,"Group BL"+str(self.id)+" = new Group();") - M3GNode.writeJava(self,aWriter,False) - for element in self.children: - aWriter.write(2,"BL%i.addChild(BL%i);" % (self.id,element.id)) - - def getData(self): - data = M3GNode.getData(self) - data = data + struct.pack("<I",len(self.children)) - for element in self.children: - data += struct.pack("<I",getId(element)) - return data - - def getDataLength(self): - return M3GNode.getDataLength(self)+ \ - struct.calcsize("<"+str(len(self.children)+1)+"I") - - -class M3GWorld(M3GGroup): - def __init__(self): - M3GGroup.__init__(self) - self.ObjectType=22 - self.activeCamera=None #ObjectIndex - self.background=None #ObjectIndex UInt32 0=None - self.M3GWorld_binaryFormat='<II' - - def searchDeep(self,alist): - alist = doSearchDeep([self.activeCamera, self.background],alist) - return M3GGroup.searchDeep(self,alist) - - - def writeJava(self,aWriter,aCreate): - if aCreate: - aWriter.write(2,"//World:"+self.name ) - aWriter.write(2,"World BL"+str(self.id)+" = new World();") - M3GGroup.writeJava(self,aWriter,False) - if self.background != None: - aWriter.write(2,"BL"+str(self.id)+".setBackground(BL"+str(self.background.id)+");") - if self.activeCamera != None: - aWriter.write(2,"BL%i.setActiveCamera(BL%i);" % - (self.id,self.activeCamera.id)) - aWriter.write(2) - - - def getData(self): - data = M3GGroup.getData(self) - return data + \ - struct.pack(self.M3GWorld_binaryFormat,getId(self.activeCamera),getId(self.background)) - - - def getDataLength(self): - return M3GGroup.getDataLength(self) + struct.calcsize(self.M3GWorld_binaryFormat) - - -class M3GBackground(M3GObject3D): - def __init__(self): - M3GObject3D.__init__(self) - self.ObjectType=4 - self.M3GBackground_binaryFormat = '<BBiiiiBB' - self.backgroundColor=M3GColorRGBA(0,0,0,0) #ColorRGBA 0x00000000 (black, transparent) - self.backgroundImage=None #ObjectIndex null (use the background color only) - self.backgroundImageModeX=32; #Byte BORDER=32 REPEAT=33 - self.backgroundImageModeY=32; #Byte BORDER - self.cropX = 0; #Int32 - self.cropY = 0 #Int32 ; - self.cropWidth = 0 #Int32 ; - self.cropHeight = 0;#Int32 - self.depthClearEnabled = True #Boolean - self.colorClearEnabled = True #Boolean - - def writeJava(self,aWriter,aCreate): - if aCreate: - aWriter.write(2,"//Background:"+self.name ) - aWriter.write(2,"Background BL"+str(self.id)+" = new Background();") - M3GObject3D.writeJava(self,aWriter,False) - aWriter.write(2,"BL"+str(self.id)+".setColor("+self.backgroundColor.writeJava()+");") - aWriter.write(2,"") - - def getData(self): - data = M3GObject3D.getData(self) - data += self.backgroundColor.getData() - data += struct.pack('<I',getId(self.backgroundImage)) - data += struct.pack(self.M3GBackground_binaryFormat, self.backgroundImageModeX, - self.backgroundImageModeY, - self.cropX, - self.cropY, - self.cropWidth, - self.cropHeight, - self.depthClearEnabled, - self.colorClearEnabled) - return data - - def getDataLength(self): - value=M3GObject3D.getDataLength(self) - value += self.backgroundColor.getDataLength() - value += struct.calcsize('<I') - value += struct.calcsize(self.M3GBackground_binaryFormat) - return value - - -class M3GCamera(M3GNode): - GENERIC=48 #Projection-Types - PARALLEL=49 - PERSPECTIVE=50 - - def __init__(self): - M3GNode.__init__(self) - self.ObjectType=5 - self.projectionType=M3GCamera.PARALLEL #Byte - #IF projectionType==GENERIC, THEN - self.projectionMatrix=M3GMatrix() #Matrix •view volume : opposite corners at (-1 -1 -1) and (1 1 1) - # TODO: Set right matrix - #ELSE - self.fovy=0.0 #Float32 - self.AspectRatio=0.0#Float32 - self.near=0.0#Float32 - self.far=0.0#Float32 - #END - - def writeJava(self,aWriter,aCreate): - if aCreate: - aWriter.write(2,"//Camera " + self.name) - aWriter.write(2,"Camera BL%i = new Camera();" % (self.id)) - M3GNode.writeJava(self,aWriter,False) - aWriter.write(2,"BL%i.setPerspective(%ff, //Field of View" % \ - (self.id,self.fovy)) - aWriter.write(4,"(float)aCanvas.getWidth()/(float)aCanvas.getHeight(),") - aWriter.write(4,str(self.near)+"f, //Near Clipping Plane") - aWriter.write(4,str(self.far)+"f); //Far Clipping Plane") - - def getData(self): - data = M3GNode.getData(self) - data += struct.pack("B",self.projectionType) - if self.projectionType == self.GENERIC: - data += self.projectionMatrix.getData() - else: - data += struct.pack("<4f",self.fovy,self.AspectRatio,self.near,self.far) - return data - - def getDataLength(self): - value = M3GNode.getDataLength(self) - value += struct.calcsize("B") - if self.projectionType == self.GENERIC: - value += self.projectionMatrix.getDataLength() - else: - value += struct.calcsize("<4f") - return value - - -class M3GMesh(M3GNode): - def __init__(self,aVertexBuffer=None, aIndexBuffer=[], aAppearance=[]): - M3GNode.__init__(self) - self.ObjectType=14 - self.vertexBuffer = aVertexBuffer #ObjectIndex - self.submeshCount=len(aIndexBuffer) #UInt32 - #FOR each submesh... - self.indexBuffer=aIndexBuffer #ObjectIndex - self.appearance=aAppearance #;ObjectIndex - #END - - def getData(self): - data = M3GNode.getData(self) - data += struct.pack('<2I', getId(self.vertexBuffer), - self.submeshCount) - for i in range(len(self.indexBuffer)): - data += struct.pack('<2I',getId(self.indexBuffer[i]), - getId(self.appearance[i])) - return data - - def getDataLength(self): - value = M3GNode.getDataLength(self) - value += struct.calcsize('<2I') - for i in range(len(self.indexBuffer)): - value += struct.calcsize('<2I') - return value - - def searchDeep(self,alist): - alist = doSearchDeep([self.vertexBuffer] +self.indexBuffer - + self.appearance ,alist) - return M3GNode.searchDeep(self,alist) - - def writeJava(self,aWriter,aCreate): - self.writeBaseJava(aWriter,aCreate,"Mesh","") - - def writeBaseJava(self,aWriter,aCreate,aClassName,aExtension): - if aCreate: - aWriter.writeClass(aClassName,self) - if self.submeshCount > 1: - aWriter.write(2,"IndexBuffer[] BL%i_indexArray = {" % (self.id)) - aWriter.write(4,",".join(["BL%i" %(i.id) for i in self.indexBuffer ])) - aWriter.write(2," };") - aWriter.write(2) - aWriter.write(2,"Appearance[] BL%i_appearanceArray = {" % (self.id)) - aWriter.write(4,",".join(["BL%i" %(i.id) for i in self.appearance ])) - aWriter.write(2," };") - aWriter.write(2) - aWriter.write(2,"%s BL%i = new %s(BL%i,BL%i_indexArray,BL%i_appearanceArray%s);" % \ - (aClassName,self.id,aClassName,self.vertexBuffer.id, self.id,self.id,aExtension)) - else: - #print "indexBuffer", len(self.indexBuffer) - #print "appearance", len(self.appearance) - aWriter.write(2,"%s BL%i = new %s(BL%i,BL%i,BL%i%s);" % \ - (aClassName, - self.id, - aClassName, - self.vertexBuffer.id, - self.indexBuffer[0].id, - self.appearance[0].id, - aExtension)) - M3GNode.writeJava(self,aWriter,False) - aWriter.write(2) - - -class M3GSkinnedMesh(M3GMesh): - def __init__(self,aVertexBuffer=None, aIndexBuffer=[], aAppearance=[]): - M3GMesh.__init__(self,aVertexBuffer, aIndexBuffer, aAppearance) - self.ObjectType=16 - self.skeleton=None #ObjectIndex - self.bones={} - #print"M3GSkinnedMesh.__init__::self.vertexBuffer:",self.vertexBuffer - ##ObjectIndex skeleton; - ##UInt32 transformReferenceCount; - ##FOR each bone reference... - ## ObjectIndex transformNode; - ## UInt32 firstVertex; - ## UInt32 vertexCount; - ## Int32 weight; - ##END - - def searchDeep(self,alist): - alist = doSearchDeep([self.skeleton],alist) - return M3GMesh.searchDeep(self,alist) - - def addSecondBone(self): - secondBones = {} - for bone in self.bones.values(): - bone2 = M3GBone() - bone2.verts=bone.verts - bone.verts=[] - mGroup = M3GGroup() - mGroup.name=bone.transformNode.name+"_second" - bone2.transformNode=mGroup - bone2.references = bone.references - bone.references = [] - bone2.weight = bone.weight - bone.weight=0 - mGroup.children = bone.transformNode.children - bone.transformNode.children = [mGroup] - mGroup.animationTracks=bone.transformNode.animationTracks - bone.transformNode.animationTracks = [] - secondBones[bone.transformNode.name+"_second"]=bone2 - for bone in secondBones.values(): - self.bones[bone.transformNode.name] = bone - - def getBlenderIndexes(self): - #print "M3GSkinnedMesh.vertexBuffer:",self.vertexBuffer - return self.vertexBuffer.positions.blenderIndexes - - def writeJava(self,aWriter,aCreate): - self.writeBaseJava(aWriter,aCreate,"SkinnedMesh", - (",BL%i" % (self.skeleton.id))) - aWriter.write(2,"//Transforms") - for bone in self.bones.values(): - #print "bone: ", bone - #print "bone.references: ", bone.references - for ref in bone.references: - aWriter.write(2,"BL%i.addTransform(BL%i,%i,%i,%i);" % - (self.id, - bone.transformNode.id,bone.weight, - ref.firstVertex, ref.vertexCount)) - aWriter.write(2) - - def getDataLength(self): - value = M3GMesh.getDataLength(self) - value += struct.calcsize('<I') #skeleton - value += struct.calcsize('<I') #transformReferenceCount - for bone in self.bones.values(): - for ref in bone.references: - value += struct.calcsize('<3Ii') - return value - - def getData(self): - data = M3GMesh.getData(self) - data += struct.pack('<I', getId(self.skeleton)) - count = 0 - for bone in self.bones.values(): count+=len(bone.references) - data += struct.pack('<I',count) - for bone in self.bones.values(): - for ref in bone.references: - data += struct.pack('<I',getId(bone.transformNode)) - data += struct.pack('<2I',ref.firstVertex,ref.vertexCount) - data += struct.pack('<i',bone.weight) - return data - -class M3GLight(M3GNode): - def __init__(self): - M3GNode.__init__(self) - self.ObjectType=12 - self.modes = {'AMBIENT':128, - 'DIRECTIONAL':129, - 'OMNI':130, - 'SPOT':131} - self.attenuationConstant = 1.0 #Float32 - self.attenuationLinear = 0.0 #Float32 - self.attenuationQuadratic = 0.0 #Float32 - self.color = M3GColorRGB(1.0, 1.0, 1.0) #ColorRGB - self.mode = self.modes['DIRECTIONAL'] #Byte Enumurator mode: DIRECTIONAL - self.intensity = 1.0 #Float32 - self.spotAngle = 45 #Float32 - self.spotExponent = 0.0 #Float32 - - def writeJava(self,aWriter,aCreate): - if aCreate: - aWriter.write(2,"//Light: " + self.name) - aWriter.write(2,"Light BL%i = new Light();" % (self.id)) - aWriter.write(2,"BL%i.setMode(%i);" % (self.id,self.mode)) #Light.OMNI - if self.mode in [self.modes['OMNI'],self.modes['SPOT']]:#Attenuation - aWriter.write(2,"BL%i.setAttenuation(%ff, %ff,%ff);" - % (self.id, - self.attenuationConstant, - self.attenuationLinear, - self.attenuationQuadratic)) - aWriter.write(2,("BL%i.setColor("+self.color.writeJava()+");") - % (self.id)) - aWriter.write(2,"BL%i.setIntensity(%ff);" - % (self.id,self.intensity)) - if self.mode == self.modes['SPOT']: - aWriter.write(2,"BL%i.setSpotAngle(%ff);" - % (self.id,self.spotAngle)) - aWriter.write(2,"BL%i.setSpotExponent(%ff);" - % (self.id,self.spotExponent)) - M3GNode.writeJava(self,aWriter,False) - aWriter.write(2) - - - def getData(self): - data = M3GNode.getData(self) - data += struct.pack("<fff", self.attenuationConstant, - self.attenuationLinear, - self.attenuationQuadratic) - data += self.color.getData() - data += struct.pack("<Bfff", self.mode, - self.intensity, - self.spotAngle, - self.spotExponent) - return data - - def getDataLength(self): - value = M3GNode.getDataLength(self) - value += self.color.getDataLength() - value += struct.calcsize('<B6f') - return value - -class M3GMaterial(M3GObject3D): - def __init__(self): - M3GObject3D.__init__(self) - self.ObjectType=13 - self.ambientColor=M3GColorRGB(0.2, 0.2, 0.2) #ColorRGB - self.diffuseColor=M3GColorRGBA(0.8, 0.8, 0.8, 1.0) #ColorRGBA - self.emissiveColor=M3GColorRGB(0.0, 0.0, 0.0) #ColorRGB - self.specularColor=M3GColorRGB(0.0, 0.0, 0.0) #ColorRGB - self.shininess=0.0 #Float32 - self.vertexColorTrackingEnabled=False #Boolean - - def writeJava(self,aWriter,aCreate): - if aCreate : - aWriter.write(2,"//Material: "+self.name ) - aWriter.write(2,"Material BL%i = new Material();" % (self.id)) - aWriter.write(2,("BL%i.setColor(Material.AMBIENT," + - self.ambientColor.writeJava()+");") % (self.id) ) - aWriter.write(2,("BL%i.setColor(Material.SPECULAR," + - self.specularColor.writeJava()+");") % (self.id) ) - aWriter.write(2,("BL%i.setColor(Material.DIFFUSE," + - self.diffuseColor.writeJava()+");") % (self.id)) - aWriter.write(2,("BL%i.setColor(Material.EMISSIVE," + - self.emissiveColor.writeJava()+");") % (self.id)) - aWriter.write(2,("BL%i.setShininess(%ff);") % (self.id,self.shininess)) - aWriter.write(2,("BL%i.setVertexColorTrackingEnable(" + - toJavaBoolean(self.vertexColorTrackingEnabled) + ");") % - (self.id)) - M3GObject3D.writeJava(self,aWriter,False) - - def getData(self): - data = M3GObject3D.getData(self) - data += self.ambientColor.getData() - data += self.diffuseColor.getData() - data += self.emissiveColor.getData() - data += self.specularColor.getData() - data += struct.pack('<fB',self.shininess, - self.vertexColorTrackingEnabled) - return data - - - def getDataLength(self): - value = M3GObject3D.getDataLength(self) - value += self.ambientColor.getDataLength() - value += self.diffuseColor.getDataLength() - value += self.emissiveColor.getDataLength() - value += self.specularColor.getDataLength() - value += struct.calcsize('<fB') - return value - - -class M3GVertexArray(M3GObject3D): - def __init__(self,aNumComponents,aComponentSize,aAutoScaling=False,aUVMapping=False): - M3GObject3D.__init__(self) - self.ObjectType=20 - self.blenderIndexes={} #Translation-Table from Blender index to m3g index - self.autoscaling = aAutoScaling #bias and scale should be computed internal - self.uvmapping=aUVMapping #Change coordinates from blender uv to uv-m3g - self.bias = [0.0,0.0,0.0] - self.scale = 1.0 - self.componentSize=aComponentSize #Byte number of bytes per component; must be [1, 2] - self.componentCount=aNumComponents #Byte number of components per vertex; must be [2, 4] - self.encoding=0 #Byte 0="raw" as bytes or 16 bit integers. - self.vertexCount=0 #UInt16 number of vertices in this VertexArray; must be [1, 65535] - if self.autoscaling==True: - self.components = array('f') - else: - self.components = self.createComponentArray() - #FOR each vertex... - # IF componentSize==1, THEN - # IF encoding==0, THEN - # Byte[componentCount] - # ELSE IF encoding==1, THEN - # Byte[componentCount] - # END - # ELSE - # IF encoding==0, THEN - # Int16[componentCount] - # ELSE IF encoding==1, THEN - # Int16[componentCount] - # END - # END - #END - - def createComponentArray(self): - if self.componentSize == 1: - return array('b') #Byte-Array - else: - return array('h') #Short-Array - - def useMaxPrecision(self,aBoundingBox): - """With Bias and Scale you can maximize the precision of the array""" - #print "useMaxPrecision" - vertexList = M3GVertexList(aBoundingBox) - first = vertexList[0] - minimum =[first[0],first[1],first[2]] - maximum = [first[0],first[1],first[2]] #Search maximal Dimension - for element in vertexList: - for i in range(3): - if minimum[i] > element[i] : minimum[i] = element[i] - if maximum[i] < element[i] : maximum[i] = element[i] - #print i, maximum[i],element[i] - lrange=[0,0,0] - maxRange=0.0 - maxDimension=-1 - for i in range(3): #set bias - lrange[i] = maximum[i]-minimum[i] - self.bias[i] = minimum[i]*0.5+maximum[i]*0.5 - #print "Bias",i,self.bias[i],"min-max",minimum[i],maximum[i],"lrang",lrange[i] - if lrange[i] > maxRange: - maxRange = lrange[i] - maxDimension=i - self.scale = maxRange/65533.0 - #print "MaxRange ",maxRange - #print "scale",self.scale - - - def internalAutoScaling(self): - print "internalAutoScaling" - #Already done? - print self.components.typecode - if not self.autoscaling or self.components.typecode!="f":return - #Find bais and scale - minimum=[] - maximum=[] - for i in range(self.componentCount): - minimum.append(self.components[i]) - maximum.append(self.components[i]) - for i in range(0,len(self.components),self.componentCount): - for j in range(self.componentCount): - if minimum[j] > self.components[i+j] : minimum[j] = self.components[i+j] - if maximum[j] < self.components[i+j] : maximum[j] = self.components[i+j] - #print "i+j=",i+j,"min=",minimum[j],"max=",maximum[j],"elem=",self.components[i+j] - #print "min=", minimum - #print "max=", maximum - lrange=[0] * self.componentCount - maxRange=0.0 - maxDimension=-1 - for i in range(self.componentCount): #set bias - lrange[i] = maximum[i]-minimum[i] - self.bias[i] = minimum[i]*0.5+maximum[i]*0.5 - #print "Bias",i,self.bias[i],"min-max",minimum[i],maximum[i],"lrang",lrange[i] - if lrange[i] > maxRange: - maxRange = lrange[i] - maxDimension=i - maxValue=(2**(8*self.componentSize)*1.0)-2.0 - #print "MaxValue=",maxValue - self.scale = maxRange/maxValue - #print "MaxRange ",maxRange - #print "scale",self.scale - #Copy Components - oldArray=self.components - self.components=self.createComponentArray() - for i in range(0,len(oldArray),self.componentCount): - for j in range(self.componentCount): - element=int((oldArray[i+j]-self.bias[j])/self.scale) - #print "element",element - self.components.append(element) - # Reverse t coordinate because M3G uses a different 2D coordinate system than Blender. - if self.uvmapping: - for i in range(0,len(self.components),2): - self.components[i+1]= int(self.components[i+1]*(-1)) #Error in Version 0.7 - for i in range(len(self.components)): - if abs(self.components[i])>maxValue:raise Exception( i+". element too great/small!") - - def writeJava(self,aWriter,aCreate): - self.internalAutoScaling() - if aCreate: - aWriter.write(2,"// VertexArray " + self.name) - if self.componentSize == 1: - aWriter.write(2,"byte[] BL%i_array = {" % (self.id)) - else: - aWriter.write(2,"short[] BL%i_array = {" % (self.id)) - aWriter.writeList(self.components) - aWriter.write(2,"};") - aWriter.write(2) - aWriter.write(2,"VertexArray BL%i = new VertexArray(BL%i_array.length/%i,%i,%i);" % - (self.id,self.id, - self.componentCount,self.componentCount,self.componentSize)) - aWriter.write(2,"BL%i.set(0,BL%i_array.length/%i,BL%i_array);" % - (self.id,self.id,self.componentCount,self.id)) - M3GObject3D.writeJava(self,aWriter,False) - aWriter.write(2) - - - def getData(self): - self.internalAutoScaling() - self.vertexCount = len(self.components)/self.componentCount - data = M3GObject3D.getData(self) - data += struct.pack('<3BH',self.componentSize, - self.componentCount, - self.encoding, - self.vertexCount) - componentType = "" - if self.componentSize == 1: - componentType = "b" - else: - componentType = "h" - for element in self.components: - data += struct.pack('<'+componentType,element) - return data - - def getDataLength(self): - self.internalAutoScaling() - value = M3GObject3D.getDataLength(self) - value += struct.calcsize('<3BH') - componentType = "" - if self.componentSize == 1: - componentType = "b" - else: - componentType = "h" - value += struct.calcsize('<'+str(len(self.components))+componentType) - return value - - def append(self,element,index=None): - #print "type(element):",type(element) - if type(element) is Types.vectorType : - for i in range(3): - value = int((element[i]-self.bias[i])/self.scale) - #print "append:",i,element[i],(element[i]-self.bias[i]),value - self.components.append(value) - elif type(element) is Types.MVertType: - for i in range(3): - value = int((element.co[i]-self.bias[i])/self.scale) - #print "append:",i,element[i],(element[i]-self.bias[i]),value - self.components.append(value) - if index!=None: - key=str(len(self.blenderIndexes)) - #print"key,index:",key,index - self.blenderIndexes[key]=index - #print"blenderIndexes",self.blenderIndexes - else: - print "VertexArray.append: element=",element - self.components.append(element) - -class M3GVertexBuffer(M3GObject3D): - def __init__(self): - M3GObject3D.__init__(self) - self.ObjectType=21 - self.defaultColor=M3GColorRGBA(255,255,255) #ColorRGBA 0xFFFFFFFF (opaque white). - self.positions = None #ObjectIndex - self.positionBias = [0.0,0.0,0.0] #Float32[3] - self.positionScale = 1.0 #Float32 - self.normals = None #ObjectIndex - self.colors = None #ObjectIndex - self.texCoordArrays = [] - self.texcoordArrayCount = 0 #UInt32 -## #FOR each texture coordinate array... -## self.texCoords = [] #ObjectIndex -## self.texCoordBias=[] #Float32[3] -## self.texCoordScale=[] #;Float32 -## #END -## #If a texture coordinate array has only two components, the corresponding texCoordBias[2] element -## #must be 0.0. -## #Null texture coordinate arrays are never serialized, regardless of their position. A single texture -## #coordinate array will therefore always be serialized as belonging to texturing unit 0, regardless of -## #its original unit it was assigned to. -## #There are as many references in the texture coordinates array as there are active texture units for -## #this geometry. The texture coordinate references are loaded sequentially from texture unit 0. If the -## #implementation supports more texture units than are specified, these are left in their default, inactive -## #state, with a null texture coordinate reference and an undefined bias and scale. -## #If more texture coordinate references are specified than are supported by the implementation, then -## #this must be treated as an error, as it would be in the API. The application can then decide on an -## #appropriate course of action to handle this case. - - def searchDeep(self,alist): - if self.positions!=None: alist = self.positions.searchDeep(alist) - if self.normals != None: alist = self.normals.searchDeep(alist) - if self.colors!= None: alist = self.colors.searchDeep(alist) - alist = doSearchDeep(self.texCoordArrays, alist) - return M3GObject3D.searchDeep(self,alist) - - def setPositions(self,aVertexArray): - self.positions = aVertexArray - self.positionBias = aVertexArray.bias - self.positionScale = aVertexArray.scale - - def writeJava(self,aWriter,aCreate): - if aCreate: - aWriter.write(2,"//VertexBuffer"+self.name ) - aWriter.write(2,"VertexBuffer BL%i = new VertexBuffer();" % (self.id)) - aWriter.write(2,"float BL%i_Bias[] = { %ff, %ff, %ff};" % - (self.id,self.positionBias[0], - self.positionBias[1],self.positionBias[2])) - aWriter.write(2,"BL%i.setPositions(BL%i,%ff,BL%i_Bias);" % - (self.id, self.positions.id, - self.positionScale,self.id)) - aWriter.write(2,"BL%i.setNormals(BL%i);" % (self.id,self.normals.id)) - #if self.colors != None: aWriter.write(2,"BL%i.setTexCoords(0,BL%i,1.0f,null);" % - # (self.id,self.colors.id)) - lIndex = 0 - for iTexCoord in self.texCoordArrays: - aWriter.write(2,"float BL%i_%i_TexBias[] = { %ff, %ff, %ff};" % - (self.id,lIndex, iTexCoord.bias[0], - iTexCoord.bias[1],iTexCoord.bias[2])) - #int index, javax.microedition.m3g.VertexArray194 texCoords, float scale, float[] bias - aWriter.write(2,"BL%i.setTexCoords(%i,BL%i,%ff,BL%i_%i_TexBias);" % - (self.id, lIndex, iTexCoord.id, iTexCoord.scale,self.id,lIndex)) - lIndex += 1 - - M3GObject3D.writeJava(self,aWriter,False) - - - def getData(self): - self.texcoordArrayCount = len(self.texCoordArrays) - data = M3GObject3D.getData(self) - data += self.defaultColor.getData() - data += struct.pack('<I4f3I',getId(self.positions), - self.positionBias[0], - self.positionBias[1], - self.positionBias[2], - self.positionScale, - getId(self.normals), - getId(self.colors), - self.texcoordArrayCount) - for iTexCoord in self.texCoordArrays: - data += struct.pack('<I', getId(iTexCoord)) - data += struct.pack('<ffff', iTexCoord.bias[0], - iTexCoord.bias[1], - iTexCoord.bias[2], - iTexCoord.scale) - return data - - - def getDataLength(self): - value = M3GObject3D.getDataLength(self) - value += self.defaultColor.getDataLength() - value += struct.calcsize('<I4f3I') - value += struct.calcsize('<Iffff') * len(self.texCoordArrays) - return value - - -class M3GPolygonMode(M3GObject3D): - CULL_BACK=160 - CULL_NONE=162 - SHADE_FLAT=164 - SHADE_SMOOTH=165 - WINDING_CCW=168 - WINDING_CW=169 - - def __init__(self): - M3GObject3D.__init__(self) - self.ObjectType=8 - self.culling=M3GPolygonMode.CULL_BACK #Byte - self.shading=M3GPolygonMode.SHADE_SMOOTH #Byte - self.winding=M3GPolygonMode.WINDING_CCW #Byte - self.twoSidedLightingEnabled = False #Boolean - self.localCameraLightingEnabled = False #Boolean - self.perspectiveCorrectionEnabled = False #Boolean - - def writeJava(self,aWriter,aCreate): - if aCreate: - aWriter.write(2,"PolygonMode BL%i = new PolygonMode();" % (self.id)) - aWriter.write(2,"BL%i.setCulling(%i);" % (self.id,self.culling)) - aWriter.write(2,"BL%i.setShading(%i);" % (self.id,self.shading)) - aWriter.write(2,"BL%i.setWinding(%i);" % (self.id,self.winding)) - aWriter.write(2,("BL%i.setTwoSidedLightingEnable(" + - toJavaBoolean(self.twoSidedLightingEnabled) + ");") % - (self.id)) - aWriter.write(2,("BL%i.setLocalCameraLightingEnable(" + - toJavaBoolean(self.localCameraLightingEnabled) + ");") % - (self.id)) - aWriter.write(2,("BL%i.setPerspectiveCorrectionEnable(" + - toJavaBoolean(self.perspectiveCorrectionEnabled) + ");") % - (self.id)) - aWriter.write(2) - M3GObject3D.writeJava(self,aWriter,False) - - def getData(self): - data = M3GObject3D.getData(self) - data += struct.pack('6B',self.culling, - self.shading, - self.winding, - self.twoSidedLightingEnabled, - self.localCameraLightingEnabled, - self.perspectiveCorrectionEnabled) - return data - - def getDataLength(self): - value = M3GObject3D.getDataLength(self) - value += struct.calcsize('6B') - return value - -class M3GIndexBuffer(M3GObject3D): - def __init__(self): - M3GObject3D.__init__(self) - - def getData(self): - return M3GObject3D.getData(self) - - def getDataLength(self): - return M3GObject3D.getDataLength(self) - - def writeJava(self,aWriter,aCreate): - M3GObject3D.writeJava(self,aWriter,False) - - -class M3GTriangleStripArray(M3GIndexBuffer): - def __init__(self): - M3GIndexBuffer.__init__(self) - self.ObjectType=11 - self.encoding=128 #Byte Bit 7: 1 = explicit property on index buffer true - #Bit 1 .. 6: 0 = "raw" integer values 1= a single byte will suffice - #2 = a 16 bit integer is suffi to hold all the given index values - #IF encoding == 0, THEN - #self.startIndex = 0 #;UInt32 - #ELSE IF encoding == 1, THEN - #Byte startIndex; - #ELSE IF encoding == 2, THEN - #UInt16 startIndex; - #ELSE IF encoding == 128, THEN - self.indices = [] #;UInt32[] - #ELSE IF encoding == 129, THEN - #Byte[] indices; - #ELSE IF encoding == 130, THEN - #UInt16[] indices; - #END - self.stripLengths = [] #;UInt32[] - - def writeJava(self,aWriter,aCreate): - if aCreate: - aWriter.write(2,"//length of TriangleStrips") - aWriter.write(2,"int[] BL"+str(self.id)+"_stripLength ={"+ - ",".join([str(element) for element in self.stripLengths])+"};") - aWriter.write(2) - aWriter.write(2,"//IndexBuffer") - aWriter.write(2,"int[] BL%i_Indices = {" % (self.id)) - aWriter.write(2,",".join([str(element) for element in self.indices])+"};") - aWriter.write(2) - aWriter.write(2,"IndexBuffer BL%i=new TriangleStripArray(BL%i_Indices,BL%i_stripLength);" % - (self.id, self.id, self.id)) - M3GIndexBuffer.writeJava(self,aWriter,False) - aWriter.write(2) - - - def getData(self): - data = M3GIndexBuffer.getData(self) - data += struct.pack('<BI',self.encoding, - len(self.indices)) - for element in self.indices: - data += struct.pack('<I',element) - data += struct.pack('<I',len(self.stripLengths)) - for element in self.stripLengths: - data += struct.pack('<I',element) - return data - - def getDataLength(self): - value = M3GIndexBuffer.getDataLength(self) - value += struct.calcsize('<BI') - if len(self.indices) > 0 : - value += struct.calcsize('<' + str(len(self.indices)) + 'I') - value += struct.calcsize('<I') - if len(self.stripLengths) > 0: - value+= struct.calcsize('<'+str(len(self.stripLengths))+'I') - return value - - -class M3GAppearance(M3GObject3D): - def __init__(self): - M3GObject3D.__init__(self) - self.ObjectType=3 - self.layer=0 #Byte - self.compositingMode=None #ObjectIndex - self.fog=None #ObjectIndex - self.polygonMode=None #ObjectIndex - self.material=None #ObjectIndex - self.textures=[] #;ObjectIndex[] - - def searchDeep(self,alist): - alist = doSearchDeep([self.compositingMode,self.fog, - self.polygonMode,self.material] - + self.textures,alist) - return M3GObject3D.searchDeep(self,alist) - - def getData(self): - data = M3GObject3D.getData(self) - data += struct.pack("<B5I", self.layer, - getId(self.compositingMode), - getId(self.fog), - getId(self.polygonMode), - getId(self.material), - len(self.textures)) - for element in self.textures: - data += struct.pack("<I",getId(element)) - return data - - def getDataLength(self): - value = M3GObject3D.getDataLength(self) - value += struct.calcsize("<B5I") - if len(self.textures) > 0 : - value += struct.calcsize("<"+str(len(self.textures))+'I') - return value - - - def writeJava(self,aWriter,aCreate): - if aCreate: - aWriter.write(2,"//Appearance") - aWriter.write(2,"Appearance BL%i = new Appearance();" % (self.id)) - if self.compositingMode!= None: - aWriter.write(2,"BL%i.setPolygonMode(BL%i);" % - (self.id,self.compositingMode.id)) - if self.fog!=None: - aWriter.write(2,"BL%i.setFog(BL%i);" % - (self.id,self.fog.id)) - if self.polygonMode!=None: - aWriter.write(2,"BL%i.setPolygonMode(BL%i);" % - (self.id,self.polygonMode.id)) - if self.material!=None: - aWriter.write(2,"BL%i.setMaterial(BL%i);" % - (self.id,self.material.id)) - i=0 - for itexture in self.textures: - aWriter.write(2,"BL%i.setTexture(%i,BL%i);" % - (self.id,i,itexture.id)) - i =+ 1 - M3GObject3D.writeJava(self,aWriter,False) - aWriter.write(2) - -class M3GTexture2D(M3GTransformable): - #M3G imposes the following restrictions when assigning textures to a model: - #The dimensions must be powers of two (4, 8, 16, 32, 64, 128...). - - WRAP_REPEAT = 241 - WRAP_CLAMP = 240 - FILTER_BASE_LEVEL=208 - FILTER_LINEAR=209 - FILTER_NEAREST=210 - FUNC_ADD=224 - FUNC_BLEND=225 - FUNC_DECAL=226 - FUNC_MODULATE=227 - FUNC_REPLACE=228 - - def __init__(self,aImage): - M3GTransformable.__init__(self) - self.ObjectType=17 - self.Image = aImage #ObjectIndex - self.blendColor=M3GColorRGB(0,0,0) - self.blending=M3GTexture2D.FUNC_MODULATE #Byte - self.wrappingS=M3GTexture2D.WRAP_REPEAT #Byte - self.wrappingT=M3GTexture2D.WRAP_REPEAT #Byte - self.levelFilter=M3GTexture2D.FILTER_BASE_LEVEL #Byte - self.imageFilter=M3GTexture2D.FILTER_NEAREST #Byte - - def searchDeep(self,alist): - alist = doSearchDeep([self.Image],alist) - return M3GTransformable.searchDeep(self,alist) - - def getData(self): - data = M3GTransformable.getData(self) - data += struct.pack('<I', getId(self.Image)) - data += self.blendColor.getData() - data += struct.pack('5B',self.blending, - self.wrappingS, - self.wrappingT, - self.levelFilter, - self.imageFilter) - return data - - def getDataLength(self): - value = M3GTransformable.getDataLength(self) - value += struct.calcsize('<I') - value += self.blendColor.getDataLength() - value += struct.calcsize('5B') - return value - - def writeJava(self,aWriter,aCreate): - if aCreate: - aWriter.write(2,"//Texture") - aWriter.write(2,"Texture2D BL%i = new Texture2D(BL%i);" % (self.id, - self.Image.id)) - aWriter.write(2,"BL%i.setFiltering(%i,%i);" % (self.id, - self.levelFilter, - self.imageFilter)) - aWriter.write(2,"BL%i.setWrapping(%i,%i);" % (self.id, - self.wrappingS, - self.wrappingT)) - aWriter.write(2,"BL%i.setBlending(%i);" % (self.id,self.blending)) - aWriter.write(2) - M3GTransformable.writeJava(self,aWriter,False) - -class ImageFactory: - images={} - def getImage(self, image, externalReference): - # It's important to use getFilename() because getName() returns a - # truncated string depending on the length of the file name. - filename = Blender.sys.expandpath(image.getFilename()) - - if self.images.has_key(filename): - image = self.images[filename] - elif externalReference: - # Check for file ending (only relevant for external images). The M3G specification - # mandates only PNG support, but some devices might also support additional image types. - [path,ext] = splitext(filename) - if ext != ".png": - print "Warning: image file ends with " + ext + ". M3G specification only mandates PNG support." - - image = M3GExternalReference() - image.URI = Blender.sys.basename(filename) - self.images[filename] = image - else: - image = M3GImage2D(image) - self.images[filename] = image - return image - - getImage = classmethod(getImage) - - -class M3GImage2D(M3GObject3D): - ALPHA=96 #a single byte per pixel, representing pixel opacity - LUMINANCE=97 #a single byte per pixel, representing pixel luminance. - LUMINANCE_ALPHA=98 #two bytes per pixel. The first: luminance, the second: alpha. - RGB=99 #three bytes per pixel, representing red, green and blue - RGBA=100 #four bytes per pixel, representing red, green, blue and alpha - - def __init__(self, aImage, aFormat=RGBA): - M3GObject3D.__init__(self) - self.ObjectType=10 - self.image=aImage #Blender Image - self.format=aFormat #Byte - self.isMutable=False #Boolean changable or not - [self.width, self.height] = aImage.getSize() - - #IF isMutable==false, THEN - self.palette=0 #Byte[] - self.pixels = array('B') #Byte[] - self.extractPixelsFromImage() - #END -#For a palettised format, the pixels array contains a single palette -#index per pixel, and the palette array will contain up to 256 entries, -#each consisting of a pixel specifier appropriate to the format chosen. - -#For a non-palettised format, the palette array will be empty, -#and the pixels array contains a pixel specifier appropriate to the format -#chosen. -#In a pixel specifier, each byte is scaled such that 0 represents the -#value 0.0 and 255 represents the value 1.0. The different formats -#require different data to be serialized, as follows: - -#The width and height of the image must be non-negative powers of two, but they need not be equal. - - def getData(self): - data = M3GObject3D.getData(self) - data += struct.pack('2B', self.format, self.isMutable) - data += struct.pack('<2I', self.width, self.height) - if self.isMutable == False: - # TODO: support palettised formats also - # export palette data - data += struct.pack('<I', 0) - - # export pixel data - if self.format == M3GImage2D.RGBA: - #print "len pixels",len(self.pixels) - data += struct.pack('<I', len(self.pixels)) - for pixel in self.pixels: - data += struct.pack('B', pixel) - #elif... - return data - - def getDataLength(self): - value = M3GObject3D.getDataLength(self) - value += struct.calcsize('2B') - value += struct.calcsize('<2I') - if self.isMutable == False: - # TODO: support palettised formats also - value+= struct.calcsize('<I') - - # pixel data size - if self.format == M3GImage2D.RGBA: - value += struct.calcsize('<I') - value += struct.calcsize(str(len(self.pixels))+'B') - return value - - def writeJava(self,aWriter,aCreate): - if aCreate: - lFileName = self.image.filename - if not Blender.sys.exists(lFileName) : - lFileName = Blender.sys.join(dirname(Blender.Get('filename')), - basename(self.image.filename)) - elif not Blender.sys.exists(lFileName): - raise FileError, 'Image file not found!' - lTargetFile = Blender.sys.join(Blender.sys.dirname(aWriter.filename), - Blender.sys.basename(self.image.filename)) - copy_file(lFileName,lTargetFile) - #shutil.copyfile(lFileName,lTargetFile) - aWriter.write(2,"//Image2D") - aWriter.write(2,"Image BL%i_Image = null;" % (self.id)) - aWriter.write(2,"try {") - aWriter.write(3,"BL%i_Image = Image.createImage(\"/%s\");" % - (self.id,basename(self.image.filename))) - aWriter.write(2,"} catch (IOException e) {") - aWriter.write(3,"e.printStackTrace();") - aWriter.write(2,"}") - aWriter.write(2,"Image2D BL%i = new Image2D(Image2D.RGBA,BL%i_Image);" % - (self.id,self.id)) - aWriter.write(2) - M3GObject3D.writeJava(self,aWriter,False) - aWriter.write(2) - - def extractPixelsFromImage(self): - # Reverse t coordiante because M3G uses a different 2D coordinate system than OpenGL. - for y in range(self.height): - for x in range(self.width): - [r, g, b, a] = self.image.getPixelI(x, self.height-1-y) - self.pixels.append(r) - self.pixels.append(g) - self.pixels.append(b) - self.pixels.append(a) - -class M3GAnimationController(M3GObject3D): - def __init__(self): - M3GObject3D.__init__(self) - self.ObjectType=1 - self.speed = 1.0 #Float32 - self.weight = 1.0 #Float32 - self.activeIntervalStart = 0 #Int32 - (always active) - self.activeIntervalEnd = 0 #Int32 - self.referenceSequenceTime = 0.0 #Float32 - self.referenceWorldTime = 0 #Int32 - - def writeJava(self,aWriter,aCreate): - if aCreate: - aWriter.writeClass("AnimationController",self) - aWriter.write(2,"AnimationController BL%i = new AnimationController();" % - (self.id)) - aWriter.write(2,"BL%i.setActiveInterval(%i, %i);" % - (self.id,self.activeIntervalStart,self.activeIntervalEnd)) - #lightAnim.setPosition(0, 2000);(2) Applying the animation during rendering - M3GObject3D.writeJava(self,aWriter,False) - - def getData(self): - data = M3GObject3D.getData(self) - data += struct.pack("<ffiifi", self.speed, - self.weight, - self.activeIntervalStart, - self.activeIntervalEnd, - self.referenceSequenceTime, - self.referenceWorldTime) - return data - - def getDataLength(self): - value = M3GObject3D.getDataLength(self) - return value + struct.calcsize("<ffiifi") - -class M3GAnimationTrack(M3GObject3D): - ALPHA=256 - AMBIENT_COLOR=257 - COLOR=258 - CROP=259 - DENSITY=260 - DIFFUSE_COLOR=261 - EMISSIVE_COLOR=262 - FAR_DISTANCE=263 - FIELD_OF_VIEW=264 - INTENSITY=265 - MORPH_WEIGHTS=266 - NEAR_DISTANCE=267 - ORIENTATION=268 - PICKABILITY=269 - SCALE=270 - SHININESS=271 - SPECULAR_COLOR=272 - SPOT_ANGLE=273 - SPOT_EXPONENT=274 - TRANSLATION=275 - VISIBILITY=276 - - def __init__(self,aSequence,aProperty): - M3GObject3D.__init__(self) - self.ObjectType = 2 - self.keyframeSequence = aSequence #ObjectIndex - self.animationController = None #ObjectIndex - self.propertyID = aProperty #UInt32 - - def getData(self): - data = M3GObject3D.getData(self) - data += struct.pack("<3I", getId(self.keyframeSequence), - getId(self.animationController), - self.propertyID) - return data - - def getDataLength(self): - value = M3GObject3D.getDataLength(self) - return value + struct.calcsize("<3I") - - def writeJava(self,aWriter,aCreate): - if aCreate: - aWriter.writeClass("AnimationTrack",self) - #print "self.id,self.keyframeSequence,self.propertyID",self.id,self.keyframeSequence,self.propertyID - aWriter.write(2,"AnimationTrack BL%i = new AnimationTrack(BL%i,%i);" % - (self.id,self.keyframeSequence.id,self.propertyID)) - aWriter.write(2,"BL%i.setController(BL%i);" % - (self.id,self.animationController.id)) - M3GObject3D.writeJava(self,aWriter,False) - - def searchDeep(self,alist): - alist = doSearchDeep([self.keyframeSequence, self.animationController],alist) - return M3GObject3D.searchDeep(self,alist) - -class M3GKeyframeSequence(M3GObject3D): - CONSTANT=192 - LINEAR=176 - LOOP=193 - SLERP=177 - SPLINE=178 - SQUAD=179 - STEP=180 - - def __init__(self,aNumKeyframes, aNumComponents,aBlenderInterpolation, - aM3GInterpolation=None): - M3GObject3D.__init__(self) - self.ObjectType = 19 - if aM3GInterpolation!=None: - self.interpolation = aM3GInterpolation - else: - if aBlenderInterpolation == "Constant": - self.interpolation = self.STEP #Byte - elif aBlenderInterpolation == "Bezier": - self.interpolation = self.SPLINE #Byte - elif aBlenderInterpolation == "Linear": - self.interpolation = self.LINEAR #Byte - else: - pass # TODO : Throw Error - self.repeatMode = self.CONSTANT #Byte CONSTANT or LOOP - self.encoding = 0 #Byte 0=raw - # TODO: Other encodings - self.duration = 0 #UInt32 - self.validRangeFirst = 0 #UInt32 - self.validRangeLast = 0 #UInt32 - self.componentCount = aNumComponents #UInt32 - self.keyframeCount = aNumKeyframes #UInt32 - #IF encoding == 0 - #FOR each key frame... - self.time = [] #Int32 - self.vectorValue = [] # Float32[componentCount] - #END - #ELSE IF encoding == 1 - #Float32[componentCount] vectorBias; - #Float32[componentCount] vectorScale; - #FOR each key frame... - #Int32 time; - #Byte[componentCount] vectorValue; - #END - #ELSE IF encoding == 2 - #Float32[componentCount] vectorBias; - #Float32[componentCount] vectorScale; - #FOR each key frame... - #Int32 time; - #UInt16[componentCount] vectorValue; - #END - #END - -#All of the vectorValue arrays are the same size, so a separate count is stored outside the individual -#keyframe's data rather than with each array. The encoding field indicates the encoding scheme to be used for the keyframe data. Only the -#nominated values above are allowed. Other values must be treated as errors. - -#•Encoding 0 indicates that the values are stored "raw" as floats. -#•Encodings 1 and 2 indicate that the values are quantized to 1 or 2 bytes. For each component, -#a bias and scale are calculated from the sequence of values for that component. The bias is the -#mimimum value, the scale is the maximum value minus the minimum value. The raw values -#are then converted to a value 0..1 by subtracting the bias and dividing by the scale. These raw -#values are then quantized into the range of a Byte or UInt16 by multiplying by 255 or 65535 -#respectively. The converse operation restores the original value from the quantized values. - - def beforeExport(self): - #M3G can not work with negative zero - #print"beforeExport ID= ",self.id - for i in range(self.keyframeCount): - for j in range(self.componentCount): - x = struct.pack("<f",self.vectorValue[i][j]) - y = struct.unpack("<f",x) - #print "beforeExport i,j ",i,j,self.vectorValue[i][j],y - if abs(self.vectorValue[i][j]) < 0.000001 : - #print "Negative Zero found!",self.vectorValue[i][j] - self.vectorValue[i][j]=0.0 - #print "zero ",self.vectorValue[i][j] - - def getData(self): - self.beforeExport() - data = M3GObject3D.getData(self) - data += struct.pack("<3B5I",self.interpolation, - self.repeatMode, - self.encoding, - self.duration, - self.validRangeFirst, - self.validRangeLast, - self.componentCount, - self.keyframeCount) - #FOR each key frame... - for i in range(self.keyframeCount): - data += struct.pack("<i",self.time[i]) #Int32 - for j in range(self.componentCount): - data += struct.pack("<f",self.vectorValue[i][j]) # Float32[componentCount] - return data - - def getDataLength(self): - value = M3GObject3D.getDataLength(self) - value += struct.calcsize("<3B5I") - value += struct.calcsize("<i") * self.keyframeCount - value += struct.calcsize("<f") * self.keyframeCount * self.componentCount - return value - - def setRepeatMode(self,aBlenderMode): - if aBlenderMode == "Constant" : - self.repeatMode = self.CONSTANT - elif aBlenderMode == "Cyclic": - self.repeatMode = self.LOOP - else: - print "In IPO: Mode " + aBlenderMode + " is not assisted!" - - def setKeyframe(self, aIndex, aTime, aVector): - self.time.append(aTime) - self.vectorValue.append(aVector) - - def writeJava(self,aWriter,aCreate): - self.beforeExport() - if aCreate: - aWriter.writeClass("KeyframeSequence",self) - aWriter.write(2,"KeyframeSequence BL%i = new KeyframeSequence(%i, %i, %i);" % - (self.id,self.keyframeCount,self.componentCount,self.interpolation)) - for i in range(len(self.time)): - lLine = "BL%i.setKeyframe(%i,%i, new float[] { %ff, %ff, %ff" % \ - (self.id,i,self.time[i],self.vectorValue[i][0], \ - self.vectorValue[i][1],self.vectorValue[i][2]) - if self.componentCount == 4: - lLine += ", %ff" % (self.vectorValue[i][3]) - lLine += "});" - aWriter.write(2,lLine) - # TODO : Works only with componentCount = 3 - aWriter.write(2,"BL%i.setDuration(%i);" % (self.id, self.duration)) - aWriter.write(2,"BL%i.setRepeatMode(%i);" % (self.id,self.repeatMode)) - M3GObject3D.writeJava(self,aWriter,False) - -# ---- Translator -------------------------------------------------------------- # - -class M3GTranslator: - "Trys to translate a blender scene into a mg3 World" - - def __init__(self): - self.world = None - self.scene = None - self.nodes = [] - - def start(self): - print "Translate started ..." - - self.scene = Blender.Scene.GetCurrent() - self.world = self.translateWorld(self.scene) - - for obj in self.scene.objects : - if obj.getType()=='Camera': # older Version: isinstance(obj.getData(),Types.CameraType) - self.translateCamera(obj) - elif obj.getType()=='Mesh': - self.translateMesh(obj) - elif obj.getType()=='Lamp' and mOptions.lightingEnabled: # older Version: isinstance(obj.getData(),Types.LampType) - self.translateLamp(obj) - elif obj.getType()=='Empty': - self.translateEmpty(obj) - else: - print "Warning: could not translate" + str(obj) + ". Try to convert object to mesh using Alt-C" - - self.translateParenting() - - print "Translate finished." - return self.world - - def translateParenting(self): - for iNode in self.nodes: - if iNode.parentBlenderObj == None: - self.world.children.append(iNode) - else: - for jNode in self.nodes: - if iNode.parentBlenderObj == jNode.blenderObj: - #TODO : Every object can be parent - jNode.children.append(iNode) - #lMatrix = Matrix(iNode.blenderMatrixWorld) * Matrix(jNode.blenderMatrixWorld).invert() - lMatrix = self.calculateChildMatrix(iNode.blenderMatrixWorld,jNode.blenderMatrixWorld) - iNode.transform = self.translateMatrix(lMatrix) - iNode.hasGeneralTransform=True - break - - def calculateChildMatrix(self,child,parent): - return Matrix(child) * Matrix(parent).invert() - - def translateArmature(self,obj,meshObj,aSkinnedMesh): - print "translate Armature ..." - #print "translateArmature::aSkinnedMesh.vertexBuffer:",aSkinnedMesh.vertexBuffer - armature = obj.getData() - - #Pose - #pose = obj.getPose() - #print "pose ",pose - #for bone in pose.bones.values(): - # print "bone local",bone.localMatrix - # print "bone pose",bone.poseMatrix - - #Skeleton - mGroup = M3GGroup() - self.translateCore(obj,mGroup) - aSkinnedMesh.skeleton = mGroup - mGroup.transform = self.translateMatrix( - self.calculateChildMatrix(obj.matrixWorld, - meshObj.matrixWorld)) - - #Bones - #print "armature:",armature.bones - for bone in armature.bones.values(): #Copy Bones - mBone = M3GBone() - mBone.transformNode = M3GGroup() - self.translateCore(bone, mBone.transformNode) - #mBone.transformNode.transform = self.translateMatrix(pose.bones[bone.name].poseMatrix)#Test!!!! - #print "node transform", mBone.transformNode.transform - #mBone.transformNode.transform=self.translateMatrix(self.calculateChildMatrix(bone.matrix['ARMATURESPACE'],meshObj.matrixWorld)) - if bone.hasParent(): - mBone.transformNode.transform = self.translateMatrix( - self.calculateChildMatrix(bone.matrix['ARMATURESPACE'], - bone.parent.matrix['ARMATURESPACE'])) - mBone.weight = bone.weight - aSkinnedMesh.bones[bone.name]=mBone - - rootBone = [] #Copy Child-Parent-Structure - for bone in armature.bones.values(): - mBone = aSkinnedMesh.bones[bone.name] - if not bone.hasParent(): - rootBone.append(mBone) - if bone.hasChildren(): - for childBone in bone.children: - mChildBone = aSkinnedMesh.bones[childBone.name] - mBone.transformNode.children.append(mChildBone.transformNode) - for rbone in rootBone: - aSkinnedMesh.skeleton.children.append(rbone.transformNode) - - #VertexGroups - Skinning - if armature.vertexGroups: - for boneName in aSkinnedMesh.bones.keys(): - aSkinnedMesh.bones[boneName].setVerts(self.translateVertsGroup(meshObj.getData(False,True).getVertsFromGroup(boneName), - aSkinnedMesh)) - #Envelope - Skinning - if armature.envelopes: - pass #TODO - - #Action - self.translateAction(obj,aSkinnedMesh) - aSkinnedMesh.addSecondBone() - - - def translateVertsGroup(self,group,aSkinnedMesh): - #print "group: ",group - #print "items: ",aSkinnedMesh.getBlenderIndexes().items() - ergebnis = [int(k) for k,v in aSkinnedMesh.getBlenderIndexes().items() if v in group] - #print "ergebnis: ",ergebnis - return ergebnis - - def translateAction(self,armatureObj,aSkinnedMesh): - action = armatureObj.getAction() - if action==None: return - - print "tranlating Action ..." - if mOptions.exportAllActions: - lArmatureID = self.translateUserID(armatureObj.getData().name) - print "armatureID ", lArmatureID, armatureObj - for a in Blender.Armature.NLA.GetActions().values(): - (lArmatureActionID,lEndFrame,lActionID) = self.translateActionName(a.name) - #print "action", a - #print "lArmatureID", lArmatureActionID - #print "lEndFrame", lEndFrame - #print "lActionID", lActionID - if lArmatureActionID == lArmatureID: - #print "Action found" - mController = self.translateActionIPOs(a,aSkinnedMesh,lEndFrame) - mController.userID = lActionID - #print "mController.userID ",mController.userID - - #print "getActionScripts() ", Blender.Armature.NLA.getActionStrips() - else: - self.translateActionIPOs(action,aSkinnedMesh) - - - def translateActionIPOs(self,aAction,aSkinnedMesh,aEndFrame=0): - ipos = aAction.getAllChannelIpos() - mController=None - for boneName in aSkinnedMesh.bones.keys(): - if ipos.has_key(boneName): - ipo = ipos[boneName] - if mController==None: mController = M3GAnimationController() - self.translateIpo(ipo,aSkinnedMesh.bones[boneName].transformNode,mController,aEndFrame) - return mController - - def translateActionName(self,name): - # <Action Name>#A<M3G ID of Armature>E<End Frame>#<ID of Action> - lError = "Armature name " + name + " is not ok. Perhaps you should set option 'ExportAllAction' to false." - #print "name ", name - lLetter = name.find("#") - if lLetter == -1 :raise Exception(lError) - if name[lLetter+1]!='A': raise Exception(lError) - lName = name[lLetter+2:] - #print "lName ", lName - lLetter = lName.find("E") - #print "lLetter ", lLetter - if lLetter == -1 :raise Exception(lError) - #print "lName[:]", lName[:0] - lArmatureID = int(lName[:lLetter]) - lName = lName[lLetter+1:] - lLetter = lName.find("#") - if lLetter == -1:raise Exception(lError) - lEndFrame = int(lName[:lLetter]) - lActionID = int(lName[lLetter+1:]) - return (lArmatureID,lEndFrame,lActionID) - - - def translateWorld(self,scene): - "creates world object" - world = M3GWorld() - - #Background - world.background = M3GBackground() - blWorld= scene.world - #AllWorlds = Blender.World.Get() # Set Color - #if len(AllWorlds)>=1: # world object available - if blWorld != None: - world.background.backgroundColor=self.translateRGBA(blWorld.getHor(),0) # horizon color of the first world - if mOptions.createAmbientLight & mOptions.lightingEnabled: - lLight = M3GLight() - lLight.mode = lLight.modes['AMBIENT'] - lLight.color = self.translateRGB(blWorld.getAmb()) - self.nodes.append(lLight) - - #TODO: Set background picture from world - - return world - - def translateEmpty(self,obj): - print "translate empty ..." - mGroup = M3GGroup() - self.translateToNode(obj,mGroup) - - def translateCamera(self,obj): - print "translate camera ..." - camera = obj.getData() - if camera.getType()!=0: - print "Only perscpectiv cameras will work korrekt" - return #Type=0 'perspectiv' Camera will be translated - mCamera = M3GCamera() - mCamera.projectionType=mCamera.PERSPECTIVE - mCamera.fovy=60.0 # TODO: Calculate fovy from Blender.lens - mCamera.AspectRatio=4.0/3.0 # TODO: different in every device - mCamera.near=camera.getClipStart() - mCamera.far=camera.getClipEnd() - self.translateToNode(obj,mCamera) - self.world.activeCamera = mCamera # Last one is always the active one - - - def translateMaterials(self, aMaterial, aMesh, aMatIndex, createNormals, createUvs): - print "translate materials ..." - - mAppearance = M3GAppearance() - - if createNormals: - mMaterial = M3GMaterial() - mMaterial.name = aMaterial.name - mMaterial.diffuseColor = self.translateRGBA(aMaterial.rgbCol,1.0) #ColorRGBA - #material.specularColor= self.translateRGB(mat.specCol) #ColorRGB - mAppearance.material = mMaterial - - if createUvs: - # Search file name in mesh face. - lImage = None - for iface in aMesh.faces: - if iface.mat==aMatIndex: - if iface.image != None: - lImage = iface.image - break - if lImage==None: - raise Exception("Mesh " + aMesh.name + ": No image found for uv-texture! Perhaps no uv-coordinates ?") - - # M3G requires textures to have power-of-two dimensions. - [width, height] = lImage.getSize() - powerWidth = 1 - while (powerWidth < width): - powerWidth *= 2 - powerHeight = 1 - while (powerHeight < height): - powerHeight *= 2 - if powerWidth != width or powerHeight != height: - raise Exception("Image " + lImage.filename + ": width and height must be power-of-two!") - - # ImageFactory reuses existing images. - mImage = ImageFactory.getImage(lImage, mOptions.textureExternal) - mTexture = M3GTexture2D(mImage) - mAppearance.textures.append(mTexture) - - mPolygonMode=M3GPolygonMode() - mPolygonMode.perspectiveCorrectionEnabled = mOptions.perspectiveCorrection - if not aMesh.mode & Modes.TWOSIDED: - mPolygonMode.culling=M3GPolygonMode.CULL_BACK - else: - mPolygonMode.culling=M3GPolygonMode.CULL_NONE - if mOptions.smoothShading: - mPolygonMode.shading=M3GPolygonMode.SHADE_SMOOTH - else: - mPolygonMode.shading=M3GPolygonMode.SHADE_FLAT - - mAppearance.polygonMode = mPolygonMode - - return mAppearance - - - def translateMesh(self,obj): - print "translate mesh ..." + str(obj) - - # Mesh data. - mesh = obj.getData(False, True) # get Mesh not NMesh object - if len(mesh.faces) <= 0: # no need to process empty meshes - print "Empty mesh " + str(obj) + " not processed." - return - - vertexBuffer = M3GVertexBuffer() - positions = M3GVertexArray(3, 2) # 3 coordinates - 2 bytes - if mOptions.autoscaling: positions.useMaxPrecision(mesh.verts) - indexBuffers = [] - appearances = [] - print str(len(mesh.materials)) + " material(s) found." - - # Texture coordinates. - createUvs = False - if mOptions.textureEnabled & mesh.faceUV: - for material in mesh.materials: - if material.getMode() & Material.Modes.TEXFACE: createUvs = True; - - if createUvs: - if mOptions.autoscaling: - uvCoordinates = M3GVertexArray(2,2,True,True) #2 coordinates - 2 bytes - autoscaling - else: - uvCoordinates = M3GVertexArray(2, 2) #2 coordinates - 2 bytes - uvCoordinates.bias[0] = 0.5 - uvCoordinates.bias[1] = 0.5 - uvCoordinates.bias[2] = 0.5 - uvCoordinates.scale = 1.0/65535.0 - else: - uvCoordinates = None - - # Normals. - createNormals = False - if mOptions.lightingEnabled: - for material in mesh.materials: - if not (material.getMode() & Material.Modes.SHADELESS): createNormals = True; - - if createNormals: - normals = M3GVertexArray(3, 1) # 3 coordinates - 1 byte - else: - normals = None - - # Create a submesh for each material. - for materialIndex, material in enumerate(mesh.materials): - faces = [face for face in mesh.faces if face.mat == materialIndex] - if len(faces) >= 0: - indexBuffers.append(self.translateFaces(faces, positions, normals, uvCoordinates, createNormals, createUvs)) - appearances.append(self.translateMaterials(material, mesh, materialIndex, createNormals, createUvs)) - - # If the above didn't result in any IndexBuffer (e.g. there's no material), write a single IndexBuffer - # with all faces and a default Appearance. - if len(indexBuffers) == 0: - indexBuffers.append(self.translateFaces(mesh.faces, positions, normals, uvCoordinates, createNormals, createUvs)) - appearances.append(M3GAppearance()) - - vertexBuffer.setPositions(positions) - if createNormals: vertexBuffer.normals = normals - if createUvs: vertexBuffer.texCoordArrays.append(uvCoordinates) - - parent = obj.getParent() - if parent!=None and parent.getType()=='Armature': #Armatures ? - mMesh = M3GSkinnedMesh(vertexBuffer,indexBuffers,appearances) - #print"vertexBuffer.positions:",vertexBuffer.positions - print"mMesh.vertexBuffer:",mMesh.vertexBuffer - self.translateArmature(parent,obj,mMesh) - else: - mMesh = M3GMesh(vertexBuffer,indexBuffers,appearances) - - self.translateToNode(obj,mMesh) - - #Do Animation - self.translateObjectIpo(obj,mMesh) - - def translateFaces(self, faces, positions, normals, uvCoordinates, createNormals, createUvs): - """Translates a list of faces into vertex data and triangle strips.""" - - # Create vertices and triangle strips. - indices = [0, 0, 0, 0] - triangleStrips = M3GTriangleStripArray() - - for face in faces: - for vertexIndex, vertex in enumerate(face.verts): - # Find candidates for sharing (vertices with same Blender ID). - vertexCandidateIds = [int(k) for k, v in positions.blenderIndexes.items() if v == vertex.index] - - # Check normal. - if createNormals and not face.smooth: - # For solid faces, a vertex can only be shared if the the face normal is - # the same as the normal of the shared vertex. - for candidateId in vertexCandidateIds[:]: - for j in range(3): - if face.no[j]*127 != normals.components[candidateId*3 + j]: - vertexCandidateIds.remove(candidateId) - break - - # Check texture coordinates. - if createUvs: - # If texture coordinates are required, a vertex can only be shared if the - # texture coordinates match. - for candidateId in vertexCandidateIds[:]: - s = int((face.uv[vertexIndex][0]-0.5)*65535) - t = int((0.5-face.uv[vertexIndex][1])*65535) - if (s != uvCoordinates.components[candidateId*2 + 0]) or (t != uvCoordinates.components[candidateId*2 + 1]): - vertexCandidateIds.remove(candidateId) - - if len(vertexCandidateIds) > 0: - # Share the vertex. - indices[vertexIndex] = vertexCandidateIds[0] - else: - # Create new vertex. - positions.append(vertex, vertex.index) - indices[vertexIndex] = len(positions.components)/3 - 1 - - # Normal. - if createNormals: - for j in range(3): - if face.smooth: - normals.append(int(vertex.no[j]*127)) # vertex normal - else: - normals.append(int(face.no[j]*127)) # face normal - - # Texture coordinates. - if createUvs: - lUvCoordinatesFound = True - print "face.uv[vertexIndex][0]:",face.uv[vertexIndex][0] - print "face.uv[vertexIndex][1]:",face.uv[vertexIndex][1] - if mOptions.autoscaling: - uvCoordinates.append(face.uv[vertexIndex][0]) - uvCoordinates.append(face.uv[vertexIndex][1]) - else: - uvCoordinates.append(int((face.uv[vertexIndex][0]-0.5)*65535)) - # Reverse t coordinate because M3G uses a different 2D coordinate system than Blender. - uvCoordinates.append(int((0.5-face.uv[vertexIndex][1])*65535)) - - # IndexBuffer. - triangleStrips.stripLengths.append(len(face.verts)) - if len(face.verts) > 3 : - triangleStrips.indices += [indices[1], indices[2], indices[0], indices[3]] # quad - else : - triangleStrips.indices += [indices[0], indices[1], indices[2]] # tri - - return triangleStrips - - - def translateObjectIpo(self,obj,aM3GObject): - if obj.getIpo() == None : return #No Ipo available - print "translate Ipo ..." - - lIpo = obj.getIpo() - self.translateIpo(lIpo,aM3GObject) - - - def translateIpo(self,aIpo,aM3GObject,aM3GAnimContr=None,aEndFrame=0): - #Print info about curves - #for iCurve in lIpo.getCurves(): - # print "Extrapolation",iCurve.getExtrapolation() #Constant, Extrapolation, Cyclic or Cyclic_extrapolation - # print "Interpolation",iCurve.getInterpolation() #Constant, Bezier, or Linear - # print "Name",iCurve.getName() - # for iPoint in iCurve.getPoints(): - # print "Knode points",iPoint.getPoints() - types = ['Loc','Rot','Size','Quat'] - - for type in types: - if aIpo.getCurve(type+'X'): - self.translateIpoCurve(aIpo,aM3GObject,type,aM3GAnimContr,aEndFrame) - - - def translateIpoCurve(self,aIpo,aM3GObject,aCurveType,aM3GAnimContr,aEndFrame=0): - - lContext = self.scene.getRenderingContext() - if aEndFrame==0: - lEndFrame = lContext.endFrame() - else: - lEndFrame = aEndFrame - - lTimePerFrame = 1.0 / lContext.framesPerSec() * 1000 - - lCurveX = aIpo.getCurve(aCurveType+'X') - lCurveY = aIpo.getCurve(aCurveType+'Y') - lCurveZ = aIpo.getCurve(aCurveType+'Z') - if aCurveType=='Quat': lCurveW = aIpo.getCurve(aCurveType+'W') - - lInterpolation = None - if aCurveType == 'Rot' or aCurveType == 'Quat': - lTrackType = M3GAnimationTrack.ORIENTATION - lNumComponents=4 - lCurveFactor= 10 #45 Degrees = 4,5 - if aCurveType == 'Quat': - lTrackType = M3GAnimationTrack.ORIENTATION - lNumComponents=4 - lCurveFactor= 1 - lInterpolation = M3GKeyframeSequence.SLERP - #lInterpolation = M3GKeyframeSequence.SQUAD - elif aCurveType == 'Size': - lTrackType = M3GAnimationTrack.SCALE - lNumComponents=3 - lCurveFactor=1 - else: - lTrackType = M3GAnimationTrack.TRANSLATION - lNumComponents=3 - lCurveFactor=1 - - mSequence = M3GKeyframeSequence(len(lCurveX.getPoints()), - lNumComponents, - lCurveX.getInterpolation(), - lInterpolation) - - #print 'ComponentCount',mSequence.componentCount - - mSequence.duration = lEndFrame * lTimePerFrame - mSequence.setRepeatMode(lCurveX.getExtrapolation()) - - lIndex = 0 - for iPoint in lCurveX.getPoints(): - lPoint = iPoint.getPoints() - - lPointList = [(lPoint[1]*lCurveFactor), - (lCurveY.evaluate(lPoint[0])*lCurveFactor), - (lCurveZ.evaluate(lPoint[0])*lCurveFactor)] - - #print "aCurveType ", aCurveType - - if aCurveType == 'Loc': - #print "PointList ", lPointList - #lorgTransVector = aM3GObject.blenderTransformMatrix.translationPart() - #ltrans = TranslationMatrix(Vector(lPointList)) - #ltrans2 = self.calculateChildMatrix(ltrans,aM3GObject.blenderTransformMatrix) - #lVector = ltrans2.translationPart() + lorgTransVector - #lPointList = [lVector.x, lVector.y,lVector.z] - #print "PointList ", lPointList - pass - - if aCurveType == 'Quat': - lPointList.append(lCurveW.evaluate(lPoint[0])*lCurveFactor) - #lQuat = Quaternion([lPointList[3],lPointList[0],lPointList[1],lPointList[2]]) - #print "Quat ", lQuat - #print "Quat.angel ", lQuat.angle - #print "Quat.axis ", lQuat.axis - #print "PointList ", lPointList - - #print "PointList",lPointList - - if aCurveType =='Rot': - lQuat = Euler(lPointList).toQuat() - #lPointList = [lQuat.w,lQuat.x,lQuat.y,lQuat.z] - lPointList = [lQuat.x,lQuat.y,lQuat.z,lQuat.w] - #print " Quat=", lPointList - - mSequence.setKeyframe(lIndex, - lPoint[0]*lTimePerFrame, - lPointList) - lIndex += 1 - mSequence.validRangeFirst = 0 - mSequence.validRangeLast = lIndex - 1 - - mTrack = M3GAnimationTrack(mSequence,lTrackType) - aM3GObject.animationTracks.append(mTrack) - if aM3GAnimContr==None: aM3GAnimContr = M3GAnimationController() - mTrack.animationController = aM3GAnimContr - - - def translateLamp(self,obj): - print "translate lamp ..." - lamp = obj.getData() - - #Type - lampType=lamp.getType() - if not lampType in [Lamp.Types.Lamp,Lamp.Types.Spot,Lamp.Types.Sun]: - print "INFO: Type of light is not supported. See documentation" - return #create not light; type not supported - mLight = M3GLight() - if lampType == Lamp.Types.Lamp: - mLight.mode = mLight.modes['OMNI'] - elif lampType == Lamp.Types.Spot: - mLight.mode = mLight.modes['SPOT'] - elif lampType == Lamp.Types.Sun: - mLight.mode = mLight.modes['DIRECTIONAL'] - #Attenuation (OMNI,SPOT): - if lampType in [Lamp.Types.Lamp,Lamp.Types.Spot]: - mLight.attenuationConstant = 0.0 - mLight.attenuationLinear = 2.0/lamp.dist - mLight.attenuationQuadratic = 0.0 - #Color - mLight.color = self.translateRGB(lamp.col) - #Energy - mLight.intensity = lamp.energy - #SpotAngle, SpotExponent (SPOT) - if lampType == Lamp.Types.Spot: - mLight.spotAngle = lamp.spotSize/2 - mLight.spotExponent = lamp.spotBlend - self.translateToNode(obj,mLight) - - - def translateCore(self,obj,node): - #Name - node.name = obj.name - node.userID = self.translateUserID(obj.name) - #Location - #node.translation=self.translateLoc(obj.LocX,obj.LocY,obj.LocZ - #node.hasComponentTransform=True - #Transform - #node.transform = self.translateMatrix(obj.getMatrix('localspace')) - if type(obj) is Types.BoneType: - #print "BoneMatrix ",obj.matrix['BONESPACE'] - node.transform = self.translateMatrix(obj.matrix['ARMATURESPACE']) - #'ARMATURESPACE' - this matrix of the bone in relation to the armature - #'BONESPACE' - the matrix of the bone in relation to itself - else: - node.transform = self.translateMatrix(obj.matrixWorld) - node.hasGeneralTransform=True - - - def translateToNode(self,obj,node): - self.translateCore(obj,node) - #Nodes - self.nodes.append(node) - #Link to Blender Object - node.blenderObj = obj - node.blenderMatrixWorld = obj.matrixWorld - lparent = None - if obj.getParent()!=None: - if obj.getParent().getType()!='Armature': - lparent = obj.getParent() - else: - if obj.getParent().getParent()!=None and obj.getParent().getParent().getType()!='Armature': - lparent = obj.getParent().getParent() - node.parentBlenderObj = lparent - - - def translateUserID(self, name): - id = 0 - start = name.find('#') - - # Use digits that follow the # sign for id. - if start != -1: - start += 1 - end = start - for char in name[start:]: - if char.isdigit(): - end += 1 - else: - break - - if end > start: - id = int(name[start:end]) - - return id - - def translateLoc(self,aLocX,aLocY,aLocZ): - return M3GVector3D(aLocX,aLocY,aLocZ) - - def translateRGB(self,color): - return M3GColorRGB(int(color[0]*255), - int(color[1]*255), - int(color[2]*255)) - - def translateRGBA(self,color,alpha): - return M3GColorRGBA(int(color[0]*255), - int(color[1]*255), - int(color[2]*255), - int(alpha*255)) - - def translateMatrix(self,aPyMatrix): - """ - 0 1 2 3 - 4 5 6 7 - 8 9 10 11 - 12 13 14 15 """ - #print "Matrix:", aPyMatrix - lMatrix = M3GMatrix() - lMatrix.elements[0] = aPyMatrix[0][0] - lMatrix.elements[1] = aPyMatrix[1][0] - lMatrix.elements[2] = aPyMatrix[2][0] - lMatrix.elements[3] = aPyMatrix[3][0] - lMatrix.elements[4] = aPyMatrix[0][1] - lMatrix.elements[5] = aPyMatrix[1][1] - lMatrix.elements[6] = aPyMatrix[2][1] - lMatrix.elements[7] = aPyMatrix[3][1] - lMatrix.elements[8] = aPyMatrix[0][2] - lMatrix.elements[9] = aPyMatrix[1][2] - lMatrix.elements[10] = aPyMatrix[2][2] - lMatrix.elements[11] = aPyMatrix[3][2] - lMatrix.elements[12] = aPyMatrix[0][3] - lMatrix.elements[13] = aPyMatrix[1][3] - lMatrix.elements[14] = aPyMatrix[2][3] - lMatrix.elements[15] = aPyMatrix[3][3] - return lMatrix - - -# ---- Exporter ---------------------------------------------------------------- # - -class M3GExporter: - "Exports Blender-Scene to M3D" - def __init__(self, aWriter): - self.writer = aWriter - - - def start(self): - print "Info: starting export ..." - #rpdb2.start_embedded_debugger("t",True) - Translator = M3GTranslator() - world = Translator.start() - - #sys.settrace(tracer) - exportList = self.createDeepSearchList(world) - externalReferences = [element for element in exportList if element.__class__ is M3GExternalReference] - exportList = [element for element in exportList if element.__class__ is not M3GExternalReference] - #sys.settrace(None) - - # 1 is reservated for HeaderObject. - i=1 - - # Next are the external references. - for element in externalReferences: - i += 1 - element.id = i - print "object ",element.id, element - - # And the standard scene objects. - for element in exportList: - i += 1 - element.id = i - print "object ",element.id, element - - self.writer.writeFile(world, exportList, externalReferences) - - print("Ready!") - - - def createDeepSearchList(self,aWorld): - "creates the right order for saving m3g : leafs first" - return aWorld.searchDeep([]) - - - -# ---- Writer ---------------------------------------------------------------- # -class JavaWriter: - "writes a java class which creates m3g-Scene in a j2me programm" - def __init__(self,aFilename): - self.filename = aFilename - self.classname = Blender.sys.basename(aFilename) - self.classname = self.classname[:-5] #without extention ".java" - self.outFile = file(aFilename,"w") - - def write(self, tab, zeile=""): - "writes to file" - #print "\t" * tab + zeile - print >>self.outFile, "\t" * tab + zeile - - def writeFile(self,aWorld,aExportList,externalReferences): - self.world = aWorld - self.writeHeader() - for element in aExportList: - element.writeJava(self,True) - self.writeFooter() - self.outFile.close() - - def writeHeader(self): - "writes class header" - self.write(0,"import javax.microedition.lcdui.Image;") - self.write(0,"import javax.microedition.m3g.*;") - self.write(0,"public final class "+self.classname+" {") - self.write(1,"public static World getRoot(Canvas3D aCanvas) {") - - def writeFooter(self): - self.write(1) - self.write(1,"return BL"+str(self.world.id)+";") - self.write(0,"}}") - - def writeList(self,alist,numberOfElementsPerLine=12,aType=""): - '''Writes numberOfElementsPerLine''' - line="" - lastLine="" - counter=0 - for element in alist: - if counter!=0: - line = line + "," + str(element) + aType - else: - line = str(element) + aType - counter = counter + 1 - if counter == numberOfElementsPerLine: - if len(lastLine)>0: - self.write(3,lastLine+",") - lastLine=line - line="" - counter = 0 - if len(lastLine)>0: - if len(line)>0: - self.write(3,lastLine+",") - else: - self.write(3,lastLine) - if len(line) > 0: self.write(3,line) - - def writeClass(self,aName,aM3GObject): - self.write(2) - self.write(2,"//"+aName+":"+aM3GObject.name) - - -class M3GSectionObject: - def __init__(self,aObject): - """Object Structure - Each object in the file represents one object in the - scene graph tree, and is stored in a chunk. The - structure of an object chunk is as follows: - Byte ObjectType - UInt32 Length - Byte[] Data""" - #ObjectType - #This field describes what type of object has been serialized. - #The values 0 and 0xFF are special: 0 represents the header object, - #and 0xFF represents an external reference. - #Example: Byte ObjectType = 14 - self.ObjectType = aObject.ObjectType - self.data = aObject.getData() - self.length = aObject.getDataLength() - - def getData(self): - data = struct.pack('<BI',self.ObjectType,self.length) - data += self.data - return data - - def getDataLength(self): - return struct.calcsize('<BI') + self.length - -class M3GSection: - '''Part of a M3G binary file' - Section Structur - Byte CompressionScheme - UInt32 TotalSectionLength - UInt32 UncompressedLength - Byte[] Objects - UInt32 Checksum ''' - def __init__(self,aObjectList,compressed=False): - self.CompressionScheme=0 - self.TotalSectionLength=0 #including the CompressionScheme, - #TotalSectionLength, UncompressedLength, - #Objects and Checksum fields, - self.UncompressedLength=0 #Length of Objects uncompresses - self.Objects = '' - for element in aObjectList: - lObject = M3GSectionObject(element) - #print "Obj:", lObject, lObject.getDataLength(), len(lObject.getData()) - self.Objects += lObject.getData() - self.UncompressedLength += lObject.getDataLength() - self.TotalSectionLength=struct.calcsize('<BIII')+self.UncompressedLength - - def getData(self): - data = struct.pack('<BII',self.CompressionScheme, - self.TotalSectionLength, - self.UncompressedLength) - data += self.Objects - #self.Checksum = zlib.adler32(data) - self.Checksum = self.ownAdler32(data) - print "Checksum",self.Checksum - #print "Own Checksum",self.ownAdler32(data) - return data + struct.pack('<I',self.Checksum) - - def ownAdler32(self,data): - s1 = int(1) #uint32_t - s2 = int(0) #uint32_t - for n in data: - s1 = (s1 + int(struct.unpack("B",n)[0])) % 65521 - s2 = (s2 + s1) % 65521 - return (s2 << 16) + s1 - - def getLength(self): - return self.TotalSectionLength - - def write(self,aFile): - print "Write Section.." - print "TotalSectionLength:", str(self.TotalSectionLength) - aFile.write(self.getData()) - - #CompressionScheme - #Example Byte CompressionScheme = 1; - #0 Uncompressed, Adler32 Checksum - #1 ZLib compression, 32 k buffer size, Adler32 Checksum - #2...255 Reserved - #TotalSectionLength: total length of the section in bytes - #Example: UInt32 TotalSectionLength = 2056 - #UncompressedLength - #contains the length of the Objects field after decompression. - #If no compression is specified for this section, - #this equals the actual number of bytes serialized in the Objects array. - #CompressionScheme - #Currently, only the Adler32 checksum is mandatory. - #The checksum is calculated using all preceding bytes in - #the section, i.e. the CompressionScheme,TotalSectionLength, - #UncompressedLength, and the actual serialized data in the - #Objects field (i.e. in its compressed form if compression is speci- - #fied). - #Example: UInt32 Checksum = 0xffe806a3 - - - - -class M3GFileIdentifier: - def __init__(self): - '''Byte[12] FileIdentifier = { 0xAB, 0x4A, 0x53, 0x52, 0x31, 0x38, 0x34, - 0xBB, 0x0D, 0x0A, 0x1A, 0x0A } - This can also be expressed using C-style character definitions as: - Byte[12] FileIdentifier = { '«', 'J', 'S', 'R', '1', '8', '4', '»', '\r', - '\n', '\x1A', '\n' }''' - self.data = [ 0xAB, 0x4A, 0x53, 0x52, 0x31, 0x38, 0x34, - 0xBB, 0x0D, 0x0A, 0x1A, 0x0A ] - - def write(self,aFile): - for element in self.data: - aFile.write(struct.pack('B',element)) - - def getLength(self): - return len(self.data) - - -class M3GWriter: - """writes a m3g binary file - File Structur - File Identifier - Section 0 File Header Object - Section 1 External Reference Objects - Section 2 Scene Objects - Section 3 Scene Objects - ... ... - Section n Scene Objects""" - - def __init__(self,aFilename): - self.FileName = aFilename - - - def writeFile(self,aWorld,aExportList,externalReferences): - '''Called after translation - first atempt: all objects in one section''' - print "M3G file writing .." - - fileIdentifier = M3GFileIdentifier() - - fileHeaderObject = M3GHeaderObject() - section0 = M3GSection([fileHeaderObject]) - sectionN = M3GSection(aExportList) - - length = fileIdentifier.getLength() - length += section0.getLength() - length += sectionN.getLength() - - if len(externalReferences) != 0: - section1 = M3GSection(externalReferences) - length += section1.getLength() - fileHeaderObject.hasExternalReferences = True - - fileHeaderObject.TotalFileSize=length - fileHeaderObject.ApproximateContentSize=length - section0 = M3GSection([fileHeaderObject]) - - output = open(self.FileName, mode='wb') - - fileIdentifier.write(output) - section0.write(output) - if len(externalReferences) != 0: - section1.write(output) - sectionN.write(output) - - output.close() - - print "M3G file written." - - -class OptionMgr: - """Reads and saves options """ - - def __init__(self): - self.setDefault() - rdict = Registry.GetKey('M3GExport', True) # True to check on disk as well - if rdict: # if found, get the values saved there - try: - self.textureEnabled = rdict['textureEnabled'] - self.textureExternal = rdict['textureExternal'] - self.lightingEnabled = rdict['lightingEnabled'] - self.createAmbientLight = rdict['createAmbientLight'] - self.exportAllActions = rdict['exportAllActions'] - self.autoscaling = rdict['autoscaling'] - self.perspectiveCorrection = rdict['perspectiveCorrection'] - self.smoothShading = rdict['smoothShading'] - self.exportAsJava = rdict['exportAsJava'] - self.exportVersion2 = rdict['exportVersion2'] - self.exportGamePhysics = rdict['exportGamePhysics'] - - except: self.save() # if data isn't valid, rewrite it - - def setDefault(self): - self.textureEnabled = True - self.textureExternal = False - self.lightingEnabled = True - self.createAmbientLight = False - self.exportAllActions = False - self.autoscaling = True - self.perspectiveCorrection = False - self.smoothShading = True - self.exportAsJava = False - self.exportVersion2 = False - self.exportGamePhysics = False - - def save(self): - d = {} - d['textureEnabled'] = self.textureEnabled - d['textureExternal'] = self.textureExternal - d['lightingEnabled'] = self.lightingEnabled - d['createAmbientLight'] = self.createAmbientLight - d['exportAllActions'] = self.exportAllActions - d['autoscaling'] = self.autoscaling - d['perspectiveCorrection'] = self.perspectiveCorrection - d['smoothShading'] = self.smoothShading - d['exportAsJava'] = self.exportAsJava - d['exportVersion2'] = self.exportVersion2 - d['exportGamePhysics'] = self.exportGamePhysics - - Blender.Registry.SetKey('M3GExport', d, True) - - -# ---- User Interface -------------------------------------------------------- # -mOptions = OptionMgr() - -def gui(): - """Draws the options menu.""" - # Flush events. - for s in Window.GetScreenInfo(): - Window.QHandle(s['id']) - - # Display options. - textureEnabled = Draw.Create(mOptions.textureEnabled) - textureExternal = Draw.Create(mOptions.textureExternal) - lightingEnabled = Draw.Create(mOptions.lightingEnabled) - createAmbientLight = Draw.Create(mOptions.createAmbientLight) - exportAllActions = Draw.Create(mOptions.exportAllActions) - autoscaling = Draw.Create(mOptions.autoscaling) - perspectiveCorrection = Draw.Create(mOptions.perspectiveCorrection) - smoothShading = Draw.Create(mOptions.smoothShading) - exportAsJava = Draw.Create(mOptions.exportAsJava) - exportVersion2 = Draw.Create(mOptions.exportVersion2) - exportGamePhysics = Draw.Create(mOptions.exportGamePhysics) - - pupBlock = [\ - ('Texturing'),\ - ('Enabled', textureEnabled, 'Enables texture export'),\ - ('External', textureExternal, 'References external files for textures'),\ - ('Lighting'),\ - ('Enabled', lightingEnabled, 'Enables light export'),\ - ('Ambient Light', createAmbientLight, 'Inserts an extra light object for ambient light'),\ - ('Mesh Options'),\ - ('Autoscaling', autoscaling, 'Uses maximum precision for vertex positions'),\ - ('Persp. Correction', perspectiveCorrection, 'Sets perspective correction flag'),\ - ('Smooth Shading', smoothShading, 'Sets smooth shading flag'),\ - ('Posing'),\ - ('All Armature Actions', exportAllActions, 'Exports all actions for armatures'),\ - ('Export'),\ - ('As Java Source', exportAsJava, 'Exports scene as Java source code'),\ - ('M3G Version 2.0', exportVersion2, 'Exports M3G Version 2.0 File'),\ - ('Game Physics', exportGamePhysics, 'Includes Game Physics infos for NOPE in export') - ] - - # Only execute if use didn't quit (ESC). - if Draw.PupBlock('M3G Export', pupBlock): - mOptions.textureEnabled = textureEnabled.val - mOptions.textureExternal = textureExternal.val - mOptions.lightingEnabled = lightingEnabled.val - mOptions.createAmbientLight = createAmbientLight.val - mOptions.exportAllActions = exportAllActions.val - mOptions.autoscaling = autoscaling.val - mOptions.perspectiveCorrection = perspectiveCorrection.val - mOptions.smoothShading = smoothShading.val - mOptions.exportAsJava = exportAsJava.val - mOptions.exportVersion2 = exportVersion2.val - mOptions.exportGamePhysics = exportGamePhysics.val - mOptions.save() - - if mOptions.exportAsJava: - Window.FileSelector(file_callback_java, 'Export M3G as Java', Blender.sys.makename(ext='.java')) - else: - Window.FileSelector(file_callback_m3g, 'Export M3G Binary', Blender.sys.makename(ext='.m3g')) - -def file_callback_java(filename): - Window.WaitCursor(1) # Blender will automatically remove wait cursor in case of an exception - exporter=M3GExporter(JavaWriter(filename)) - exporter.start() - Window.WaitCursor(0) - Window.RedrawAll() - -def file_callback_m3g(filename): - Window.WaitCursor(1) - exporter=M3GExporter(M3GWriter(filename)) - exporter.start() - Window.WaitCursor(0) - Window.RedrawAll() - -if __name__ == '__main__': - gui() - diff --git a/release/scripts/export_map.py b/release/scripts/export_map.py deleted file mode 100644 index 2262ae3b89b..00000000000 --- a/release/scripts/export_map.py +++ /dev/null @@ -1,454 +0,0 @@ -#!BPY - -""" -Name: 'Quake 3 (.map)' -Blender: 249 -Group: 'Export' -Tooltip: 'Export to Quake map format' -""" - -__author__ = 'Campbell Barton' -__version__ = '0.1a' -__email__ = "ideasman42@gmail.com" -__bpydoc__ = """\ -This script Exports a Quake 3 map format. - - Supports meshes, lights and nurbs patch surfaces -""" - -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Script copyright (C): Campbell Barton -# -# 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 ***** -# -------------------------------------------------------------------------- - - - - -from Blender import * -import BPyMesh - -PREF_SCALE= Draw.Create(100) -PREF_FACE_THICK= Draw.Create(0.1) -PREF_GRID_SNAP= Draw.Create(0) -# Quake 1/2? -# PREF_DEF_TEX_OPTS= Draw.Create(' 0 0 0 1 1\n') # not user settable yet -# Quake 3+? -PREF_DEF_TEX_OPTS= Draw.Create(' 0 0 0 1 1 0 0 0\n') # not user settable yet - -PREF_NULL_TEX= Draw.Create('NULL') # not user settable yet -PREF_INVIS_TEX= Draw.Create('common/caulk') - -def write_cube2brush(file, faces): - ''' - Takes 6 faces and writes a brush, - these faces can be from 1 mesh, 1 cube within a mesh of larger cubes - Faces could even come from different meshes or be contrived. - ''' - # comment only - # file.write('// brush "%s", "%s"\n' % (ob.name, ob.getData(name_only=1))) - file.write('// brush from cube\n{\n') - - if PREF_GRID_SNAP.val: format_vec= '( %d %d %d ) ' - else: format_vec= '( %.8f %.8f %.8f ) ' - - for f in faces: - # from 4 verts this gets them in reversed order and only 3 of them - # 0,1,2,3 -> 2,1,0 - for v in f.v[2::-1]: - file.write(format_vec % tuple(v.co) ) - - try: mode= f.mode - except: mode= 0 - - if mode & Mesh.FaceModes.INVISIBLE: - file.write(PREF_INVIS_TEX.val) - else: - try: image= f.image - except: image= None - - if image: file.write(sys.splitext(sys.basename(image.filename))[0]) - else: file.write(PREF_NULL_TEX.val) - - # Texture stuff ignored for now - file.write(PREF_DEF_TEX_OPTS.val) - file.write('}\n') - - -def round_vec(v): - if PREF_GRID_SNAP.val: - return round(v.x), round(v.y), round(v.z) - else: - return tuple(v) - -def write_face2brush(file, face): - ''' - takes a face and writes it as a brush - each face is a cube/brush - ''' - - if PREF_GRID_SNAP.val: format_vec= '( %d %d %d ) ' - else: format_vec= '( %.8f %.8f %.8f ) ' - - - image_text= PREF_NULL_TEX.val - - try: mode= face.mode - except: mode= 0 - - if mode & Mesh.FaceModes.INVISIBLE: - image_text= PREF_INVIS_TEX.val - else: - try: image= face.image - except: image= None - if image: image_text = sys.splitext(sys.basename(image.filename))[0] - - # original verts as tuples for writing - orig_vco= [tuple(v.co) for v in face] - - # new verts that give the face a thickness - dist= PREF_SCALE.val * PREF_FACE_THICK.val - new_vco= [round_vec(v.co - (v.no * dist)) for v in face] - #new_vco= [round_vec(v.co - (face.no * dist)) for v in face] - - file.write('// brush from face\n{\n') - # front - for co in orig_vco[2::-1]: - file.write(format_vec % co ) - file.write(image_text) - # Texture stuff ignored for now - file.write(PREF_DEF_TEX_OPTS.val) - - - for co in new_vco[:3]: - file.write(format_vec % co ) - if mode & Mesh.FaceModes.TWOSIDE: - file.write(image_text) - else: - file.write(PREF_INVIS_TEX.val) - - # Texture stuff ignored for now - file.write(PREF_DEF_TEX_OPTS.val) - - # sides. - if len(orig_vco)==3: # Tri, it seemms tri brushes are supported. - index_pairs= ((0,1), (1,2), (2,0)) - else: - index_pairs= ((0,1), (1,2), (2,3), (3,0)) - - for i1, i2 in index_pairs: - for co in orig_vco[i1], orig_vco[i2], new_vco[i2]: - file.write( format_vec % co ) - file.write(PREF_INVIS_TEX.val) - file.write(PREF_DEF_TEX_OPTS.val) - - file.write('}\n') - -def is_cube_facegroup(faces): - ''' - Returens a bool, true if the faces make up a cube - ''' - # cube must have 6 faces - if len(faces) != 6: - print '1' - return False - - # Check for quads and that there are 6 unique verts - verts= {} - for f in faces: - if len(f)!= 4: - return False - - for v in f: - verts[v.index]= 0 - - if len(verts) != 8: - return False - - # Now check that each vert has 3 face users - for f in faces: - for v in f: - verts[v.index] += 1 - - for v in verts.itervalues(): - if v != 3: # vert has 3 users? - return False - - # Could we check for 12 unique edges??, probably not needed. - return True - -def is_tricyl_facegroup(faces): - ''' - is the face group a tri cylinder - Returens a bool, true if the faces make an extruded tri solid - ''' - - # cube must have 5 faces - if len(faces) != 5: - print '1' - return False - - # Check for quads and that there are 6 unique verts - verts= {} - tottri= 0 - for f in faces: - if len(f)== 3: - tottri+=1 - - for v in f: - verts[v.index]= 0 - - if len(verts) != 6 or tottri != 2: - return False - - # Now check that each vert has 3 face users - for f in faces: - for v in f: - verts[v.index] += 1 - - for v in verts.itervalues(): - if v != 3: # vert has 3 users? - return False - - # Could we check for 12 unique edges??, probably not needed. - return True - -def write_node_map(file, ob): - ''' - Writes the properties of an object (empty in this case) - as a MAP node as long as it has the property name - classname - returns True/False based on weather a node was written - ''' - props= [(p.name, p.data) for p in ob.game_properties] - - IS_MAP_NODE= False - for name, value in props: - if name=='classname': - IS_MAP_NODE= True - break - - if not IS_MAP_NODE: - return False - - # Write a node - file.write('{\n') - for name_value in props: - file.write('"%s" "%s"\n' % name_value) - if PREF_GRID_SNAP.val: - file.write('"origin" "%d %d %d"\n' % tuple([round(axis*PREF_SCALE.val) for axis in ob.getLocation('worldspace')]) ) - else: - file.write('"origin" "%.6f %.6f %.6f"\n' % tuple([axis*PREF_SCALE.val for axis in ob.getLocation('worldspace')]) ) - file.write('}\n') - return True - - -def export_map(filepath): - - pup_block = [\ - ('Scale:', PREF_SCALE, 1, 1000, 'Scale the blender scene by this value.'),\ - ('Face Width:', PREF_FACE_THICK, 0.01, 10, 'Thickness of faces exported as brushes.'),\ - ('Grid Snap', PREF_GRID_SNAP, 'snaps floating point values to whole numbers.'),\ - 'Null Texture',\ - ('', PREF_NULL_TEX, 1, 128, 'Export textureless faces with this texture'),\ - 'Unseen Texture',\ - ('', PREF_INVIS_TEX, 1, 128, 'Export invisible faces with this texture'),\ - ] - - if not Draw.PupBlock('map export', pup_block): - return - - Window.WaitCursor(1) - time= sys.time() - print 'Map Exporter 0.0' - file= open(filepath, 'w') - - - obs_mesh= [] - obs_lamp= [] - obs_surf= [] - obs_empty= [] - - SCALE_MAT= Mathutils.Matrix() - SCALE_MAT[0][0]= SCALE_MAT[1][1]= SCALE_MAT[2][2]= PREF_SCALE.val - - dummy_mesh= Mesh.New() - - TOTBRUSH= TOTLAMP= TOTNODE= 0 - - for ob in Object.GetSelected(): - type= ob.type - if type == 'Mesh': obs_mesh.append(ob) - elif type == 'Surf': obs_surf.append(ob) - elif type == 'Lamp': obs_lamp.append(ob) - elif type == 'Empty': obs_empty.append(ob) - - if obs_mesh or obs_surf: - # brushes and surf's must be under worldspan - file.write('\n// entity 0\n') - file.write('{\n') - file.write('"classname" "worldspawn"\n') - - - print '\twriting cubes from meshes' - for ob in obs_mesh: - dummy_mesh.getFromObject(ob.name) - - #print len(mesh_split2connected(dummy_mesh)) - - # Is the object 1 cube? - object-is-a-brush - dummy_mesh.transform(ob.matrixWorld*SCALE_MAT) # 1 to tx the normals also - - if PREF_GRID_SNAP.val: - for v in dummy_mesh.verts: - co= v.co - co.x= round(co.x) - co.y= round(co.y) - co.z= round(co.z) - - # High quality normals - BPyMesh.meshCalcNormals(dummy_mesh) - - # Split mesh into connected regions - for face_group in BPyMesh.mesh2linkedFaces(dummy_mesh): - if is_cube_facegroup(face_group): - write_cube2brush(file, face_group) - TOTBRUSH+=1 - elif is_tricyl_facegroup(face_group): - write_cube2brush(file, face_group) - TOTBRUSH+=1 - else: - for f in face_group: - write_face2brush(file, f) - TOTBRUSH+=1 - - #print 'warning, not exporting "%s" it is not a cube' % ob.name - - - dummy_mesh.verts= None - - - valid_dims= 3,5,7,9,11,13,15 - for ob in obs_surf: - ''' - Surf, patches - ''' - surf_name= ob.getData(name_only=1) - data= Curve.Get(surf_name) - mat = ob.matrixWorld*SCALE_MAT - - # This is what a valid patch looks like - - """ -// brush 0 -{ -patchDef2 -{ -NULL -( 3 3 0 0 0 ) -( -( ( -64 -64 0 0 0 ) ( -64 0 0 0 -2 ) ( -64 64 0 0 -4 ) ) -( ( 0 -64 0 2 0 ) ( 0 0 0 2 -2 ) ( 0 64 0 2 -4 ) ) -( ( 64 -64 0 4 0 ) ( 64 0 0 4 -2 ) ( 80 88 0 4 -4 ) ) -) -} -} - """ - for i, nurb in enumerate(data): - u= nurb.pointsU - v= nurb.pointsV - if u in valid_dims and v in valid_dims: - - file.write('// brush %d surf_name\n' % i) - file.write('{\n') - file.write('patchDef2\n') - file.write('{\n') - file.write('NULL\n') - file.write('( %d %d 0 0 0 )\n' % (u, v) ) - file.write('(\n') - - u_iter = 0 - for p in nurb: - - if u_iter == 0: - file.write('(') - - u_iter += 1 - - # add nmapping 0 0 ? - if PREF_GRID_SNAP.val: - file.write(' ( %d %d %d 0 0 )' % round_vec(Mathutils.Vector(p[0:3]) * mat)) - else: - file.write(' ( %.6f %.6f %.6f 0 0 )' % tuple(Mathutils.Vector(p[0:3]) * mat)) - - # Move to next line - if u_iter == u: - file.write(' )\n') - u_iter = 0 - - file.write(')\n') - file.write('}\n') - file.write('}\n') - - - # Debugging - # for p in nurb: print 'patch', p - - else: - print "NOT EXPORTING PATCH", surf_name, u,v, 'Unsupported' - - - if obs_mesh or obs_surf: - file.write('}\n') # end worldspan - - - print '\twriting lamps' - for ob in obs_lamp: - print '\t\t%s' % ob.name - lamp= ob.data - file.write('{\n') - file.write('"classname" "light"\n') - file.write('"light" "%.6f"\n' % (lamp.dist* PREF_SCALE.val)) - if PREF_GRID_SNAP.val: - file.write('"origin" "%d %d %d"\n' % tuple([round(axis*PREF_SCALE.val) for axis in ob.getLocation('worldspace')]) ) - else: - file.write('"origin" "%.6f %.6f %.6f"\n' % tuple([axis*PREF_SCALE.val for axis in ob.getLocation('worldspace')]) ) - file.write('"_color" "%.6f %.6f %.6f"\n' % tuple(lamp.col)) - file.write('"style" "0"\n') - file.write('}\n') - TOTLAMP+=1 - - - print '\twriting empty objects as nodes' - for ob in obs_empty: - if write_node_map(file, ob): - print '\t\t%s' % ob.name - TOTNODE+=1 - else: - print '\t\tignoring %s' % ob.name - - Window.WaitCursor(0) - - print 'Exported Map in %.4fsec' % (sys.time()-time) - print 'Brushes: %d Nodes: %d Lamps %d\n' % (TOTBRUSH, TOTNODE, TOTLAMP) - - -def main(): - Window.FileSelector(export_map, 'EXPORT MAP', '*.map') - -if __name__ == '__main__': main() -# export_map('/foo.map') diff --git a/release/scripts/export_mdd.py b/release/scripts/export_mdd.py deleted file mode 100644 index 4f99c9175fd..00000000000 --- a/release/scripts/export_mdd.py +++ /dev/null @@ -1,168 +0,0 @@ -#!BPY - -""" - Name: 'Vertex Keyframe Animation (.mdd)...' - Blender: 242 - Group: 'Export' - Tooltip: 'Animated mesh to MDD vertex keyframe file.' -""" - -__author__ = "Bill L.Nieuwendorp" -__bpydoc__ = """\ -This script Exports Lightwaves MotionDesigner format. - -The .mdd format has become quite a popular Pipeline format<br> -for moving animations from package to package. - -Be sure not to use modifiers that change the number or order of verts in the mesh -""" -#Please send any fixes,updates,bugs to Slow67_at_Gmail.com or cbarton_at_metavr.com -#Bill Niewuendorp -# ***** 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 ***** - -import bpy -import Blender -from Blender import * -import BPyMessages -try: - from struct import pack -except: - pack = None - - -def zero_file(filepath): - ''' - If a file fails, this replaces it with 1 char, better not remove it? - ''' - file = open(filepath, 'w') - file.write('\n') # aparently macosx needs some data in a blank file? - file.close() - - -def check_vertcount(mesh,vertcount): - ''' - check and make sure the vertcount is consistent throghout the frame range - ''' - if len(mesh.verts) != vertcount: - Blender.Draw.PupMenu('Error%t|Number of verts has changed during animation|cannot export') - f.close() - zero_file(filepath) - return - - -def mdd_export(filepath, ob, PREF_STARTFRAME, PREF_ENDFRAME, PREF_FPS): - - Window.EditMode(0) - Blender.Window.WaitCursor(1) - mesh_orig = Mesh.New() - mesh_orig.getFromObject(ob.name) - - #Flip y and z - ''' - mat = Mathutils.Matrix() - mat[2][2] = -1 - rotmat = Mathutils.RotationMatrix(90, 4, 'x') - mat_flip = mat*rotmat - ''' - # Above results in this matrix - mat_flip= Mathutils.Matrix(\ - [1.0, 0.0, 0.0, 0.0],\ - [0.0, 0.0, 1.0, 0.0],\ - [0.0, 1.0, 0.0, 0.0],\ - [0.0, 0.0, 0.0, 1.0],\ - ) - - me_tmp = Mesh.New() # container mesh - - numverts = len(mesh_orig.verts) - numframes = PREF_ENDFRAME-PREF_STARTFRAME+1 - PREF_FPS= float(PREF_FPS) - f = open(filepath, 'wb') #no Errors yet:Safe to create file - - # Write the header - f.write(pack(">2i", numframes, numverts)) - - # Write the frame times (should we use the time IPO??) - f.write( pack(">%df" % (numframes), *[frame/PREF_FPS for frame in xrange(numframes)]) ) # seconds - - #rest frame needed to keep frames in sync - Blender.Set('curframe', PREF_STARTFRAME) - me_tmp.getFromObject(ob.name) - check_vertcount(me_tmp,numverts) - me_tmp.transform(ob.matrixWorld * mat_flip) - f.write(pack(">%df" % (numverts*3), *[axis for v in me_tmp.verts for axis in v.co])) - me_tmp.verts= None - - for frame in xrange(PREF_STARTFRAME,PREF_ENDFRAME+1):#in order to start at desired frame - Blender.Set('curframe', frame) - - me_tmp.getFromObject(ob.name) - - check_vertcount(me_tmp,numverts) - - me_tmp.transform(ob.matrixWorld * mat_flip) - - # Write the vertex data - f.write(pack(">%df" % (numverts*3), *[axis for v in me_tmp.verts for axis in v.co])) - - me_tmp.verts= None - f.close() - - print'MDD Exported: %s frames:%d\n'% (filepath, numframes-1) - Blender.Window.WaitCursor(0) - - -def mdd_export_ui(filepath): - # Dont overwrite - if not BPyMessages.Warning_SaveOver(filepath): - return - - scn= bpy.data.scenes.active - ob_act= scn.objects.active - if not ob_act or ob_act.type != 'Mesh': - BPyMessages.Error_NoMeshActive() - - ctx = scn.getRenderingContext() - orig_frame = Blender.Get('curframe') - PREF_STARTFRAME= Blender.Draw.Create(int(ctx.startFrame())) - PREF_ENDFRAME= Blender.Draw.Create(int(ctx.endFrame())) - PREF_FPS= Blender.Draw.Create(ctx.fps) - - block = [\ - ("Start Frame: ", PREF_STARTFRAME, 1, 30000, "Start Bake from what frame?: Default 1"),\ - ("End Frame: ", PREF_ENDFRAME, 1, 30000, "End Bake on what Frame?"),\ - ("FPS: ", PREF_FPS, 1, 100, "Frames per second")\ - ] - - if not Blender.Draw.PupBlock("Export MDD", block): - return - - PREF_STARTFRAME, PREF_ENDFRAME=\ - min(PREF_STARTFRAME.val, PREF_ENDFRAME.val),\ - max(PREF_STARTFRAME.val, PREF_ENDFRAME.val) - - print (filepath, ob_act, PREF_STARTFRAME, PREF_ENDFRAME, PREF_FPS.val) - mdd_export(filepath, ob_act, PREF_STARTFRAME, PREF_ENDFRAME, PREF_FPS.val) - Blender.Set('curframe', orig_frame) - -if __name__=='__main__': - if not pack: - Draw.PupMenu('Error%t|This script requires a full python install') - - Blender.Window.FileSelector(mdd_export_ui, 'EXPORT MDD', sys.makename(ext='.mdd'))
\ No newline at end of file diff --git a/release/scripts/export_obj.py b/release/scripts/export_obj.py deleted file mode 100644 index 7dffb5d2048..00000000000 --- a/release/scripts/export_obj.py +++ /dev/null @@ -1,933 +0,0 @@ -#!BPY - -""" -Name: 'Wavefront (.obj)...' -Blender: 249 -Group: 'Export' -Tooltip: 'Save a Wavefront OBJ File' -""" - -__author__ = "Campbell Barton, Jiri Hnidek, Paolo Ciccone" -__url__ = ['http://wiki.blender.org/index.php/Scripts/Manual/Export/wavefront_obj', 'www.blender.org', 'blenderartists.org'] -__version__ = "1.22" - -__bpydoc__ = """\ -This script is an exporter to OBJ file format. - -Usage: - -Select the objects you wish to export and run this script from "File->Export" menu. -Selecting the default options from the popup box will be good in most cases. -All objects that can be represented as a mesh (mesh, curve, metaball, surface, text3d) -will be exported as mesh data. -""" - - -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Script copyright (C) Campbell J Barton 2007-2009 -# - V1.22- bspline import/export added (funded by PolyDimensions GmbH) -# -# 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 ***** -# -------------------------------------------------------------------------- - - -import Blender -from Blender import Mesh, Scene, Window, sys, Image, Draw -import BPyMesh -import BPyObject -import BPySys -import BPyMessages - -# Returns a tuple - path,extension. -# 'hello.obj' > ('hello', '.obj') -def splitExt(path): - dotidx = path.rfind('.') - if dotidx == -1: - return path, '' - else: - return path[:dotidx], path[dotidx:] - -def fixName(name): - if name == None: - return 'None' - else: - return name.replace(' ', '_') - -# A Dict of Materials -# (material.name, image.name):matname_imagename # matname_imagename has gaps removed. -MTL_DICT = {} - -def write_mtl(filename): - - world = Blender.World.GetCurrent() - if world: - worldAmb = world.getAmb() - else: - worldAmb = (0,0,0) # Default value - - file = open(filename, "w") - file.write('# Blender3D MTL File: %s\n' % Blender.Get('filename').split('\\')[-1].split('/')[-1]) - file.write('# Material Count: %i\n' % len(MTL_DICT)) - # Write material/image combinations we have used. - for key, (mtl_mat_name, mat, img) in MTL_DICT.iteritems(): - - # Get the Blender data for the material and the image. - # Having an image named None will make a bug, dont do it :) - - file.write('newmtl %s\n' % mtl_mat_name) # Define a new material: matname_imgname - - if mat: - file.write('Ns %.6f\n' % ((mat.getHardness()-1) * 1.9607843137254901) ) # Hardness, convert blenders 1-511 to MTL's - file.write('Ka %.6f %.6f %.6f\n' % tuple([c*mat.amb for c in worldAmb]) ) # Ambient, uses mirror colour, - file.write('Kd %.6f %.6f %.6f\n' % tuple([c*mat.ref for c in mat.rgbCol]) ) # Diffuse - file.write('Ks %.6f %.6f %.6f\n' % tuple([c*mat.spec for c in mat.specCol]) ) # Specular - file.write('Ni %.6f\n' % mat.IOR) # Refraction index - file.write('d %.6f\n' % mat.alpha) # Alpha (obj uses 'd' for dissolve) - - # 0 to disable lighting, 1 for ambient & diffuse only (specular color set to black), 2 for full lighting. - if mat.getMode() & Blender.Material.Modes['SHADELESS']: - file.write('illum 0\n') # ignore lighting - elif mat.getSpec() == 0: - file.write('illum 1\n') # no specular. - else: - file.write('illum 2\n') # light normaly - - else: - #write a dummy material here? - file.write('Ns 0\n') - file.write('Ka %.6f %.6f %.6f\n' % tuple([c for c in worldAmb]) ) # Ambient, uses mirror colour, - file.write('Kd 0.8 0.8 0.8\n') - file.write('Ks 0.8 0.8 0.8\n') - file.write('d 1\n') # No alpha - file.write('illum 2\n') # light normaly - - # Write images! - if img: # We have an image on the face! - file.write('map_Kd %s\n' % img.filename.split('\\')[-1].split('/')[-1]) # Diffuse mapping image - - elif mat: # No face image. if we havea material search for MTex image. - for mtex in mat.getTextures(): - if mtex and mtex.tex.type == Blender.Texture.Types.IMAGE: - try: - filename = mtex.tex.image.filename.split('\\')[-1].split('/')[-1] - file.write('map_Kd %s\n' % filename) # Diffuse mapping image - break - except: - # Texture has no image though its an image type, best ignore. - pass - - file.write('\n\n') - - file.close() - -def copy_file(source, dest): - file = open(source, 'rb') - data = file.read() - file.close() - - file = open(dest, 'wb') - file.write(data) - file.close() - - -def copy_images(dest_dir): - if dest_dir[-1] != sys.sep: - dest_dir += sys.sep - - # Get unique image names - uniqueImages = {} - for matname, mat, image in MTL_DICT.itervalues(): # Only use image name - # Get Texface images - if image: - uniqueImages[image] = image # Should use sets here. wait until Python 2.4 is default. - - # Get MTex images - if mat: - for mtex in mat.getTextures(): - if mtex and mtex.tex.type == Blender.Texture.Types.IMAGE: - image_tex = mtex.tex.image - if image_tex: - try: - uniqueImages[image_tex] = image_tex - except: - pass - - # Now copy images - copyCount = 0 - - for bImage in uniqueImages.itervalues(): - image_path = sys.expandpath(bImage.filename) - if sys.exists(image_path): - # Make a name for the target path. - dest_image_path = dest_dir + image_path.split('\\')[-1].split('/')[-1] - if not sys.exists(dest_image_path): # Image isnt alredy there - print '\tCopying "%s" > "%s"' % (image_path, dest_image_path) - copy_file(image_path, dest_image_path) - copyCount+=1 - print '\tCopied %d images' % copyCount - - -def test_nurbs_compat(ob): - if ob.type != 'Curve': - return False - - for nu in ob.data: - if (not nu.knotsV) and nu.type != 1: # not a surface and not bezier - return True - - return False - -def write_nurb(file, ob, ob_mat): - tot_verts = 0 - cu = ob.data - - # use negative indices - Vector = Blender.Mathutils.Vector - for nu in cu: - - if nu.type==0: DEG_ORDER_U = 1 - else: DEG_ORDER_U = nu.orderU-1 # Tested to be correct - - if nu.type==1: - print "\tWarning, bezier curve:", ob.name, "only poly and nurbs curves supported" - continue - - if nu.knotsV: - print "\tWarning, surface:", ob.name, "only poly and nurbs curves supported" - continue - - if len(nu) <= DEG_ORDER_U: - print "\tWarning, orderU is lower then vert count, skipping:", ob.name - continue - - pt_num = 0 - do_closed = (nu.flagU & 1) - do_endpoints = (do_closed==0) and (nu.flagU & 2) - - for pt in nu: - pt = Vector(pt[0], pt[1], pt[2]) * ob_mat - file.write('v %.6f %.6f %.6f\n' % (pt[0], pt[1], pt[2])) - pt_num += 1 - tot_verts += pt_num - - file.write('g %s\n' % (fixName(ob.name))) # fixName(ob.getData(1)) could use the data name too - file.write('cstype bspline\n') # not ideal, hard coded - file.write('deg %d\n' % DEG_ORDER_U) # not used for curves but most files have it still - - curve_ls = [-(i+1) for i in xrange(pt_num)] - - # 'curv' keyword - if do_closed: - if DEG_ORDER_U == 1: - pt_num += 1 - curve_ls.append(-1) - else: - pt_num += DEG_ORDER_U - curve_ls = curve_ls + curve_ls[0:DEG_ORDER_U] - - file.write('curv 0.0 1.0 %s\n' % (' '.join( [str(i) for i in curve_ls] ))) # Blender has no U and V values for the curve - - # 'parm' keyword - tot_parm = (DEG_ORDER_U + 1) + pt_num - tot_parm_div = float(tot_parm-1) - parm_ls = [(i/tot_parm_div) for i in xrange(tot_parm)] - - if do_endpoints: # end points, force param - for i in xrange(DEG_ORDER_U+1): - parm_ls[i] = 0.0 - parm_ls[-(1+i)] = 1.0 - - file.write('parm u %s\n' % ' '.join( [str(i) for i in parm_ls] )) - - file.write('end\n') - - return tot_verts - -def write(filename, objects,\ -EXPORT_TRI=False, EXPORT_EDGES=False, EXPORT_NORMALS=False, EXPORT_NORMALS_HQ=False,\ -EXPORT_UV=True, EXPORT_MTL=True, EXPORT_COPY_IMAGES=False,\ -EXPORT_APPLY_MODIFIERS=True, EXPORT_ROTX90=True, EXPORT_BLEN_OBS=True,\ -EXPORT_GROUP_BY_OB=False, EXPORT_GROUP_BY_MAT=False, EXPORT_KEEP_VERT_ORDER=False,\ -EXPORT_POLYGROUPS=False, EXPORT_CURVE_AS_NURBS=True): - ''' - Basic write function. The context and options must be alredy set - This can be accessed externaly - eg. - write( 'c:\\test\\foobar.obj', Blender.Object.GetSelected() ) # Using default options. - ''' - - def veckey3d(v): - return round(v.x, 6), round(v.y, 6), round(v.z, 6) - - def veckey2d(v): - return round(v.x, 6), round(v.y, 6) - - def findVertexGroupName(face, vWeightMap): - """ - Searches the vertexDict to see what groups is assigned to a given face. - We use a frequency system in order to sort out the name because a given vetex can - belong to two or more groups at the same time. To find the right name for the face - we list all the possible vertex group names with their frequency and then sort by - frequency in descend order. The top element is the one shared by the highest number - of vertices is the face's group - """ - weightDict = {} - for vert in face: - vWeights = vWeightMap[vert.index] - for vGroupName, weight in vWeights: - weightDict[vGroupName] = weightDict.get(vGroupName, 0) + weight - - if weightDict: - alist = [(weight,vGroupName) for vGroupName, weight in weightDict.iteritems()] # sort least to greatest amount of weight - alist.sort() - return(alist[-1][1]) # highest value last - else: - return '(null)' - - - print 'OBJ Export path: "%s"' % filename - temp_mesh_name = '~tmp-mesh' - - time1 = sys.time() - scn = Scene.GetCurrent() - - file = open(filename, "w") - - # Write Header - file.write('# Blender3D v%s OBJ File: %s\n' % (Blender.Get('version'), Blender.Get('filename').split('/')[-1].split('\\')[-1] )) - file.write('# www.blender3d.org\n') - - # Tell the obj file what material file to use. - if EXPORT_MTL: - mtlfilename = '%s.mtl' % '.'.join(filename.split('.')[:-1]) - file.write('mtllib %s\n' % ( mtlfilename.split('\\')[-1].split('/')[-1] )) - - # Get the container mesh. - used for applying modifiers and non mesh objects. - containerMesh = meshName = tempMesh = None - for meshName in Blender.NMesh.GetNames(): - if meshName.startswith(temp_mesh_name): - tempMesh = Mesh.Get(meshName) - if not tempMesh.users: - containerMesh = tempMesh - if not containerMesh: - containerMesh = Mesh.New(temp_mesh_name) - - if EXPORT_ROTX90: - mat_xrot90= Blender.Mathutils.RotationMatrix(-90, 4, 'x') - - del meshName - del tempMesh - - # Initialize totals, these are updated each object - totverts = totuvco = totno = 1 - - face_vert_index = 1 - - globalNormals = {} - - # Get all meshes - for ob_main in objects: - for ob, ob_mat in BPyObject.getDerivedObjects(ob_main): - - # Nurbs curve support - if EXPORT_CURVE_AS_NURBS and test_nurbs_compat(ob): - if EXPORT_ROTX90: - ob_mat = ob_mat * mat_xrot90 - - totverts += write_nurb(file, ob, ob_mat) - - continue - # end nurbs - - # Will work for non meshes now! :) - # getMeshFromObject(ob, container_mesh=None, apply_modifiers=True, vgroups=True, scn=None) - me= BPyMesh.getMeshFromObject(ob, containerMesh, EXPORT_APPLY_MODIFIERS, EXPORT_POLYGROUPS, scn) - if not me: - continue - - if EXPORT_UV: - faceuv= me.faceUV - else: - faceuv = False - - # We have a valid mesh - if EXPORT_TRI and me.faces: - # Add a dummy object to it. - has_quads = False - for f in me.faces: - if len(f) == 4: - has_quads = True - break - - if has_quads: - oldmode = Mesh.Mode() - Mesh.Mode(Mesh.SelectModes['FACE']) - - me.sel = True - tempob = scn.objects.new(me) - me.quadToTriangle(0) # more=0 shortest length - oldmode = Mesh.Mode(oldmode) - scn.objects.unlink(tempob) - - Mesh.Mode(oldmode) - - # Make our own list so it can be sorted to reduce context switching - faces = [ f for f in me.faces ] - - if EXPORT_EDGES: - edges = me.edges - else: - edges = [] - - if not (len(faces)+len(edges)+len(me.verts)): # Make sure there is somthing to write - continue # dont bother with this mesh. - - if EXPORT_ROTX90: - me.transform(ob_mat*mat_xrot90) - else: - me.transform(ob_mat) - - # High Quality Normals - if EXPORT_NORMALS and faces: - if EXPORT_NORMALS_HQ: - BPyMesh.meshCalcNormals(me) - else: - # transforming normals is incorrect - # when the matrix is scaled, - # better to recalculate them - me.calcNormals() - - # # Crash Blender - #materials = me.getMaterials(1) # 1 == will return None in the list. - materials = me.materials - - materialNames = [] - materialItems = materials[:] - if materials: - for mat in materials: - if mat: # !=None - materialNames.append(mat.name) - else: - materialNames.append(None) - # Cant use LC because some materials are None. - # materialNames = map(lambda mat: mat.name, materials) # Bug Blender, dosent account for null materials, still broken. - - # Possible there null materials, will mess up indicies - # but at least it will export, wait until Blender gets fixed. - materialNames.extend((16-len(materialNames)) * [None]) - materialItems.extend((16-len(materialItems)) * [None]) - - # Sort by Material, then images - # so we dont over context switch in the obj file. - if EXPORT_KEEP_VERT_ORDER: - pass - elif faceuv: - try: faces.sort(key = lambda a: (a.mat, a.image, a.smooth)) - except: faces.sort(lambda a,b: cmp((a.mat, a.image, a.smooth), (b.mat, b.image, b.smooth))) - elif len(materials) > 1: - try: faces.sort(key = lambda a: (a.mat, a.smooth)) - except: faces.sort(lambda a,b: cmp((a.mat, a.smooth), (b.mat, b.smooth))) - else: - # no materials - try: faces.sort(key = lambda a: a.smooth) - except: faces.sort(lambda a,b: cmp(a.smooth, b.smooth)) - - # Set the default mat to no material and no image. - contextMat = (0, 0) # Can never be this, so we will label a new material teh first chance we get. - contextSmooth = None # Will either be true or false, set bad to force initialization switch. - - if EXPORT_BLEN_OBS or EXPORT_GROUP_BY_OB: - name1 = ob.name - name2 = ob.getData(1) - if name1 == name2: - obnamestring = fixName(name1) - else: - obnamestring = '%s_%s' % (fixName(name1), fixName(name2)) - - if EXPORT_BLEN_OBS: - file.write('o %s\n' % obnamestring) # Write Object name - else: # if EXPORT_GROUP_BY_OB: - file.write('g %s\n' % obnamestring) - - - # Vert - for v in me.verts: - file.write('v %.6f %.6f %.6f\n' % tuple(v.co)) - - # UV - if faceuv: - uv_face_mapping = [[0,0,0,0] for f in faces] # a bit of a waste for tri's :/ - - uv_dict = {} # could use a set() here - for f_index, f in enumerate(faces): - - for uv_index, uv in enumerate(f.uv): - uvkey = veckey2d(uv) - try: - uv_face_mapping[f_index][uv_index] = uv_dict[uvkey] - except: - uv_face_mapping[f_index][uv_index] = uv_dict[uvkey] = len(uv_dict) - file.write('vt %.6f %.6f\n' % tuple(uv)) - - uv_unique_count = len(uv_dict) - del uv, uvkey, uv_dict, f_index, uv_index - # Only need uv_unique_count and uv_face_mapping - - # NORMAL, Smooth/Non smoothed. - if EXPORT_NORMALS: - for f in faces: - if f.smooth: - for v in f: - noKey = veckey3d(v.no) - if not globalNormals.has_key( noKey ): - globalNormals[noKey] = totno - totno +=1 - file.write('vn %.6f %.6f %.6f\n' % noKey) - else: - # Hard, 1 normal from the face. - noKey = veckey3d(f.no) - if not globalNormals.has_key( noKey ): - globalNormals[noKey] = totno - totno +=1 - file.write('vn %.6f %.6f %.6f\n' % noKey) - - if not faceuv: - f_image = None - - if EXPORT_POLYGROUPS: - # Retrieve the list of vertex groups - vertGroupNames = me.getVertGroupNames() - - currentVGroup = '' - # Create a dictionary keyed by face id and listing, for each vertex, the vertex groups it belongs to - vgroupsMap = [[] for _i in xrange(len(me.verts))] - for vertexGroupName in vertGroupNames: - for vIdx, vWeight in me.getVertsFromGroup(vertexGroupName, 1): - vgroupsMap[vIdx].append((vertexGroupName, vWeight)) - - for f_index, f in enumerate(faces): - f_v= f.v - f_smooth= f.smooth - f_mat = min(f.mat, len(materialNames)-1) - if faceuv: - f_image = f.image - f_uv= f.uv - - # MAKE KEY - if faceuv and f_image: # Object is always true. - key = materialNames[f_mat], f_image.name - else: - key = materialNames[f_mat], None # No image, use None instead. - - # Write the vertex group - if EXPORT_POLYGROUPS: - if vertGroupNames: - # find what vertext group the face belongs to - theVGroup = findVertexGroupName(f,vgroupsMap) - if theVGroup != currentVGroup: - currentVGroup = theVGroup - file.write('g %s\n' % theVGroup) - - # CHECK FOR CONTEXT SWITCH - if key == contextMat: - pass # Context alredy switched, dont do anything - else: - if key[0] == None and key[1] == None: - # Write a null material, since we know the context has changed. - if EXPORT_GROUP_BY_MAT: - file.write('g %s_%s\n' % (fixName(ob.name), fixName(ob.getData(1))) ) # can be mat_image or (null) - file.write('usemtl (null)\n') # mat, image - - else: - mat_data= MTL_DICT.get(key) - if not mat_data: - # First add to global dict so we can export to mtl - # Then write mtl - - # Make a new names from the mat and image name, - # converting any spaces to underscores with fixName. - - # If none image dont bother adding it to the name - if key[1] == None: - mat_data = MTL_DICT[key] = ('%s'%fixName(key[0])), materialItems[f_mat], f_image - else: - mat_data = MTL_DICT[key] = ('%s_%s' % (fixName(key[0]), fixName(key[1]))), materialItems[f_mat], f_image - - if EXPORT_GROUP_BY_MAT: - file.write('g %s_%s_%s\n' % (fixName(ob.name), fixName(ob.getData(1)), mat_data[0]) ) # can be mat_image or (null) - - file.write('usemtl %s\n' % mat_data[0]) # can be mat_image or (null) - - contextMat = key - if f_smooth != contextSmooth: - if f_smooth: # on now off - file.write('s 1\n') - contextSmooth = f_smooth - else: # was off now on - file.write('s off\n') - contextSmooth = f_smooth - - file.write('f') - if faceuv: - if EXPORT_NORMALS: - if f_smooth: # Smoothed, use vertex normals - for vi, v in enumerate(f_v): - file.write( ' %d/%d/%d' % (\ - v.index+totverts,\ - totuvco + uv_face_mapping[f_index][vi],\ - globalNormals[ veckey3d(v.no) ])) # vert, uv, normal - - else: # No smoothing, face normals - no = globalNormals[ veckey3d(f.no) ] - for vi, v in enumerate(f_v): - file.write( ' %d/%d/%d' % (\ - v.index+totverts,\ - totuvco + uv_face_mapping[f_index][vi],\ - no)) # vert, uv, normal - - else: # No Normals - for vi, v in enumerate(f_v): - file.write( ' %d/%d' % (\ - v.index+totverts,\ - totuvco + uv_face_mapping[f_index][vi])) # vert, uv - - face_vert_index += len(f_v) - - else: # No UV's - if EXPORT_NORMALS: - if f_smooth: # Smoothed, use vertex normals - for v in f_v: - file.write( ' %d//%d' % (\ - v.index+totverts,\ - globalNormals[ veckey3d(v.no) ])) - else: # No smoothing, face normals - no = globalNormals[ veckey3d(f.no) ] - for v in f_v: - file.write( ' %d//%d' % (\ - v.index+totverts,\ - no)) - else: # No Normals - for v in f_v: - file.write( ' %d' % (\ - v.index+totverts)) - - file.write('\n') - - # Write edges. - if EXPORT_EDGES: - LOOSE= Mesh.EdgeFlags.LOOSE - for ed in edges: - if ed.flag & LOOSE: - file.write('f %d %d\n' % (ed.v1.index+totverts, ed.v2.index+totverts)) - - # Make the indicies global rather then per mesh - totverts += len(me.verts) - if faceuv: - totuvco += uv_unique_count - me.verts= None - file.close() - - - # Now we have all our materials, save them - if EXPORT_MTL: - write_mtl(mtlfilename) - if EXPORT_COPY_IMAGES: - dest_dir = filename - # Remove chars until we are just the path. - while dest_dir and dest_dir[-1] not in '\\/': - dest_dir = dest_dir[:-1] - if dest_dir: - copy_images(dest_dir) - else: - print '\tError: "%s" could not be used as a base for an image path.' % filename - - print "OBJ Export time: %.2f" % (sys.time() - time1) - - - -def write_ui(filename): - - if not filename.lower().endswith('.obj'): - filename += '.obj' - - if not BPyMessages.Warning_SaveOver(filename): - return - - global EXPORT_APPLY_MODIFIERS, EXPORT_ROTX90, EXPORT_TRI, EXPORT_EDGES,\ - EXPORT_NORMALS, EXPORT_NORMALS_HQ, EXPORT_UV,\ - EXPORT_MTL, EXPORT_SEL_ONLY, EXPORT_ALL_SCENES,\ - EXPORT_ANIMATION, EXPORT_COPY_IMAGES, EXPORT_BLEN_OBS,\ - EXPORT_GROUP_BY_OB, EXPORT_GROUP_BY_MAT, EXPORT_KEEP_VERT_ORDER,\ - EXPORT_POLYGROUPS, EXPORT_CURVE_AS_NURBS - - EXPORT_APPLY_MODIFIERS = Draw.Create(0) - EXPORT_ROTX90 = Draw.Create(1) - EXPORT_TRI = Draw.Create(0) - EXPORT_EDGES = Draw.Create(1) - EXPORT_NORMALS = Draw.Create(0) - EXPORT_NORMALS_HQ = Draw.Create(0) - EXPORT_UV = Draw.Create(1) - EXPORT_MTL = Draw.Create(1) - EXPORT_SEL_ONLY = Draw.Create(1) - EXPORT_ALL_SCENES = Draw.Create(0) - EXPORT_ANIMATION = Draw.Create(0) - EXPORT_COPY_IMAGES = Draw.Create(0) - EXPORT_BLEN_OBS = Draw.Create(0) - EXPORT_GROUP_BY_OB = Draw.Create(0) - EXPORT_GROUP_BY_MAT = Draw.Create(0) - EXPORT_KEEP_VERT_ORDER = Draw.Create(1) - EXPORT_POLYGROUPS = Draw.Create(0) - EXPORT_CURVE_AS_NURBS = Draw.Create(1) - - - # Old UI - ''' - # removed too many options are bad! - - # Get USER Options - pup_block = [\ - ('Context...'),\ - ('Selection Only', EXPORT_SEL_ONLY, 'Only export objects in visible selection. Else export whole scene.'),\ - ('All Scenes', EXPORT_ALL_SCENES, 'Each scene as a separate OBJ file.'),\ - ('Animation', EXPORT_ANIMATION, 'Each frame as a numbered OBJ file.'),\ - ('Object Prefs...'),\ - ('Apply Modifiers', EXPORT_APPLY_MODIFIERS, 'Use transformed mesh data from each object. May break vert order for morph targets.'),\ - ('Rotate X90', EXPORT_ROTX90 , 'Rotate on export so Blenders UP is translated into OBJs UP'),\ - ('Keep Vert Order', EXPORT_KEEP_VERT_ORDER, 'Keep vert and face order, disables some other options.'),\ - ('Extra Data...'),\ - ('Edges', EXPORT_EDGES, 'Edges not connected to faces.'),\ - ('Normals', EXPORT_NORMALS, 'Export vertex normal data (Ignored on import).'),\ - ('High Quality Normals', EXPORT_NORMALS_HQ, 'Calculate high quality normals for rendering.'),\ - ('UVs', EXPORT_UV, 'Export texface UV coords.'),\ - ('Materials', EXPORT_MTL, 'Write a separate MTL file with the OBJ.'),\ - ('Copy Images', EXPORT_COPY_IMAGES, 'Copy image files to the export directory, never overwrite.'),\ - ('Triangulate', EXPORT_TRI, 'Triangulate quads.'),\ - ('Grouping...'),\ - ('Objects', EXPORT_BLEN_OBS, 'Export blender objects as "OBJ objects".'),\ - ('Object Groups', EXPORT_GROUP_BY_OB, 'Export blender objects as "OBJ Groups".'),\ - ('Material Groups', EXPORT_GROUP_BY_MAT, 'Group by materials.'),\ - ] - - if not Draw.PupBlock('Export...', pup_block): - return - ''' - - # BEGIN ALTERNATIVE UI ******************* - if True: - - EVENT_NONE = 0 - EVENT_EXIT = 1 - EVENT_REDRAW = 2 - EVENT_EXPORT = 3 - - GLOBALS = {} - GLOBALS['EVENT'] = EVENT_REDRAW - #GLOBALS['MOUSE'] = Window.GetMouseCoords() - GLOBALS['MOUSE'] = [i/2 for i in Window.GetScreenSize()] - - def obj_ui_set_event(e,v): - GLOBALS['EVENT'] = e - - def do_split(e,v): - global EXPORT_BLEN_OBS, EXPORT_GROUP_BY_OB, EXPORT_GROUP_BY_MAT, EXPORT_APPLY_MODIFIERS, KEEP_VERT_ORDER, EXPORT_POLYGROUPS - if EXPORT_BLEN_OBS.val or EXPORT_GROUP_BY_OB.val or EXPORT_GROUP_BY_MAT.val or EXPORT_APPLY_MODIFIERS.val: - EXPORT_KEEP_VERT_ORDER.val = 0 - else: - EXPORT_KEEP_VERT_ORDER.val = 1 - - def do_vertorder(e,v): - global EXPORT_BLEN_OBS, EXPORT_GROUP_BY_OB, EXPORT_GROUP_BY_MAT, EXPORT_APPLY_MODIFIERS, KEEP_VERT_ORDER - if EXPORT_KEEP_VERT_ORDER.val: - EXPORT_BLEN_OBS.val = EXPORT_GROUP_BY_OB.val = EXPORT_GROUP_BY_MAT.val = EXPORT_APPLY_MODIFIERS.val = 0 - else: - if not (EXPORT_BLEN_OBS.val or EXPORT_GROUP_BY_OB.val or EXPORT_GROUP_BY_MAT.val or EXPORT_APPLY_MODIFIERS.val): - EXPORT_KEEP_VERT_ORDER.val = 1 - - - def do_help(e,v): - url = __url__[0] - print 'Trying to open web browser with documentation at this address...' - print '\t' + url - - try: - import webbrowser - webbrowser.open(url) - except: - print '...could not open a browser window.' - - def obj_ui(): - ui_x, ui_y = GLOBALS['MOUSE'] - - # Center based on overall pup size - ui_x -= 165 - ui_y -= 140 - - global EXPORT_APPLY_MODIFIERS, EXPORT_ROTX90, EXPORT_TRI, EXPORT_EDGES,\ - EXPORT_NORMALS, EXPORT_NORMALS_HQ, EXPORT_UV,\ - EXPORT_MTL, EXPORT_SEL_ONLY, EXPORT_ALL_SCENES,\ - EXPORT_ANIMATION, EXPORT_COPY_IMAGES, EXPORT_BLEN_OBS,\ - EXPORT_GROUP_BY_OB, EXPORT_GROUP_BY_MAT, EXPORT_KEEP_VERT_ORDER,\ - EXPORT_POLYGROUPS, EXPORT_CURVE_AS_NURBS - - Draw.Label('Context...', ui_x+9, ui_y+239, 220, 20) - Draw.BeginAlign() - EXPORT_SEL_ONLY = Draw.Toggle('Selection Only', EVENT_NONE, ui_x+9, ui_y+219, 110, 20, EXPORT_SEL_ONLY.val, 'Only export objects in visible selection. Else export whole scene.') - EXPORT_ALL_SCENES = Draw.Toggle('All Scenes', EVENT_NONE, ui_x+119, ui_y+219, 110, 20, EXPORT_ALL_SCENES.val, 'Each scene as a separate OBJ file.') - EXPORT_ANIMATION = Draw.Toggle('Animation', EVENT_NONE, ui_x+229, ui_y+219, 110, 20, EXPORT_ANIMATION.val, 'Each frame as a numbered OBJ file.') - Draw.EndAlign() - - - Draw.Label('Output Options...', ui_x+9, ui_y+189, 220, 20) - Draw.BeginAlign() - EXPORT_APPLY_MODIFIERS = Draw.Toggle('Apply Modifiers', EVENT_REDRAW, ui_x+9, ui_y+170, 110, 20, EXPORT_APPLY_MODIFIERS.val, 'Use transformed mesh data from each object. May break vert order for morph targets.', do_split) - EXPORT_ROTX90 = Draw.Toggle('Rotate X90', EVENT_NONE, ui_x+119, ui_y+170, 110, 20, EXPORT_ROTX90.val, 'Rotate on export so Blenders UP is translated into OBJs UP') - EXPORT_COPY_IMAGES = Draw.Toggle('Copy Images', EVENT_NONE, ui_x+229, ui_y+170, 110, 20, EXPORT_COPY_IMAGES.val, 'Copy image files to the export directory, never overwrite.') - Draw.EndAlign() - - - Draw.Label('Export...', ui_x+9, ui_y+139, 220, 20) - Draw.BeginAlign() - EXPORT_EDGES = Draw.Toggle('Edges', EVENT_NONE, ui_x+9, ui_y+120, 50, 20, EXPORT_EDGES.val, 'Edges not connected to faces.') - EXPORT_TRI = Draw.Toggle('Triangulate', EVENT_NONE, ui_x+59, ui_y+120, 70, 20, EXPORT_TRI.val, 'Triangulate quads.') - Draw.EndAlign() - Draw.BeginAlign() - EXPORT_MTL = Draw.Toggle('Materials', EVENT_NONE, ui_x+139, ui_y+120, 70, 20, EXPORT_MTL.val, 'Write a separate MTL file with the OBJ.') - EXPORT_UV = Draw.Toggle('UVs', EVENT_NONE, ui_x+209, ui_y+120, 31, 20, EXPORT_UV.val, 'Export texface UV coords.') - Draw.EndAlign() - Draw.BeginAlign() - EXPORT_NORMALS = Draw.Toggle('Normals', EVENT_NONE, ui_x+250, ui_y+120, 59, 20, EXPORT_NORMALS.val, 'Export vertex normal data (Ignored on import).') - EXPORT_NORMALS_HQ = Draw.Toggle('HQ', EVENT_NONE, ui_x+309, ui_y+120, 31, 20, EXPORT_NORMALS_HQ.val, 'Calculate high quality normals for rendering.') - Draw.EndAlign() - EXPORT_POLYGROUPS = Draw.Toggle('Polygroups', EVENT_REDRAW, ui_x+9, ui_y+95, 120, 20, EXPORT_POLYGROUPS.val, 'Export vertex groups as OBJ groups (one group per face approximation).') - - EXPORT_CURVE_AS_NURBS = Draw.Toggle('Nurbs', EVENT_NONE, ui_x+139, ui_y+95, 100, 20, EXPORT_CURVE_AS_NURBS.val, 'Export 3D nurbs curves and polylines as OBJ curves, (bezier not supported).') - - - Draw.Label('Blender Objects as OBJ:', ui_x+9, ui_y+59, 220, 20) - Draw.BeginAlign() - EXPORT_BLEN_OBS = Draw.Toggle('Objects', EVENT_REDRAW, ui_x+9, ui_y+39, 60, 20, EXPORT_BLEN_OBS.val, 'Export blender objects as "OBJ objects".', do_split) - EXPORT_GROUP_BY_OB = Draw.Toggle('Groups', EVENT_REDRAW, ui_x+69, ui_y+39, 60, 20, EXPORT_GROUP_BY_OB.val, 'Export blender objects as "OBJ Groups".', do_split) - EXPORT_GROUP_BY_MAT = Draw.Toggle('Material Groups', EVENT_REDRAW, ui_x+129, ui_y+39, 100, 20, EXPORT_GROUP_BY_MAT.val, 'Group by materials.', do_split) - Draw.EndAlign() - - EXPORT_KEEP_VERT_ORDER = Draw.Toggle('Keep Vert Order', EVENT_REDRAW, ui_x+239, ui_y+39, 100, 20, EXPORT_KEEP_VERT_ORDER.val, 'Keep vert and face order, disables some other options. Use for morph targets.', do_vertorder) - - Draw.BeginAlign() - Draw.PushButton('Online Help', EVENT_REDRAW, ui_x+9, ui_y+9, 110, 20, 'Load the wiki page for this script', do_help) - Draw.PushButton('Cancel', EVENT_EXIT, ui_x+119, ui_y+9, 110, 20, '', obj_ui_set_event) - Draw.PushButton('Export', EVENT_EXPORT, ui_x+229, ui_y+9, 110, 20, 'Export with these settings', obj_ui_set_event) - Draw.EndAlign() - - - # hack so the toggle buttons redraw. this is not nice at all - while GLOBALS['EVENT'] not in (EVENT_EXIT, EVENT_EXPORT): - Draw.UIBlock(obj_ui, 0) - - if GLOBALS['EVENT'] != EVENT_EXPORT: - return - - # END ALTERNATIVE UI ********************* - - - if EXPORT_KEEP_VERT_ORDER.val: - EXPORT_BLEN_OBS.val = False - EXPORT_GROUP_BY_OB.val = False - EXPORT_GROUP_BY_MAT.val = False - EXPORT_APPLY_MODIFIERS.val = False - - Window.EditMode(0) - Window.WaitCursor(1) - - EXPORT_APPLY_MODIFIERS = EXPORT_APPLY_MODIFIERS.val - EXPORT_ROTX90 = EXPORT_ROTX90.val - EXPORT_TRI = EXPORT_TRI.val - EXPORT_EDGES = EXPORT_EDGES.val - EXPORT_NORMALS = EXPORT_NORMALS.val - EXPORT_NORMALS_HQ = EXPORT_NORMALS_HQ.val - EXPORT_UV = EXPORT_UV.val - EXPORT_MTL = EXPORT_MTL.val - EXPORT_SEL_ONLY = EXPORT_SEL_ONLY.val - EXPORT_ALL_SCENES = EXPORT_ALL_SCENES.val - EXPORT_ANIMATION = EXPORT_ANIMATION.val - EXPORT_COPY_IMAGES = EXPORT_COPY_IMAGES.val - EXPORT_BLEN_OBS = EXPORT_BLEN_OBS.val - EXPORT_GROUP_BY_OB = EXPORT_GROUP_BY_OB.val - EXPORT_GROUP_BY_MAT = EXPORT_GROUP_BY_MAT.val - EXPORT_KEEP_VERT_ORDER = EXPORT_KEEP_VERT_ORDER.val - EXPORT_POLYGROUPS = EXPORT_POLYGROUPS.val - EXPORT_CURVE_AS_NURBS = EXPORT_CURVE_AS_NURBS.val - - - base_name, ext = splitExt(filename) - context_name = [base_name, '', '', ext] # basename, scene_name, framenumber, extension - - # Use the options to export the data using write() - # def write(filename, objects, EXPORT_EDGES=False, EXPORT_NORMALS=False, EXPORT_MTL=True, EXPORT_COPY_IMAGES=False, EXPORT_APPLY_MODIFIERS=True): - orig_scene = Scene.GetCurrent() - if EXPORT_ALL_SCENES: - export_scenes = Scene.Get() - else: - export_scenes = [orig_scene] - - # Export all scenes. - for scn in export_scenes: - scn.makeCurrent() # If alredy current, this is not slow. - context = scn.getRenderingContext() - orig_frame = Blender.Get('curframe') - - if EXPORT_ALL_SCENES: # Add scene name into the context_name - context_name[1] = '_%s' % BPySys.cleanName(scn.name) # WARNING, its possible that this could cause a collision. we could fix if were feeling parranoied. - - # Export an animation? - if EXPORT_ANIMATION: - scene_frames = xrange(context.startFrame(), context.endFrame()+1) # up to and including the end frame. - else: - scene_frames = [orig_frame] # Dont export an animation. - - # Loop through all frames in the scene and export. - for frame in scene_frames: - if EXPORT_ANIMATION: # Add frame to the filename. - context_name[2] = '_%.6d' % frame - - Blender.Set('curframe', frame) - if EXPORT_SEL_ONLY: - export_objects = scn.objects.context - else: - export_objects = scn.objects - - full_path= ''.join(context_name) - - # erm... bit of a problem here, this can overwrite files when exporting frames. not too bad. - # EXPORT THE FILE. - write(full_path, export_objects,\ - EXPORT_TRI, EXPORT_EDGES, EXPORT_NORMALS,\ - EXPORT_NORMALS_HQ, EXPORT_UV, EXPORT_MTL,\ - EXPORT_COPY_IMAGES, EXPORT_APPLY_MODIFIERS,\ - EXPORT_ROTX90, EXPORT_BLEN_OBS,\ - EXPORT_GROUP_BY_OB, EXPORT_GROUP_BY_MAT, EXPORT_KEEP_VERT_ORDER,\ - EXPORT_POLYGROUPS, EXPORT_CURVE_AS_NURBS) - - Blender.Set('curframe', orig_frame) - - # Restore old active scene. - orig_scene.makeCurrent() - Window.WaitCursor(0) - - -if __name__ == '__main__': - Window.FileSelector(write_ui, 'Export Wavefront OBJ', sys.makename(ext='.obj')) diff --git a/release/scripts/faceselect_same_weights.py b/release/scripts/faceselect_same_weights.py deleted file mode 100644 index 967aedec363..00000000000 --- a/release/scripts/faceselect_same_weights.py +++ /dev/null @@ -1,111 +0,0 @@ -#!BPY -""" -Name: 'Same Weights...' -Blender: 245 -Group: 'FaceSelect' -Tooltip: 'Select same faces with teh same weight for the active group.' -""" - -__author__ = ["Campbell Barton aka ideasman42"] -__url__ = ["www.blender.org", "blenderartists.org", "www.python.org"] -__version__ = "0.1" -__bpydoc__ = """\ - -Select Same Weights - -Select same weights as the active face on the active group. -""" - -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Script copyright (C) Campbell J Barton -# -# 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 ***** -# -------------------------------------------------------------------------- - -from Blender import Scene, Draw, Mesh -import BPyMesh - -def selSameWeights(me, PREF_TOLERENCE): - - # Check for missing data - if not me.faceUV: return - - act_group= me.activeGroup - if not act_group: return - - act_face = me.faces[me.activeFace] - if act_face == None: return - - - - groupNames, vWeightDict= BPyMesh.meshWeight2Dict(me) - - def get_face_weight(f): - ''' - Return the faces median weight and weight range. - ''' - wmin = 1.0 - wmax = 0.0 - w = 0.0 - for v in f: - try: - new_weight = vWeightDict[v.index][act_group] - if wmin > new_weight: wmin = new_weight - if wmax < new_weight: wmax = new_weight - w += new_weight - except: - pass - return w, wmax-wmin # weight, range - - weight_from, weight_range_from = get_face_weight(act_face) - for f in me.faces: - if (not f.sel) and f != act_face: - weight, weight_range = get_face_weight(f) - - # Compare the 2 faces weight difference and difference in their contrast. - if\ - abs(weight - weight_from) <= PREF_TOLERENCE and\ - abs(weight_range - weight_range_from) <= PREF_TOLERENCE: - f.sel = True - - -def main(): - scn= Scene.GetCurrent() - ob= scn.objects.active - - if not ob or ob.type != 'Mesh': - Draw.PupMenu('Error, no active mesh object, aborting.') - return - - me= ob.getData(mesh=1) - - PREF_TOLERENCE= Draw.Create(0.1) - - pup_block= [\ - ('Tolerence:', PREF_TOLERENCE, 0.01, 1.0, 'Tolerence for selecting faces of the same weight.'),\ - ] - - if not Draw.PupBlock('Select Same Weight...', pup_block): - return - - PREF_TOLERENCE= PREF_TOLERENCE.val - - selSameWeights(me, PREF_TOLERENCE) - -if __name__=='__main__': - main()
\ No newline at end of file diff --git a/release/scripts/flt_defaultp.py b/release/scripts/flt_defaultp.py deleted file mode 100644 index 5c44fe29a6f..00000000000 --- a/release/scripts/flt_defaultp.py +++ /dev/null @@ -1 +0,0 @@ -pal = [-1,255,16711935,-16776961,-19529729,-19726337,-19922945,-20119553,-20316161,-20578305,-20840449,-21102593,-21364737,-21692417,-22020097,-22413313,-22806529,-23199745,-23658497,-24117249,-24641537,-25165825,-25755649,-26411009,-27066369,-27787265,-28573697,-29425665,-30343169,-31326209,-32374785,-33488897,-354549761,-371458049,-388366337,-405274625,-422182913,-439156737,-456130561,-473104385,-506855425,-540672001,-574488577,-608305153,-642121729,-676003841,-709885953,-760610817,-811335681,-862060545,-912850945,-980418561,-1048051713,-1115684865,-1183383553,-1267924993,-1352466433,-1453850625,-1555300353,-1656815617,-1775173633,-1893597185,-2028863489,2130771967,-1010376193,-1043996161,-1077681665,-1111367169,-1145052673,-1178738177,-1229200897,-1279663617,-1330126337,-1380654593,-1431182849,-1498488321,-1565793793,-1633164801,-1700535809,-1784684033,-1868832257,-1969823233,-2070814209,2123096575,2005262847,1887429119,1752752639,1601298943,1449779711,1281417727,1096278527,911073791,709026303,490201599,254534143,2023935,-1380857601,-1397700353,-1431320321,-1464940289,-1498560257,-1532180225,-1565865729,-1599551233,-1650013953,-1700476673,-1750939393,-1801402113,-1851864833,-1919170305,-1986475777,-2053781249,-2121086721,2089797887,2005649663,1904724223,1803798783,1686030591,1568262399,1450494207,1315883263,1164495103,1013041407,844810495,659736831,457885951,239192319,3655935,-1767919617,-1784762369,-1801605121,-1818447873,-1852067841,-1885687809,-1919307777,-1952927745,-1986547713,-2020167681,-2070564865,-2120962049,2123542527,2073079807,2022617087,1955377151,1888137215,1820897279,1736880127,1652797439,1568714751,1467854847,1366994943,1249357823,1131655167,997175295,862695423,711372799,560050175,391950335,207007743,5287935,2139657983,2122880767,2106103551,2089326335,2072549119,2055771903,2022217471,1988663039,1955108607,1921554175,1887934207,1854314239,1803917055,1753519871,1703122687,1652725503,1602328319,1535153919,1467979519,1400805119,1316853503,1232901887,1148950271,1048221439,947427071,846632703,729061119,611489535,477140735,326014719,174888703,6919935,1837268479,1820491263,1803714047,1786936831,1770159615,1753382399,1736605183,1719827967,1686273535,1652719103,1619164671,1585610239,1552055807,1518501375,1468169727,1417838079,1367506431,1317174783,1266843135,1199734271,1132625407,1065516543,998407679,914521599,830635519,729972223,629308927,528645631,411205119,293764607,159546879,8551935,-2086957569,-2103734785,-2120512001,-2137289217,2140900863,2107346431,2073791999,2040237311,2006682623,1973127935,1939573247,1906018559,1855686655,1805354751,1755022847,1704690943,1654359039,1587249919,1520140799,1453031679,1369145343,1285258751,1201372159,1100708351,1000044543,882603519,765162495,630943999,496725503,345729791,177956863,10183935,-1699437825,-1716215297,-1732992769,-1766547457,-1800102145,-1833656833,-1867211521,-1900766209,-1934320897,-1967875585,-2018207489,-2068539649,-2118871809,2125763327,2058653951,1991544575,1924435199,1857325823,1773438975,1689552127,1588888063,1488223999,1387559679,1270118143,1152676607,1018457855,884238847,733242623,565468927,397695231,213144319,11815935,-1311918593,-1345473281,-1379027969,-1412582657,-1446137345,-1479692289,-1513247233,-1546802177,-1597134337,-1647466497,-1697798657,-1748130817,-1798463233,-1865572865,-1932682497,-1999792129,-2083678977,2127401215,2043514111,1942849791,1842185215,1724743423,1607301631,1473082367,1338863103,1187866367,1020092415,852318207,667766783,466437887,248331519,13447935,-924398849,-957953793,-991508737,-1025063681,-1058618625,-1092173569,-1142505729,-1192837889,-1243170305,-1293502721,-1343835137,-1410944769,-1478054401,-1545164289,-1629051393,-1712938497,-1796825857,-1897490433,-1998155009,-2098819841,2078705407,1961263103,1827043583,1676046591,1525049599,1357275135,1172723199,971394047,753287423,518403327,283518975,15079935,-570434049,-603988993,-637543937,-671098881,-704653825,-754986241,-805318657,-855651073,-905983489,-973093377,-1040203265,-1107313153,-1174423041,-1258310401,-1342197761,-1442862593,-1543527425,-1644192257,-1761634561,-1879076865,-2013296641,2147450879,1996453631,1828678911,1660904191,1476351999,1275022335,1056915199,822030591,570368511,301928959,16711935,-503325185,-536880129,-570435073,-603990017,-637544961,-671100161,-721432577,-771764993,-822097409,-872430081,-922762753,-989872641,-1056982529,-1124092673,-1191202817,-1275090433,-1358978049,-1459642881,-1560307969,-1660973057,-1778415617,-1895858177,-2030078209,2113891583,1962894079,1795119103,1610566655,1426013951,1224683775,1006576127,771691007,520028415,-452993537,-469771265,-503326209,-536881153,-570436097,-603991297,-637546497,-671101697,-721434113,-771766785,-822099457,-872432129,-922764801,-989874945,-1056985089,-1124095489,-1191205889,-1275093505,-1358981377,-1459646465,-1560311809,-1677754369,-1795197185,-1912640257,-2046860545,2097108991,1946110975,1778335487,1593782527,1392452095,1174344191,939458815,-419439105,-436216833,-452994561,-469772289,-503327233,-536882433,-570437633,-603992833,-637548033,-671103489,-721436161,-771768833,-822101505,-872434433,-922767361,-989877761,-1056988161,-1124098561,-1207986433,-1291874305,-1375762433,-1476427777,-1577093377,-1694536449,-1811979521,-1946200065,-2080420865,2063548159,1912549631,1744773631,1560220159,1358889215,-385884673,-402662401,-419440129,-436217857,-452995585,-469773569,-503328769,-536883969,-570439169,-603994625,-637550081,-671105537,-721438209,-771771137,-822104065,-872437249,-922770433,-989880833,-1056991489,-1124102145,-1191213057,-1275101185,-1358989569,-1459655425,-1560321281,-1677764609,-1795208193,-1912652033,-2046873345,2097095167,1946096127,1778319615,-335553025,-352330753,-369108481,-385886209,-402663937,-419441921,-436219905,-452997889,-486553089,-520108545,-553664001,-587219457,-620774913,-654330625,-687886337,-738219521,-788552705,-838885889,-889219329,-939552769,-1006663681,-1073774593,-1140885761,-1224774401,-1308663041,-1392551937,-1493218305,-1593884929,-1711329025,-1828773377,-1962995201,-2097217281,-285221377,-301999105,-318776833,-335554561,-352332289,-369110273,-385888257,-402666241,-419444225,-436222465,-453000705,-469778945,-503334401,-536890113,-570445825,-604001793,-637557761,-671113729,-721447169,-771780609,-822114305,-872448001,-922781953,-989893377,-1057004801,-1124116481,-1191228417,-1275117825,-1359007489,-1459674625,-1560342017,-1677786881,-234889729,-234890241,-251667969,-268445697,-285223425,-302001409,-318779393,-335557377,-352335361,-369113601,-385891841,-402670081,-419448321,-436226817,-453005313,-469784065,-503340033,-536896001,-570452225,-604008449,-637564929,-671121409,-704678145,-755012353,-805346561,-855681025,-906015745,-973127937,-1040240385,-1107353089,-1174466049,-1258356481,-234889729,-234890241,-234890753,-234891265,-234891777,-234892545,-234893313,-234894081,-234894849,-251673089,-268451329,-285229569,-302007809,-318786305,-335564801,-352343553,-369122305,-385901057,-402680065,-419459073,-436238337,-453017601,-486574337,-520131329,-553688321,-587245569,-620803073,-654360833,-687918849,-738254337,-788590081,-838926081,-234889729,-234890241,-234890753,-234891265,-234891777,-234892545,-234893313,-234894081,-234894849,-234895873,-234896897,-234897921,-234898945,-234900225,-234901505,-234903041,-234904577,-234906113,-234907905,-234909697,-234911745,-251691009,-268470529,-285250305,-302030081,-318810113,-335590401,-352370945,-369151745,-385932801,-402714113,-419495681,-8705,-9217,-9729,-10241,-10753,-11521,-12289,-13057,-13825,-14849,-15873,-16897,-17921,-19201,-20481,-22017,-23553,-25089,-26881,-28673,-30721,-32769,-35073,-37633,-40193,-43009,-46081,-49409,-52993,-56833,-60929,-65281,-926209,-926721,-927233,-927745,-928257,-929025,-929793,-930561,-931329,-932353,-933377,-934401,-935425,-936705,-937985,-939521,-941057,-1008129,-1075457,-1142785,-1210369,-1277953,-1345793,-1413889,-1481985,-1550337,-1618945,-1687809,-1756929,-1826305,-1895937,-2031361,-926209,-926721,-927233,-927745,-928257,-929025,-929793,-996097,-1062401,-1128961,-1195521,-1262081,-1328641,-1395457,-1462273,-1529345,-1596417,-1663489,-1730817,-1798145,-1865729,-1998849,-2132225,-2265857,-2399489,-2533377,-2667521,-2867457,-3067649,-3268097,-3468801,-3669761,-926209,-992257,-1058305,-1124353,-1190401,-1256705,-1323009,-1389313,-1455617,-1522177,-1588737,-1655297,-1721857,-1788673,-1855489,-1988097,-2120705,-2253313,-2386177,-2519041,-2652161,-2785281,-2984193,-3183361,-3382529,-3581953,-3847169,-4112641,-4378369,-4644353,-4976129,-5308161,-1188353,-1254401,-1320449,-1386497,-1452545,-1518849,-1585153,-1651457,-1717761,-1784321,-1850881,-1982977,-2115073,-2247425,-2379777,-2512385,-2644993,-2777601,-2976001,-3174401,-3373057,-3571713,-3836161,-4100865,-4365569,-4630529,-4961281,-5292289,-5689089,-6086145,-6483457,-6946561,-1384961,-1451009,-1517057,-1583105,-1649153,-1715457,-1781761,-1848065,-1979905,-2112001,-2244097,-2376193,-2508289,-2640641,-2838529,-3036673,-3234817,-3432961,-3631361,-3895297,-4159489,-4423681,-4688129,-5018369,-5348609,-5744641,-6140929,-6537473,-6999809,-7462401,-7990785,-8584961,-1581569,-1647617,-1713665,-1779713,-1845761,-1977601,-2109441,-2241281,-2373121,-2505217,-2637313,-2769409,-2967041,-3164929,-3362817,-3560961,-3759105,-4022785,-4286721,-4550657,-4880385,-5210113,-5540097,-5935873,-6331649,-6793217,-7255041,-7782657,-8310529,-8904193,-9563649,-10223361,-1712641,-1778689,-1844737,-1976321,-2107905,-2239745,-2371585,-2503425,-2635265,-2767361,-2964993,-3162625,-3360257,-3558145,-3821569,-4085249,-4348929,-4612609,-4942081,-5271553,-5666817,-6062081,-6457601,-6918913,-7380225,-7907329,-8434689,-9027841,-9686785,-10345985,-11070977,-11861761,-1843713,-1975297,-2106881,-2238465,-2370049,-2501889,-2633729,-2765569,-2962945,-3160577,-3358209,-3555841,-3753473,-4016897,-4280321,-4544001,-4873217,-5202433,-5531905,-5926913,-6322177,-6782977,-7244033,-7770881,-8297729,-8890369,-9548801,-10207489,-10931969,-11722241,-12578305,-13500161,-1974785,-2106369,-2237953,-2369537,-2501121,-2632961,-2830337,-3027713,-3225089,-3422721,-3620353,-3883521,-4146689,-4410113,-4673537,-5002753,-5331969,-5726721,-6121729,-6582273,-7043073,-7503873,-8030465,-8622849,-9215233,-9873409,-10597377,-11387137,-12242689,-13164033,-14085633,-15138561,-2236929,-2368513,-2500097,-2631681,-2763265,-2960641,-3158017,-3355393,-3552769,-3815937,-4079105,-4342273,-4605441,-4934401,-5263361,-5658113,-6052865,-6447617,-6908161,-7368705,-7895041,-8421377,-9013505,-9671425,-10329345,-11053057,-11842561,-12697857,-13618945,-14605825,-15658497,-16776961]
\ No newline at end of file diff --git a/release/scripts/flt_dofedit.py b/release/scripts/flt_dofedit.py deleted file mode 100644 index 36e8e4d2501..00000000000 --- a/release/scripts/flt_dofedit.py +++ /dev/null @@ -1,835 +0,0 @@ -#!BPY - -""" -Name: 'FLT DOF Editor' -Blender: 240 -Group: 'Misc' -Tooltip: 'Degree of Freedom editor for FLT nodes' -""" - -__author__ = "Geoffrey Bantle" -__version__ = "1.0 11/21/07" -__email__ = ('scripts', 'Author, ') -__url__ = ('blender', 'blenderartists.org') - -__bpydoc__ ="""\ -This script provides tools for working with OpenFlight databases in Blender. OpenFlight is a -registered trademark of MultiGen-Paradigm, Inc. - -Feature overview and more availible at: -http://wiki.blender.org/index.php/Scripts/Manual/FLTools -""" - -# -------------------------------------------------------------------------- -# flt_palettemanager.py version 0.1 2005/04/08 -# -------------------------------------------------------------------------- -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Copyright (C) 2007: Blender Foundation -# -# 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 ***** -# -------------------------------------------------------------------------- - -import Blender.Draw as Draw -from Blender.BGL import * -import Blender -import flt_properties -reload(flt_properties) -from flt_properties import * - -#event codes -evcode = { - "DOF_MAKE" : 100, - "DOF_UPDATE" : 138, - "DOF_DELETE" : 101, - "DOF_TRANSX" : 102, - "DOF_TRANSY" : 103, - "DOF_TRANSZ" : 104, - "DOF_ROTX" : 105, - "DOF_ROTY" : 106, - "DOF_ROTZ" : 107, - "DOF_SCALEX" : 108, - "DOF_SCALEY" : 109, - "DOF_SCALEZ" : 110, - "DOF_MIN_TRANSX" : 111, - "DOF_MIN_TRANSY" : 112, - "DOF_MIN_TRANSZ" : 113, - "DOF_MIN_ROTX" : 114, - "DOF_MIN_ROTY" : 115, - "DOF_MIN_ROTZ" : 116, - "DOF_MIN_SCALEX" : 117, - "DOF_MIN_SCALEY" : 118, - "DOF_MIN_SCALEZ" : 119, - "DOF_MAX_TRANSX" : 120, - "DOF_MAX_TRANSY" : 121, - "DOF_MAX_TRANSZ" : 122, - "DOF_MAX_ROTX" : 123, - "DOF_MAX_ROTY" : 124, - "DOF_MAX_ROTZ" : 125, - "DOF_MAX_SCALEX" : 126, - "DOF_MAX_SCALEY" : 127, - "DOF_MAX_SCALEZ" : 128, - "DOF_STEP_TRANSX" : 129, - "DOF_STEP_TRANSY" : 130, - "DOF_STEP_TRANSZ" : 131, - "DOF_STEP_ROTX" : 132, - "DOF_STEP_ROTY" : 133, - "DOF_STEP_ROTZ" : 134, - "DOF_STEP_SCALEX" : 135, - "DOF_STEP_SCALEY" : 136, - "DOF_STEP_SCALEZ" : 137 -} - -#system -DOF_MAKE = None -DOF_UPDATE = None -DOF_DELETE = None - -#toggle buttons -DOF_TRANSX = None -DOF_TRANSY = None -DOF_TRANSZ = None -DOF_ROTX = None -DOF_ROTY = None -DOF_ROTZ = None -DOF_SCALEX = None -DOF_SCALEY = None -DOF_SCALEZ = None - -#Minimums -DOF_MIN_TRANSX = None -DOF_MIN_TRANSY = None -DOF_MIN_TRANSZ = None -DOF_MIN_ROTX = None -DOF_MIN_ROTY = None -DOF_MIN_ROTZ = None -DOF_MIN_SCALEX = None -DOF_MIN_SCALEY = None -DOF_MIN_SCALEZ = None - -#maximums -DOF_MAX_TRANSX = None -DOF_MAX_TRANSY = None -DOF_MAX_TRANSZ = None -DOF_MAX_ROTX = None -DOF_MAX_ROTY = None -DOF_MAX_ROTZ = None -DOF_MAX_SCALEX = None -DOF_MAX_SCALEY = None -DOF_MAX_SCALEZ = None - -#step -DOF_STEP_TRANSX = None -DOF_STEP_TRANSY = None -DOF_STEP_TRANSZ = None -DOF_STEP_ROTX = None -DOF_STEP_ROTY = None -DOF_STEP_ROTZ = None -DOF_STEP_SCALEX = None -DOF_STEP_SCALEY = None -DOF_STEP_SCALEZ = None - -#labels -DOF_ROTSTRING = None -DOF_TRANSTRING = None -DOF_SCALESTRING = None -DOF_EDITLABEL = None - -#make ID props easier/morereadable -zmin = '14d!ZMIN' -zmax = '15d!ZMAX' -zcur = '16d!ZCUR' -zstep = '17d!ZSTEP' -ymin = '18d!YMIN' -ymax = '19d!YMAX' -ycur = '20d!YCUR' -ystep = '21d!YSTEP' -xmin = '22d!XMIN' -xmax = '23d!XMAX' -xcur = '24d!XCUR' -xstep = '25d!XSTEP' -pitchmin = '26d!PITCH-MIN' -pitchmax = '27d!PITCH-MAX' -pitchcur = '28d!PITCH-CUR' -pitchstep = '29d!PITCH-STEP' -rollmin = '30d!ROLL-MIN' -rollmax = '31d!ROLL-MAX' -rollcur = '32d!ROLL-CUR' -rollstep = '33d!ROLL-STEP' -yawmin = '34d!YAW-MIN' -yawmax = '35d!YAW-MAX' -yawcur = '36d!YAW-CUR' -yawstep = '37d!YAW-STEP' -zscalemin = '38d!ZSIZE-MIN' -zscalemax = '39d!ZSIZE-MAX' -zscalecur = '40d!ZSIZE-CUR' -zscalestep = '41d!ZSIZE-STEP' -yscalemin = '42d!YSIZE-MIN' -yscalemax = '43d!YSIZE-MAX' -yscalecur = '44d!YSIZE-CUR' -yscalestep = '45d!YSIZE-STEP' -xscalemin = '46d!XSIZE-MIN' -xscalemax = '47d!XSIZE-MAX' -xscalecur = '48d!XSIZE-CUR' -xscalestep = '49d!XSIZE-STEP' - - - -def update_state(): - state = dict() - state["activeScene"] = Blender.Scene.GetCurrent() - state["activeObject"] = state["activeScene"].objects.active - if state["activeObject"] and not state["activeObject"].sel: - state["activeObject"] = None - state["activeMesh"] = None - if state["activeObject"] and state["activeObject"].type == 'Mesh': - state["activeMesh"] = state["activeObject"].getData(mesh=True) - - - state["activeFace"] = None - if state["activeMesh"]: - if state["activeMesh"].faceUV and state["activeMesh"].activeFace != None: - state["activeFace"] = state["activeMesh"].faces[state["activeMesh"].activeFace] - - - #update editmode - state["editmode"] = Blender.Window.EditMode() - - return state - -def idprops_append(object, typecode, props): - object.properties["FLT"] = dict() - object.properties["FLT"]['type'] = typecode - for prop in props: - object.properties["FLT"][prop] = props[prop] - object.properties["FLT"]['3t8!id'] = object.name - -def idprops_kill(): - state = update_state() - if state["activeObject"] and state["activeObject"].properties.has_key('FLT'): - state["activeObject"].properties.pop('FLT') - -def idprops_copy(source): - state = update_state() - if source.properties.has_key('FLT'): - for object in state["activeScene"].objects: - if object.sel and object != source and (state["activeScene"].Layers & object.Layers): - idprops_kill(object) - object.properties['FLT'] = dict() - for key in source.properties['FLT']: - object.properties['FLT'][key] = source.properties['FLT'][key] - -def select_by_typecode(typecode): - state = update_state() - - for object in state["activeScene"].objects: - if object.properties.has_key('FLT') and object.properties['FLT']['type'] == typecode and state["activeScene"].Layers & object.Layers: - object.select(1) - -def DOF_get_frame(): - state = update_state() - - if not state["activeObject"] and not id_props_type(state["activeObject"], 14): - return - - #Warning! assumes 1 BU == 10 meters. - #do origin - state["activeObject"].properties['FLT']['5d!ORIGX'] = state["activeObject"].getLocation('worldspace')[0]*10.0 - state["activeObject"].properties['FLT']['6d!ORIGY'] = state["activeObject"].getLocation('worldspace')[1]*10.0 - state["activeObject"].properties['FLT']['7d!ORIGZ'] = state["activeObject"].getLocation('worldspace')[2]*10.0 - #do X axis - x = Blender.Mathutils.Vector(1.0,0.0,0.0) - x = x * state["activeObject"].getMatrix('worldspace') - x = x * 10.0 - state["activeObject"].properties['FLT']['8d!XAXIS-X'] = x[0] - state["activeObject"].properties['FLT']['9d!XAXIS-Y'] = x[1] - state["activeObject"].properties['FLT']['10d!XAXIS-Z'] = x[2] - #do X/Y plane - x = Blender.Mathutils.Vector(0.0,1.0,0.0) - x.normalize() - x = x * state["activeObject"].getMatrix('worldspace') - x = x * 10.0 - state["activeObject"].properties['FLT']['11d!XYPLANE-X'] = x[0] - state["activeObject"].properties['FLT']['12d!XYPLANE-Y'] = x[1] - state["activeObject"].properties['FLT']['13d!XZPLANE-Z'] = x[2] - -def idprops_type(object, typecode): - if object.properties.has_key('FLT') and object.properties['FLT'].has_key('type') and object.properties['FLT']['type'] == typecode: - return True - return False - -#ui type code -def get_prop(typecode, prop): - - state = update_state() - if state["activeObject"] and idprops_type(state["activeObject"], typecode): - props = state["activeObject"].properties['FLT'] - else: - props = flt_properties.FLTDOF - - return props[prop] - -def set_prop(typecode, prop, value): - state = update_state() - if state["activeObject"] and idprops_type(state["activeObject"],typecode): - state["activeObject"].properties['FLT'][prop] = value - -lockxtrans = (1 << 31) -lockytrans = (1 << 30) -lockztrans = (1 << 29) -lockxrot = (1 << 28) -lockyrot = (1 << 27) -lockzrot = (1 << 26) -lockxscale = (1 << 25) -lockyscale = (1 << 24) -lockzscale = (1 << 23) - -def get_lockmask(mask): - state = update_state() - if state["activeObject"]: - flag = get_prop(14,'50I!FLAG') - if flag & mask: - return True - return False - -def set_lockmask(mask): - state = update_state() - if state["activeObject"] and idprops_type(state["activeObject"], 14): - oldvalue = state["activeObject"].properties['FLT']['50I!FLAG'] - oldvalue = struct.unpack('>I', struct.pack('>i', oldvalue))[0] - oldvalue |= mask - state["activeObject"].properties['FLT']['50I!FLAG'] = struct.unpack('>i', struct.pack(">I", oldvalue))[0] - -def clear_lockmask(mask): - state = update_state() - if state["activeObject"] and idprops_type(state["activeObject"], 14): - oldvalue = state["activeObject"].properties['FLT']['50I!FLAG'] - oldvalue = struct.unpack('>I', struct.pack('>i', oldvalue))[0] - oldvalue &= ~mask - state["activeObject"].properties['FLT']['50I!FLAG'] = struct.unpack('>i',struct.pack('>I',oldvalue))[0] - - -def create_dof(): - state = update_state() - actobj = state["activeObject"] - if actobj and not idprops_type(actobj, 14): - idprops_kill() - idprops_append(actobj,14, flt_properties.FLTDOF) - DOF_get_frame() - - -def event(evt,val): - if evt == Draw.ESCKEY: - Draw.Exit() - -def but_event(evt): - global DOF_MAKE - global DOF_UPDATE - global DOF_DELETE - - global DOF_TRANSX - global DOF_TRANSY - global DOF_TRANSZ - global DOF_ROTX - global DOF_ROTY - global DOF_ROTZ - global DOF_SCALEX - global DOF_SCALEY - global DOF_SCALEZ - - global DOF_MIN_TRANSX - global DOF_MIN_TRANSY - global DOF_MIN_TRANSZ - global DOF_MIN_ROTX - global DOF_MIN_ROTY - global DOF_MIN_ROTZ - global DOF_MIN_SCALEX - global DOF_MIN_SCALEY - global DOF_MIN_SCALEZ - - global DOF_MAX_TRANSX - global DOF_MAX_TRANSY - global DOF_MAX_TRANSZ - global DOF_MAX_ROTX - global DOF_MAX_ROTY - global DOF_MAX_ROTZ - global DOF_MAX_SCALEX - global DOF_MAX_SCALEY - global DOF_MAX_SCALEZ - - global DOF_STEP_TRANSX - global DOF_STEP_TRANSY - global DOF_STEP_TRANSZ - global DOF_STEP_ROTX - global DOF_STEP_ROTY - global DOF_STEP_ROTZ - global DOF_STEP_SCALEX - global DOF_STEP_SCALEY - global DOF_STEP_SCALEZ - - #labels - global DOF_ROTSTRING - global DOF_TRANSTRING - global DOF_SCALESTRING - - - #masks - global lockxtrans - global lockytrans - global lockztrans - global lockxrot - global lockyrot - global lockzrot - global lockxscale - global lockyscale - global lockzscale - - global zmin - global zmax - global zcur - global zstep - global ymin - global ymax - global ycur - global ystep - global xmin - global xmax - global xcur - global xstep - global pitchmin - global pitchmax - global pitchcur - global pitchstep - global rollmin - global rollmax - global rollcur - global rollstep - global yawmin - global yawmax - global yawcur - global yawstep - global zscalemin - global zscalemax - global zscalecur - global zscalestep - global yscalemin - global yscalemax - global yscalecur - global yscalestep - global xscalemin - global xscalemax - global xscalecur - global xscalestep - - - - #do "system" events - if evt == evcode["DOF_MAKE"]: - create_dof() - - if evt == evcode["DOF_UPDATE"]: - DOF_get_frame() - - if evt == evcode["DOF_DELETE"]: - idprops_kill() - #do translation lock events - if evt == evcode["DOF_TRANSX"]: - if DOF_TRANSX.val == True: - set_lockmask(lockxtrans) - else: - clear_lockmask(lockxtrans) - - if evt == evcode["DOF_TRANSY"]: - if DOF_TRANSY.val == True: - set_lockmask(lockytrans) - else: - clear_lockmask(lockytrans) - - if evt == evcode["DOF_TRANSZ"]: - if DOF_TRANSZ.val == True: - set_lockmask(lockztrans) - else: - clear_lockmask(lockztrans) - - - #do rotation lock events - if evt == evcode["DOF_ROTX"]: - if DOF_ROTX.val == True: - set_lockmask(lockxrot) - else: - clear_lockmask(lockxrot) - - if evt == evcode["DOF_ROTY"]: - if DOF_ROTY.val == True: - set_lockmask(lockyrot) - else: - clear_lockmask(lockyrot) - - if evt == evcode["DOF_ROTZ"]: - if DOF_ROTZ.val == True: - set_lockmask(lockzrot) - else: - clear_lockmask(lockzrot) - - #do scale lock events - if evt == evcode["DOF_SCALEX"]: - if DOF_SCALEX.val == True: - set_lockmask(lockxscale) - else: - clear_lockmask(lockxscale) - - if evt == evcode["DOF_SCALEY"]: - if DOF_SCALEY.val == True: - set_lockmask(lockyscale) - else: - clear_lockmask(lockyscale) - - if evt == evcode["DOF_SCALEZ"]: - if DOF_SCALEZ.val == True: - set_lockmask(lockzscale) - else: - clear_lockmask(lockzscale) - - - #do translation buttons - if evt == evcode["DOF_MIN_TRANSX"]: - set_prop(14, xmin, DOF_MIN_TRANSX.val) - if evt == evcode["DOF_MAX_TRANSX"]: - set_prop(14,xmax, DOF_MAX_TRANSX.val) - if evt == evcode["DOF_STEP_TRANSX"]: - set_prop(14,xstep, DOF_STEP_TRANSX.val) - - if evt == evcode["DOF_MIN_TRANSY"]: - set_prop(14, ymin, DOF_MIN_TRANSY.val) - if evt == evcode["DOF_MAX_TRANSY"]: - set_prop(14,ymax, DOF_MAX_TRANSY.val) - if evt == evcode["DOF_STEP_TRANSY"]: - set_prop(14,ystep, DOF_STEP_TRANSY.val) - - if evt == evcode["DOF_MIN_TRANSZ"]: - set_prop(14, zmin, DOF_MIN_TRANSZ.val) - if evt == evcode["DOF_MAX_TRANSZ"]: - set_prop(14, zmax, DOF_MAX_TRANSZ.val) - if evt == evcode["DOF_STEP_TRANSZ"]: - set_prop(14, zstep, DOF_STEP_TRANSZ.val) - - #do rotation buttons - if evt == evcode["DOF_MIN_ROTX"]: - set_prop(14, pitchmin, DOF_MIN_ROTX.val) - if evt == evcode["DOF_MAX_ROTX"]: - set_prop(14, pitchmax, DOF_MAX_ROTX.val) - if evt == evcode["DOF_STEP_ROTX"]: - set_prop(14, pitchstep, DOF_STEP_ROTX.val) - - if evt == evcode["DOF_MIN_ROTY"]: - set_prop(14, rollmin, DOF_MIN_ROTY.val) - if evt == evcode["DOF_MAX_ROTY"]: - set_prop(14, rollmax, DOF_MAX_ROTY.val) - if evt == evcode["DOF_STEP_ROTY"]: - set_prop(14, rollstep, DOF_STEP_ROTY.val) - - if evt == evcode["DOF_MIN_ROTZ"]: - set_prop(14, yawmin, DOF_MIN_ROTZ.val) - if evt == evcode["DOF_MAX_ROTZ"]: - set_prop(14, yawmax, DOF_MAX_ROTZ.val) - if evt == evcode["DOF_STEP_ROTZ"]: - set_prop(14, yawstep, DOF_STEP_ROTZ.val) - - #do scale buttons - if evt == evcode["DOF_MIN_SCALEX"]: - set_prop(14, xscalemin, DOF_MIN_SCALEX.val) - if evt == evcode["DOF_MAX_SCALEX"]: - set_prop(14, xscalemax, DOF_MAX_SCALEX.val) - if evt == evcode["DOF_STEP_SCALEX"]: - set_prop(14, xscalestep, DOF_STEP_SCALEX.val) - - if evt == evcode["DOF_MIN_SCALEY"]: - set_prop(14, yscalemin, DOF_MIN_SCALEY.val) - if evt == evcode["DOF_MAX_SCALEY"]: - set_prop(14, yscalemax, DOF_MAX_SCALEY.val) - if evt == evcode["DOF_STEP_SCALEY"]: - set_prop(14, yscalestep, DOF_STEP_SCALEY.val) - - if evt == evcode["DOF_MIN_SCALEZ"]: - set_prop(14, zscalemin, DOF_MIN_SCALEZ.val) - if evt == evcode["DOF_MAX_SCALEZ"]: - set_prop(14, zscalemax, DOF_MAX_SCALEZ.val) - if evt == evcode["DOF_STEP_SCALEZ"]: - set_prop(14, zscalestep, DOF_STEP_SCALEZ.val) - - - Draw.Redraw(1) - Blender.Window.RedrawAll() - -def draw_propsheet(x,y): - #UI buttons - global DOF_MAKE - global DOF_UPDATE - global DOF_DELETE - - global DOF_TRANSX - global DOF_TRANSY - global DOF_TRANSZ - global DOF_ROTX - global DOF_ROTY - global DOF_ROTZ - global DOF_SCALEX - global DOF_SCALEY - global DOF_SCALEZ - - global DOF_MIN_TRANSX - global DOF_MIN_TRANSY - global DOF_MIN_TRANSZ - global DOF_MIN_ROTX - global DOF_MIN_ROTY - global DOF_MIN_ROTZ - global DOF_MIN_SCALEX - global DOF_MIN_SCALEY - global DOF_MIN_SCALEZ - - global DOF_MAX_TRANSX - global DOF_MAX_TRANSY - global DOF_MAX_TRANSZ - global DOF_MAX_ROTX - global DOF_MAX_ROTY - global DOF_MAX_ROTZ - global DOF_MAX_SCALEX - global DOF_MAX_SCALEY - global DOF_MAX_SCALEZ - - global DOF_STEP_TRANSX - global DOF_STEP_TRANSY - global DOF_STEP_TRANSZ - global DOF_STEP_ROTX - global DOF_STEP_ROTY - global DOF_STEP_ROTZ - global DOF_STEP_SCALEX - global DOF_STEP_SCALEY - global DOF_STEP_SCALEZ - - #labels - global DOF_ROTSTRING - global DOF_TRANSTRING - global DOF_SCALESTRING - global DOF_EDITLABEL - - #masks - global lockxtrans - global lockytrans - global lockztrans - global lockxrot - global lockyrot - global lockzrot - global lockxscale - global lockyscale - global lockzscale - - global zmin - global zmax - global zcur - global zstep - global ymin - global ymax - global ycur - global ystep - global xmin - global xmax - global xcur - global xstep - global pitchmin - global pitchmax - global pitchcur - global pitchstep - global rollmin - global rollmax - global rollcur - global rollstep - global yawmin - global yawmax - global yawcur - global yawstep - global zscalemin - global zscalemax - global zscalecur - global zscalestep - global yscalemin - global yscalemax - global yscalecur - global yscalestep - global xscalemin - global xscalemax - global xscalecur - global xscalestep - - - global evcode - - state = update_state() - - row_height = 20 - toggle_width = 50 - input_width = 100 - pad = 10 - origx = x - origy = (row_height * 15) + (pad * 15) - - - #editor label - x = origx - y = origy - #y = y - (row_height + pad) - DOF_EDITLABEL = Blender.Draw.Label("FLT Degree of Freedom Editor", x, y, 200, row_height) - - - #draw Translation limits - x = origx - y = y- (row_height + pad) - DOF_TRANSTRING = Blender.Draw.Label("Translation Limits", x, y, input_width, row_height) - - - #X limits - x = origx - y = y- (row_height + pad) - DOF_TRANSX = Blender.Draw.Toggle("LimX", evcode["DOF_TRANSX"], x, y, toggle_width, row_height, get_lockmask(lockxtrans), "") - x = x + (toggle_width + pad) - DOF_MIN_TRANSX = Blender.Draw.Number("MinX", evcode["DOF_MIN_TRANSX"], x, y, input_width, row_height,get_prop(14,xmin), -1000000.0, 1000000.0, "") - x = x + (input_width + pad) - DOF_MAX_TRANSX = Blender.Draw.Number("MaxX", evcode["DOF_MAX_TRANSX"], x, y, input_width, row_height,get_prop(14,xmax), -1000000.0, 1000000.0, "") - x = x + (input_width + pad) - DOF_STEP_TRANSX = Blender.Draw.Number("StepX", evcode["DOF_STEP_TRANSX"], x, y, input_width, row_height,get_prop(14,xstep), -1000000.0, 1000000.0, "") - - #Y limits - x = origx - y = y- (row_height + pad) - DOF_TRANSY = Blender.Draw.Toggle("LimY", evcode["DOF_TRANSY"], x, y, toggle_width, row_height, get_lockmask(lockytrans), "") - x = x + (toggle_width + pad) - DOF_MIN_TRANSY = Blender.Draw.Number("MinY", evcode["DOF_MIN_TRANSY"], x, y, input_width, row_height, get_prop(14,ymin), -1000000.0, 1000000.0, "") - x = x + (input_width + pad) - DOF_MAX_TRANSY = Blender.Draw.Number("MaxY", evcode["DOF_MAX_TRANSY"], x, y, input_width, row_height, get_prop(14,ymax), -1000000.0, 1000000.0, "") - x = x + (input_width + pad) - DOF_STEP_TRANSY = Blender.Draw.Number("StepY", evcode["DOF_STEP_TRANSY"], x, y, input_width, row_height, get_prop(14,ystep), -1000000.0, 1000000.0, "") - - #Z limits - x = origx - y = y- (row_height + pad) - DOF_TRANSZ = Blender.Draw.Toggle("LimZ", evcode["DOF_TRANSZ"], x, y, toggle_width, row_height, get_lockmask(lockztrans), "") - x = x + (toggle_width + pad) - DOF_MIN_TRANSZ = Blender.Draw.Number("MinZ", evcode["DOF_MIN_TRANSZ"], x, y, input_width, row_height, get_prop(14,zmin), -1000000.0, 1000000.0, "") - x = x + (input_width + pad) - DOF_MAX_TRANSZ = Blender.Draw.Number("MaxZ", evcode["DOF_MAX_TRANSZ"], x, y, input_width, row_height, get_prop(14,zmax), -1000000.0, 1000000.0, "") - x = x + (input_width + pad) - DOF_STEP_TRANSZ = Blender.Draw.Number("StepZ", evcode["DOF_STEP_TRANSZ"], x, y, input_width, row_height, get_prop(14,zstep), -1000000.0, 1000000.0, "") - - #draw Rotation limits - x = origx - y = y- (row_height + pad) - DOF_ROTSTRING = Blender.Draw.Label("Rotation Limits", x, y, input_width, row_height) - - #draw Rotation limits - #X limits - x = origx - y = y- (row_height + pad) - DOF_ROTX = Blender.Draw.Toggle("LimX", evcode["DOF_ROTX"], x, y, toggle_width, row_height, get_lockmask(lockxrot), "") - x = x + (toggle_width + pad) - DOF_MIN_ROTX = Blender.Draw.Number("MinX", evcode["DOF_MIN_ROTX"], x, y, input_width, row_height, get_prop(14,pitchmin), -1000000.0, 1000000.0, "") - x = x + (input_width + pad) - DOF_MAX_ROTX = Blender.Draw.Number("MaxX", evcode["DOF_MAX_ROTX"], x, y, input_width, row_height, get_prop(14,pitchmax), -1000000.0, 1000000.0, "") - x = x + (input_width + pad) - DOF_STEP_ROTX = Blender.Draw.Number("StepX", evcode["DOF_STEP_ROTX"], x, y, input_width, row_height, get_prop(14,pitchstep), -1000000.0, 1000000.0, "") - - #Y limits - x = origx - y = y- (row_height + pad) - DOF_ROTY = Blender.Draw.Toggle("LimY", evcode["DOF_ROTY"], x, y, toggle_width, row_height, get_lockmask(lockyrot), "") - x = x + (toggle_width + pad) - DOF_MIN_ROTY = Blender.Draw.Number("MinY", evcode["DOF_MIN_ROTY"], x, y, input_width, row_height, get_prop(14,rollmin), -1000000.0, 1000000.0, "") - x = x + (input_width + pad) - DOF_MAX_ROTY = Blender.Draw.Number("MaxY", evcode["DOF_MAX_ROTY"], x, y, input_width, row_height, get_prop(14,rollmax), -1000000.0, 1000000.0, "") - x = x + (input_width + pad) - DOF_STEP_ROTY = Blender.Draw.Number("StepY", evcode["DOF_STEP_ROTY"], x, y, input_width, row_height, get_prop(14,rollstep), -1000000.0, 1000000.0, "") - - #Z limits - x = origx - y = y- (row_height + pad) - DOF_ROTZ = Blender.Draw.Toggle("LimZ", evcode["DOF_ROTZ"], x, y, toggle_width, row_height, get_lockmask(lockzrot), "") - x = x + (toggle_width + pad) - DOF_MIN_ROTZ = Blender.Draw.Number("MinZ", evcode["DOF_MIN_ROTZ"], x, y, input_width, row_height, get_prop(14, yawmin), -1000000.0, 1000000.0, "") - x = x + (input_width + pad) - DOF_MAX_ROTZ = Blender.Draw.Number("MaxZ", evcode["DOF_MAX_ROTZ"], x, y, input_width, row_height, get_prop(14, yawmax), -1000000.0, 1000000.0, "") - x = x + (input_width + pad) - DOF_STEP_ROTZ = Blender.Draw.Number("StepZ", evcode["DOF_STEP_ROTZ"], x, y, input_width, row_height, get_prop(14, yawstep), -1000000.0, 1000000.0, "") - - - #draw Scale limits - x = origx - y = y- (row_height + pad) - DOF_SCALESTRING = Blender.Draw.Label("Scale Limits", x, y, input_width, row_height) - - #draw Scale limits - #X limits - x = origx - y = y- (row_height + pad) - DOF_SCALEX = Blender.Draw.Toggle("LimX", evcode["DOF_SCALEX"], x, y, toggle_width, row_height, get_lockmask(lockxscale), "") - x = x + (toggle_width + pad) - DOF_MIN_SCALEX = Blender.Draw.Number("MinX", evcode["DOF_MIN_SCALEX"], x, y, input_width, row_height, get_prop(14, xscalemin), -1000000.0, 1000000.0, "") - x = x + (input_width + pad) - DOF_MAX_SCALEX = Blender.Draw.Number("MaxX", evcode["DOF_MAX_SCALEX"], x, y, input_width, row_height, get_prop(14, xscalemax), -1000000.0, 1000000.0, "") - x = x + (input_width + pad) - DOF_STEP_SCALEX = Blender.Draw.Number("StepX", evcode["DOF_STEP_SCALEX"], x, y, input_width, row_height, get_prop(14, xscalestep), -1000000.0, 1000000.0, "") - - #Y limits - x = origx - y = y- (row_height + pad) - DOF_SCALEY = Blender.Draw.Toggle("LimY", evcode["DOF_SCALEY"], x, y, toggle_width, row_height, get_lockmask(lockyscale), "") - x = x + (toggle_width + pad) - DOF_MIN_SCALEY = Blender.Draw.Number("MinY", evcode["DOF_MIN_SCALEY"], x, y, input_width, row_height, get_prop(14, yscalemin), -1000000.0, 1000000.0, "") - x = x + (input_width + pad) - DOF_MAX_SCALEY = Blender.Draw.Number("MaxY", evcode["DOF_MAX_SCALEY"], x, y, input_width, row_height, get_prop(14, yscalemax), -1000000.0, 1000000.0, "") - x = x + (input_width + pad) - DOF_STEP_SCALEY = Blender.Draw.Number("StepY", evcode["DOF_STEP_SCALEY"], x, y, input_width, row_height, get_prop(14, yscalestep), -1000000.0, 1000000.0, "") - - #Z limits - x = origx - y = y- (row_height + pad) - DOF_SCALEZ = Blender.Draw.Toggle("LimZ", evcode["DOF_SCALEZ"], x, y, toggle_width, row_height, get_lockmask(lockzscale), "") - x = x + (toggle_width + pad) - DOF_MIN_SCALEZ = Blender.Draw.Number("MinZ", evcode["DOF_MIN_SCALEZ"], x, y, input_width, row_height, get_prop(14, zscalemin), -1000000.0, 1000000.0, "") - x = x + (input_width + pad) - DOF_MAX_SCALEZ = Blender.Draw.Number("MaxZ", evcode["DOF_MAX_SCALEZ"], x, y, input_width, row_height, get_prop(14, zscalemax), -1000000.0, 1000000.0, "") - x = x + (input_width + pad) - DOF_STEP_SCALEZ = Blender.Draw.Number("StepZ", evcode["DOF_STEP_SCALEZ"], x, y, input_width, row_height, get_prop(14, zscalestep), -1000000.0, 1000000.0, "") - - #System - x = origx - y = y - (row_height + (pad)*3) - DOF_MAKE = Blender.Draw.PushButton("Make DOF", evcode["DOF_MAKE"], x, y, input_width, row_height, "Make a Dof Node out of Active Object") - x = x + (input_width + pad) - DOF_UPDATE = Blender.Draw.PushButton("Grab Loc/Rot", evcode["DOF_UPDATE"], x, y, input_width, row_height, "Update the Dof Node position/orientation") - x = x + (input_width + pad) - DOF_DELETE = Blender.Draw.PushButton("Delete DOF", evcode["DOF_DELETE"], x, y, input_width, row_height, "Delete the Dof Node properties") - - - - -def gui(): - #draw the propsheet/toolbox. - psheety = 800 - #psheetx = psheety + 10 - draw_propsheet(20,psheety) - -Draw.Register(gui,event,but_event) -
\ No newline at end of file diff --git a/release/scripts/flt_export.py b/release/scripts/flt_export.py deleted file mode 100644 index c099c8e62d1..00000000000 --- a/release/scripts/flt_export.py +++ /dev/null @@ -1,1697 +0,0 @@ -#!BPY -""" Registration info for Blender menus: -Name: 'OpenFlight (.flt)...' -Blender: 245 -Group: 'Export' -Tip: 'Export to OpenFlight v16.0 (.flt)' -""" - -__author__ = "Greg MacDonald, Geoffrey Bantle" -__version__ = "2.0 11/21/07" -__url__ = ("blender", "blenderartists.org", "Author's homepage, http://sourceforge.net/projects/blight/") -__bpydoc__ = """\ -This script exports v16.0 OpenFlight files. OpenFlight is a -registered trademark of MultiGen-Paradigm, Inc. - -Feature overview and more availible at: -http://wiki.blender.org/index.php/Scripts/Manual/Export/openflight_flt -""" - -# flt_export.py is an OpenFlight exporter for blender. -# -# Copyright (C) 2005 Greg MacDonald, 2007 Blender Foundation. -# -# 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. - -import Blender -from Blender import Modifier -import os.path -import flt_properties -import flt_defaultp as defaultp -from flt_filewalker import FltOut -from flt_filewalker import FileFinder -from flt_properties import * -import shutil -import trace -import sys - -FF = FileFinder() -records = process_recordDefs() - -class ExporterOptions: - - def read_state(self): - reg = Blender.Registry.GetKey('flt_export',1) - if reg: - for key in self.state: - if reg.has_key(key): - self.state[key] = reg[key] - - def write_state(self): - d = dict() - for key in self.state: - d[key] = self.state[key] - Blender.Registry.SetKey('flt_export', d, 1) - def __init__(self): - self.verbose = 1 - self.tolerance = 0.001 - self.writevcol = True - - self.state = {'export_shading' : 0, - 'shading_default' : 45, - 'basepath' : os.path.dirname(Blender.Get('filename')), - 'scale': 1.0, - 'doxrefs' : 1, - 'attrib' : 0, - 'copytex' : 0, - 'transform' : 0, - 'xapp' : 1} - - #default externals path - if(os.path.exists(os.path.join(self.state['basepath'],'externals'))): - self.state['externalspath'] = os.path.join(self.state['basepath'],'externals') - else: - self.state['externalspath'] = self.state['basepath'] - - if(os.path.exists(os.path.join(self.state['basepath'],'textures'))): - self.state['texturespath'] = os.path.join(self.state['basepath'],'textures') - else: - self.state['texturespath'] = self.state['basepath'] - - self.state['xappath'] = '' - self.read_state() #read from registry - - -options = ExporterOptions() -tex_files = dict() #a list of (possibly) modified texture path names - -tex_layers = ['Layer0', 'Layer1', 'Layer2', 'Layer3', 'Layer4', 'Layer5', 'Layer6', 'Layer7'] -mask = 2147483648 -mtexmasks = [] -for i in xrange(7): - mtexmasks.append(mask) - mask = mask / 2 - -FLOAT_TOLERANCE = options.tolerance - -#need to move all this stuff to flt_properties.py. -identity_matrix = [[1.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 0.0, 1.0]] -alltypes = [2,4,14,11,73,63,111] -childtypes = { - 2 : [111,2,73,4,14,63], - 4 : [111], - 73 : [111,2,73,4,14,63], - 63 : [], - 14 : [111,2,73,4,14,63], - 111 : [] -} -recordlen = { - 2: 44, - 4: 28, - 73: 80, - 63: 216, - 14: 384, - 111: 156 -} - -def is_identity(m): - for i in xrange(4): - for j in xrange(4): - if abs(m[i][j] - identity_matrix[i][j]) > FLOAT_TOLERANCE: - return False - return True - -class MaterialDesc: - def __init__(self): - self.name = 'Blender' - - # Colors, List of 3 floats. - self.diffuse = [1.0, 1.0, 1.0] - self.specular = [1.0, 1.0, 1.0] - - # Scalars - self.ambient = 0.1 # [0.0, 1.0] - self.emissive = 0.0 # [0.0, 1.0] - self.shininess = 32.0 # Range is [0.0, 128.0] - self.alpha = 1.0 # Range is [0.0, 1.0] - -class VertexDesc: - def __init__(self, co=None, no=None, uv=None, fltindex=None,cindex=None): - if co: self.x, self.y, self.z = tuple(co) - else: self.x = self.y = self.z = 0.0 - if no: self.nx, self.ny, self.nz = tuple(no) - else: self.nx = self.ny = self.nz = 0.0 - if uv: self.u, self.v = tuple(uv) - else: self.u = self.v = 0.0 - if cindex: self.cindex = cindex - else: self.cindex = 127 - self.fltindex = fltindex - self.accum = 0 - -class shadowVert: - def __init__(self,bvert,object,world,normal): - global options - - self.co = Blender.Mathutils.Vector(bvert.co[0],bvert.co[1],bvert.co[2]) - #if world: - # vec = self.co - # vec = Blender.Mathutils.Vector(vec[0] * options.scale, vec[1] * options.scale, vec[2] * options.scale) #scale - # self.co = Blender.Mathutils.TranslationMatrix(vec) * (self.co * object.getMatrix('worldspace')) - - if normal: - #if world: - # self.no = Blender.Mathutils.Vector(normal * object.getMatrix('worldspace')).normalize() - #else: - self.no = Blender.Mathutils.Vector(normal[0],normal[1],normal[2]) - - else: - #if world: - #self.no = Blender.Mathutils.Vector(bvert.no * object.getMatrix('worldspace')).normalize() - #else: - self.no = Blender.Mathutils.Vector(bvert.no[0],bvert.no[1],bvert.no[2]) - - #do scaling factor - #if options.scale != 1.0: - #self.co[0] = self.co[0] * options.scale - #self.co[1] = self.co[1] * options.scale - #self.co[2] = self.co[2] * options.scale - - self.index = bvert.index - -class GlobalResourceRepository: - def new_face_name(self): - self.face_name += 1 - return 'f%i' % (self.face_name-1) - - def vertex_count(self): - return len(self.vertex_lst) - - def request_vertex_desc(self, i): - return self.vertex_lst[i] - - def request_vertex_index(self, object, mesh, face, vfindex, uvok,cindex): - - flatShadeNorm = None - vno = None - - - if type(face) is list: - vertex = face[vfindex] - elif str(type(face)) == "<type " + "'Blender MVert'>": - vertex = face - vno = Blender.Mathutils.Vector(0.0,0.0,1.0) - elif str(type(face)) == "<type " + "'Blender MEdge'>": - if vfindex == 1: - vertex = face.v1 - elif vfindex == 2: - vertex = face.v2 - elif str(type(face)) == "<type " + "'Blender MFace'>": - if not face.smooth: - flatShadeNorm = face.no - vertex = face.v[vfindex] - else: - return None - - if not self.namehash.has_key(object.name): - self.namehash[object.name] = dict() - indexhash = self.namehash[object.name] - - #export in global space? THIS HAS BEEN MADE REDUNDANT... REMOVE ME - if not options.state['transform']: - vertex = shadowVert(vertex,object,True,flatShadeNorm) - else: - vertex = shadowVert(vertex,object,False,flatShadeNorm) - - if vno: - vertex.no = vno - - - #Check to see if this vertex has been visited before. If not, add - if not indexhash.has_key(vertex.index): - if uvok: - newvdesc = VertexDesc(vertex.co, vertex.no, face.uv[vfindex], self.nextvindex,cindex=cindex) - else: - newvdesc = VertexDesc(co=vertex.co, no=vertex.no,fltindex=self.nextvindex,cindex=cindex) - - indexhash[vertex.index] = [newvdesc] - self.vertex_lst.append(newvdesc) - self.nextvindex = self.nextvindex + 1 - return newvdesc.fltindex - - else: - desclist = indexhash[vertex.index] - if uvok: - faceu = face.uv[vfindex][0] - facev = face.uv[vfindex][1] - else: - faceu = 0.0 - facev = 0.0 - for vdesc in desclist: - if\ - abs(vdesc.x - vertex.co[0]) > FLOAT_TOLERANCE or\ - abs(vdesc.y - vertex.co[1]) > FLOAT_TOLERANCE or\ - abs(vdesc.z - vertex.co[2]) > FLOAT_TOLERANCE or\ - abs(vdesc.nx - vertex.no[0]) > FLOAT_TOLERANCE or\ - abs(vdesc.ny - vertex.no[1]) > FLOAT_TOLERANCE or\ - abs(vdesc.nz - vertex.no[2]) > FLOAT_TOLERANCE or\ - vdesc.cindex != cindex or\ - abs(vdesc.u - faceu) > FLOAT_TOLERANCE or\ - abs(vdesc.v - facev) > FLOAT_TOLERANCE: - pass - else: - return vdesc.fltindex - - #if we get this far, we didnt find a match. Add a new one and return - if uvok: - newvdesc = VertexDesc(vertex.co, vertex.no, face.uv[vfindex], self.nextvindex,cindex=cindex) - else: - newvdesc = VertexDesc(co=vertex.co, no=vertex.no,fltindex=self.nextvindex,cindex=cindex) - indexhash[vertex.index].append(newvdesc) - self.vertex_lst.append(newvdesc) - self.nextvindex = self.nextvindex + 1 - return newvdesc.fltindex - - - def request_texture_index(self, image): - match = None - for i in xrange(len(self.texture_lst)): - if self.texture_lst[i] != image: - continue - match = i - break - if match != None: - return match - else: - self.texture_lst.append(image) - return len(self.texture_lst) - 1 - - def request_texture_filename(self, index): - return Blender.sys.expandpath(self.texture_lst[index].getFilename()) - - def texture_count(self): - return len(self.texture_lst) - - def request_material_index(self, desc): - match = None - for i in xrange(len(self.material_lst)): - if self.material_lst[i].diffuse != desc.diffuse: - continue - if self.material_lst[i].specular != desc.specular: - continue - if self.material_lst[i].ambient != desc.ambient: - continue - if self.material_lst[i].emissive != desc.emissive: - continue - if self.material_lst[i].shininess != desc.shininess: - continue - if self.material_lst[i].alpha != desc.alpha: - continue - match = i - break - - if match != None: - return i - else: - self.material_lst.append(desc) - return len(self.material_lst) - 1 - - def request_material_desc(self, index): - return self.material_lst[index] - - def material_count(self): - return len(self.material_lst) - - # Returns not actual index but one that includes intensity information. - # color_index = 127*intensity + 128*actual_index - def request_color_index(self, col): - r,g,b = tuple(col) - m = max(r, g, b) - if m > 0.0: - intensity = m / 1.0 - r = int(round(r/m * 255.0)) - g = int(round(g/m * 255.0)) - b = int(round(b/m * 255.0)) - brightest = [r, g, b] - else: - brightest = [255, 255, 255] - intensity = 0.0 - - match = None - for i in xrange(len(self.color_lst)): - if self.color_lst[i] != brightest: - continue - - match = i - break - - if match != None: - index = match - else: - length = len(self.color_lst) - if length <= 1024: - self.color_lst.append(brightest) - index = length - else: - if options.verbose >= 1: - print 'Warning: Exceeded max color limit.' - index = 0 - - color_index = int(round(127.0*intensity)) + 128*index - return color_index - - # Returns color from actual index. - def request_max_color(self, index): - return self.color_lst[index] - - def color_count(self): - return len(self.color_lst) - - def __init__(self): - #Vertex handling - self.vertex_lst = [] - self.nextvindex = 0 - self.namehash = dict() - - self.texture_lst = [] - self.material_lst = [] - self.color_lst = [[255, 255, 255]] - self.face_name = 0 - -class Node: - # Gathers info from blender needed for export. - # The =[0] is a trick to emulate c-like static function variables - # that are persistant between calls. - def blender_export(self, level=[0]): - if self.object: - if options.verbose >= 2: - print '\t' * level[0], self.name, self.object.type - level[0] += 1 - - self.children.reverse() - for child in self.children: - child.blender_export() - - level[0] -= 1 - - # Exports this node's info to file. - def write(self): - pass - - def write_matrix(self): - if self.matrix and not is_identity(self.matrix): - self.header.fw.write_short(49) # Matrix opcode - self.header.fw.write_ushort(68) # Length of record - for i in xrange(4): - for j in xrange(4): - self.header.fw.write_float(self.matrix[i][j]) - - def write_push(self): - self.header.fw.write_short(10) - self.header.fw.write_ushort(4) - - def write_pop(self): - self.header.fw.write_short(11) - self.header.fw.write_ushort(4) - - def write_push_extension(self): - self.header.fw.write_short(21) - self.header.fw.write_ushort(24) - self.header.fw.pad(18) - self.header.fw.write_ushort(0) - - def write_pop_extension(self): - self.header.fw.write_short(22) - self.header.fw.write_ushort(24) - self.header.fw.pad(18) - self.header.fw.write_ushort(0) - - def write_longid(self, name): - length = len(name) - if length >= 8: - self.header.fw.write_short(33) # Long ID opcode - self.header.fw.write_ushort(length+5) # Length of record - self.header.fw.write_string(name, length+1) # name + zero terminator - - def write_comment(self,comment): - length = len(comment) - if length >= 65535: - comment = comment[:65530] - length = len(comment) - - pad = (length % 4) - 1 - if pad < 0: - pad = None - reclength = length + 5 - else: - reclength = length + 5 + pad - - self.header.fw.write_short(31) # Comment Opcode - self.header.fw.write_ushort(reclength) # Length of record is 4 + comment length + null terminator + pad - self.header.fw.write_string(comment,length+1) # comment + zero terminator - if pad: - self.header.fw.pad(pad) # pad to multiple of 4 bytes - - # Initialization sets up basic tree structure. - def __init__(self, parent, header, object,props): - global options - - self.header = header - self.object = object - if object: - self.name = self.object.name - if not options.state['transform']: - oloc = Blender.Mathutils.Vector(object.getLocation('worldspace')) - vec = Blender.Mathutils.Vector(oloc[0] * options.state['scale'], oloc[1] * options.state['scale'], oloc[2] * options.state['scale']) #scale - self.matrix = self.object.getMatrix('worldspace') * Blender.Mathutils.TranslationMatrix(vec - oloc) - else: - self.matrix = self.object.getMatrix('localspace') #do matrix mult here. - self.props = props - self.child_objects = self.header.parenthash[object.name] - else: - self.name = 'no name' - self.matrix = None - self.props = None - self.child_objects = self.header.child_objects - - self.children = [] - self.parent = parent - if parent: - parent.children.append(self) - - # Spawn children. - for child in self.child_objects: - if(not child.restrictDisplay): - childprops = None - ftype = None - if not child.properties.has_key('FLT'): - if child.type == 'Empty': - if child.DupGroup: - childprops = FLTXRef.copy() - ftype = 63 - else: - childprops = FLTGroup.copy() - ftype = 2 - elif child.type == 'Mesh': - if self.header.childhash[child.name] or not child.parent: - childprops = FLTGroup.copy() - ftype = 2 - else: - childprops = FLTObject.copy() - ftype = 4 - - else: - childprops = dict() - for prop in child.properties['FLT']: - childprops[prop] = child.properties['FLT'][prop] - ftype = child.properties['FLT']['type'] - - if ftype in self.childtypes and ftype in alltypes: - Newnode = FLTNode(self,header,child,childprops,ftype) - if child.type == 'Mesh': - self.header.mnodes.append(Newnode) -class FaceDesc: - def __init__(self): - self.vertex_index_lst = [] - self.mface = None - self.texture_index = 65535 - self.material_index = 65535 - self.color_index = 127 - self.renderstyle = 0 - self.twoside = 0 - self.name = None #uses next FLT name if not set... fix resolution of conflicts! - self.billboard = 0 - - #Multi-Tex info. Dosn't include first UV Layer! - self.uvlayer = list() #list of list of tuples for UV coordinates. - self.images = list() #list of texture indices for seperate UV layers - self.mtex = list() - self.subface = None #can either be 'Push' or 'Pop' - -def edge_get_othervert(vert, edge): - if edge.v1 == vert: - return edge.v2 - elif edge.v2 == vert: - return edge.v1 - return None - -class FLTNode(Node): - def walkLoop(self, targetvert, startvert, startedge, edgelist, visited, vedges, closeloop): - loop = [targetvert] - - curvert = startvert - curedge = startedge - visited[curedge] = True - found = False - - while not found: - loop.append(curvert) - disk = vedges[curvert.index] - if not closeloop: - if len(disk) == 1: - visited[curedge] = True - break - else: - if len(disk) < 2: #what? - visited[curedge] = True - return None - - if disk[0] == curedge: - curedge = disk[1] - else: - curedge = disk[0] - if curedge.v1.index == curvert.index: - curvert = curedge.v2 - else: - curvert = curedge.v1 - - visited[curedge] = True - - if(curvert == targetvert): - found = True - - return loop - - def buildVertFaces(self,vertuse): - for vert in self.exportmesh.verts: - if vertuse[vert.index][0] == False and vertuse[vert.index][1] == 0: - face_desc = FaceDesc() - face_desc.vertex_index_lst.append(self.header.GRR.request_vertex_index(self.object, self.exportmesh, vert, 0,0,0)) - face_desc.renderstyle = 3 - face_desc.color_index = 227 - self.face_lst.append(face_desc) - - def buildEdgeFaces(self,vertuse): - for edge in self.exportmesh.edges: - v1 = vertuse[edge.v1.index] - v2 = vertuse[edge.v2.index] - if v1[0] == False and v2[0] == False: - if v1[1] == 1 and v2[1] == 1: - face_desc = FaceDesc() - face_desc.vertex_index_lst.append(self.header.GRR.request_vertex_index(self.object, self.exportmesh, edge, 1, 0,0)) - face_desc.vertex_index_lst.append(self.header.GRR.request_vertex_index(self.object, self.exportmesh, edge, 2, 0,0)) - face_desc.renderstyle = 3 - face_desc.color_index = 227 - self.face_lst.append(face_desc) - - - def vertwalk(self, startvert, loop, disk, visited): - visited[startvert] = True - for edge in disk[startvert]: - othervert = edge_get_othervert(startvert, edge) - if not visited[othervert]: - loop.append(othervert) - self.vertwalk(othervert,loop,disk,visited) - - def buildOpenFacesNew(self, vertuse): - wireverts = list() - wiredges = list() - visited = dict() - disk = dict() - loops = list() - - for edge in self.exportmesh.edges: - v1 = vertuse[edge.v1.index] - v2 = vertuse[edge.v2.index] - if v1[0] == False and v2[0] == False: - if v1[1] < 3 and v2[1] < 3: - wireverts.append(edge.v1) - wireverts.append(edge.v2) - wiredges.append(edge) - - #build disk data - for vert in wireverts: - visited[vert] = False - disk[vert] = list() - for edge in wiredges: - disk[edge.v1].append(edge) - disk[edge.v2].append(edge) - - #first pass: do open faces - for vert in wireverts: - if not visited[vert] and vertuse[vert.index][1] == 1: - loop = list() - done = 0 - startvert = vert - while not done: - done = 1 - visited[startvert] = True - loop.append(startvert) - for edge in disk[startvert]: - othervert = edge_get_othervert(startvert, edge) - if not visited[othervert]: - done = 0 - startvert = othervert - break - if len(loop) > 2: loops.append( ('Open', loop) ) - for vert in wireverts: - if not visited[vert]: - loop = list() - done = 0 - startvert = vert - while not done: - done = 1 - visited[startvert] = True - loop.append(startvert) - for edge in disk[startvert]: - othervert = edge_get_othervert(startvert,edge) - if not visited[othervert]: - done = 0 - startvert = othervert - break - if len(loop) > 2: loops.append( ('closed', loop) ) - - #now go through the loops and append. - for l in loops: - (ftype, loop) = l - face_desc = FaceDesc() - for i,vert in enumerate(loop): - face_desc.vertex_index_lst.append(self.header.GRR.request_vertex_index(self.object,self.exportmesh,loop,i,0,0)) - if ftype == 'closed': - face_desc.renderstyle = 2 - else: - face_desc.renderstyle = 3 - face_desc.color_index = 227 - self.face_lst.append(face_desc) - - - - def sortFLTFaces(self,a,b): - aindex = a.getProperty("FLT_ORIGINDEX") - bindex = b.getProperty("FLT_ORIGINDEX") - - if aindex > bindex: - return 1 - elif aindex < bindex: - return -1 - return 0 - - def buildNormFaces(self): - - global options - meshlayers = self.exportmesh.getUVLayerNames() - oldlayer = self.exportmesh.activeUVLayer - uvok = 0 - subfaceok = 0 - subfacelevel = 0 - - #special case - if self.exportmesh.faceUV and len(meshlayers) == 1: - uvok = 1 - elif self.exportmesh.faceUV and tex_layers[0] in meshlayers: - self.exportmesh.activeUVLayer = tex_layers[0] - uvok = 1 - - #Sort faces according to the subfaces/FLT indices - if "FLT_ORIGINDEX" in self.exportmesh.faces.properties and "FLT_SFLEVEL" in self.exportmesh.faces.properties: - exportfaces = list() - for face in self.exportmesh.faces: - exportfaces.append(face) - exportfaces.sort(self.sortFLTFaces) - subfaceok = 1 - else: - exportfaces = self.exportmesh.faces - - # Faces described as lists of indices into the GRR's vertex_lst. - for face in exportfaces: - descs = list() - #first we export the face as normal - index_lst = [] - face_v = face.verts - for i, v in enumerate(face_v): - index_lst.append(self.header.GRR.request_vertex_index(self.object,self.exportmesh,face,i,uvok,0)) - face_desc = FaceDesc() - face_desc.vertex_index_lst = index_lst - face_desc.mface = face - descs.append(face_desc) - - #deal with subfaces - if subfaceok: - fsflevel = face.getProperty("FLT_SFLEVEL") - for face_desc in descs: - if fsflevel > subfacelevel: - face_desc.subface = 'Push' - subfacelevel = fsflevel - elif fsflevel < subfacelevel: - face_desc.subface = 'Pop' - subfacelevel = fsflevel - - - if uvok and (face.mode & Blender.Mesh.FaceModes.TWOSIDE): - face_desc.renderstyle = 1 - for face_desc in descs: - if "FLT_COL" in self.exportmesh.faces.properties: - color_index = face.getProperty("FLT_COL") -# if(color_index < 127): -# color_index = 127 #sanity check for face color indices - if(color_index == 0): - color_index = 127 - face_desc.color_index = color_index - else: - face_desc.color_index = 127 - if "FLT_ID" in self.exportmesh.faces.properties: - face_desc.name = face.getProperty("FLT_ID") #need better solution than this. - - if uvok and face.mode & Blender.Mesh.FaceModes["BILLBOARD"]: - face_desc.billboard = 1 - - self.face_lst.append(face_desc) - if uvok: - self.exportmesh.activeUVLayer = oldlayer - - def buildTexData(self): - - meshlayers = self.exportmesh.getUVLayerNames() - oldlayer = self.exportmesh.activeUVLayer - uvok = 0 - - if self.exportmesh.faceUV and len(meshlayers) == 1: - uvok = 1 - if self.exportmesh.faceUV and tex_layers[0] in meshlayers: - self.exportmesh.activeUVLayer = tex_layers[0] - uvok = 1 - - if uvok: - #do base layer. UVs have been stored on vertices directly already. - for i, face in enumerate(self.face_lst): - if face.mface: - mface = face.mface - image = mface.image - if image != None and mface.mode & Blender.Mesh.FaceModes["TEX"]: - index = self.header.GRR.request_texture_index(image) - else: - index = -1 - face.texture_index = index - - for i, face in enumerate(self.face_lst): - if face.mface: - mface_v = face.mface.v - for v in mface_v: - face.uvlayer.append([]) - - for layername in tex_layers[1:]: - if layername in meshlayers: - self.exportmesh.activeUVLayer=layername - for i, face in enumerate(self.face_lst): - if face.mface: - - face.mtex.append(layername) - mface = face.mface - mface_v = mface.v - image = mface.image - - if image != None and mface.mode & Blender.Mesh.FaceModes["TEX"]: - index = self.header.GRR.request_texture_index(image) - face.images.append(index) - else: - face.images.append(-1) - - for j, v in enumerate(mface_v): - face.uvlayer[j].append(tuple(mface.uv[j])) - if uvok: - self.exportmesh.activeUVLayer = oldlayer - def blender_export(self): - global options - Node.blender_export(self) - if self.opcode == 111: - self.exportmesh = Blender.Mesh.New() - self.exportmesh.getFromObject(self.object.name) - - for vert in self.exportmesh.verts: - if not options.state['transform']: - vec = vert.co - vec = Blender.Mathutils.Vector(vec[0] * options.state['scale'], vec[1] * options.state['scale'], vec[2] * options.state['scale']) #scale - vert.co = Blender.Mathutils.TranslationMatrix(vec) * (vert.co * self.object.getMatrix('worldspace')) - - if options.state['scale'] != 1.0: - vert.co = vert.co * options.state['scale'] - - if("FLT_VCOL") in self.mesh.verts.properties: - for v in self.exportmesh.verts: - self.vert_lst.append(self.header.GRR.request_vertex_index(self.object,self.exportmesh,v,0,0,v.getProperty("FLT_VCOL"))) - else: - for v in self.mesh.verts: - self.vert_lst.append(self.header.GRR.request_vertex_index(self.object,self.mesh,v,0,0,127)) - - - - elif self.mesh: - orig_mesh = self.object.getData(mesh=True) - self.exportmesh = Blender.Mesh.New() - default = None - - - if options.state['export_shading']: - mods = self.object.modifiers - hasedsplit = False - for mod in mods: - if mod.type == Blender.Modifier.Types.EDGESPLIT: - hasedsplit = True - break - if not hasedsplit: - default = mods.append(Modifier.Types.EDGESPLIT) - default[Modifier.Settings.EDGESPLIT_ANGLE] = options.state['shading_default'] - default[Modifier.Settings.EDGESPLIT_FROM_ANGLE] = True - default[Modifier.Settings.EDGESPLIT_FROM_SHARP] = False - self.object.makeDisplayList() - - self.exportmesh.getFromObject(self.object.name) - - #recalculate vertex positions - for vert in self.exportmesh.verts: - if not options.state['transform']: - vec = vert.co - vec = Blender.Mathutils.Vector(vec[0] * options.state['scale'], vec[1] * options.state['scale'], vec[2] * options.state['scale']) #scale - vert.co = Blender.Mathutils.TranslationMatrix(vec) * (vert.co * self.object.getMatrix('worldspace')) - - if options.state['scale'] != 1.0: - vert.co = vert.co * options.state['scale'] - - flipped = self.object.getMatrix('worldspace').determinant() - - if not options.state['transform']: - self.exportmesh.calcNormals() - - - if default: - #remove modifier from list - mods.remove(default) - self.object.makeDisplayList() - - #build some adjacency data - vertuse = list() - wiredges = list() - openends = list() - for v in self.exportmesh.verts: - vertuse.append([False,0]) - - #build face incidence data - for face in self.exportmesh.faces: - for i, v in enumerate(face.verts): - vertuse[v.index][0] = True - - for edge in self.exportmesh.edges: #count valance - vertuse[edge.v1.index][1] = vertuse[edge.v1.index][1] + 1 - vertuse[edge.v2.index][1] = vertuse[edge.v2.index][1] + 1 - - #create all face types - self.buildVertFaces(vertuse) - self.buildEdgeFaces(vertuse) - self.buildOpenFacesNew(vertuse) - self.buildNormFaces() - self.buildTexData() - - if not options.state['transform']: - if flipped < 0: - for vdesc in self.header.GRR.vertex_lst: - vdesc.accum = 0 - for face in self.face_lst: - face.vertex_index_lst.reverse() - for vert in face.vertex_index_lst: - self.header.GRR.vertex_lst[vert].accum = 1 - - for vdesc in self.header.GRR.vertex_lst: - if vdesc.accum: - vdesc.nx = vdesc.nx * -1 - vdesc.ny = vdesc.ny * -1 - vdesc.nz = vdesc.nz * -1 - - - def write_faces(self): - sublevel = 0 - for face_desc in self.face_lst: - if face_desc.name: - face_name = face_desc.name - else: - face_name = self.header.GRR.new_face_name() - - #grab the alpha value. - alpha = 0 - if face_desc.texture_index > -1: - try: - typestring = os.path.splitext(self.header.GRR.texture_lst[face_desc.texture_index].getFilename())[1] - if typestring == '.inta' or typestring == '.rgba': - alpha = 1 - except: - pass - - if not alpha: - for index in face_desc.images: - try: - typestring = os.path.splitext(self.header.GRR.texture_lst[index].getFilename())[1] - if typestring == '.inta' or typestring == '.rgba': - alpha = 1 - except: - pass - - if face_desc.billboard: - alpha = 2 - - if face_desc.subface: - if face_desc.subface == 'Push': - self.header.fw.write_short(19) - self.header.fw.write_ushort(4) - sublevel += 1 - else: - self.header.fw.write_short(20) - self.header.fw.write_ushort(4) - sublevel -= 1 - self.header.fw.write_short(5) # Face opcode - self.header.fw.write_ushort(80) # Length of record - self.header.fw.write_string(face_name, 8) # ASCII ID - self.header.fw.write_int(-1) # IR color code - self.header.fw.write_short(0) # Relative priority - self.header.fw.write_char(face_desc.renderstyle) # Draw type - self.header.fw.write_char(0) # Draw textured white. - self.header.fw.write_ushort(0) # Color name index - self.header.fw.write_ushort(0) # Alt color name index - self.header.fw.write_char(0) # Reserved - self.header.fw.write_char(alpha) # Template - self.header.fw.write_short(-1) # Detail tex pat index - if face_desc.texture_index == -1: - self.header.fw.write_ushort(65535) - else: - self.header.fw.write_ushort(face_desc.texture_index) # Tex pattern index - if face_desc.material_index == -1: - self.header.fw.write_ushort(65535) - else: - self.header.fw.write_ushort(face_desc.material_index) # material index - self.header.fw.write_short(0) # SMC code - self.header.fw.write_short(0) # Feature code - self.header.fw.write_int(0) # IR material code - self.header.fw.write_ushort(0) # transparency 0 = opaque - self.header.fw.write_uchar(0) # LOD generation control - self.header.fw.write_uchar(0) # line style index - self.header.fw.write_int(0) # Flags - self.header.fw.write_uchar(2) # Light mode - #self.header.fw.write_uchar(3) # Light mode - - self.header.fw.pad(7) # Reserved - self.header.fw.write_uint(0) # Packed color - self.header.fw.write_uint(0) # Packed alt color - self.header.fw.write_short(-1) # Tex map index - self.header.fw.write_short(0) # Reserved - self.header.fw.write_uint(face_desc.color_index) # Color index - self.header.fw.write_uint(127) # Alt color index - self.header.fw.write_short(0) # Reserved - self.header.fw.write_short(-1) # Shader index - - self.write_longid(face_name) - - - #Write Multitexture field if appropriate - mtex = len(face_desc.mtex) - if mtex: - uvmask = 0 - for layername in face_desc.mtex: - mask = mtexmasks[tex_layers.index(layername)-1] - uvmask |= mask - self.header.fw.write_ushort(52) # MultiTexture Opcode - self.header.fw.write_ushort(8 + (mtex * 8)) # Length - self.header.fw.write_uint(uvmask) # UV mask - for i in xrange(mtex): - if face_desc.images[i] == -1: - self.header.fw.write_ushort(65535) - else: - self.header.fw.write_ushort(face_desc.images[i]) # Tex pattern index - self.header.fw.write_ushort(0) # Tex effect - self.header.fw.write_ushort(0) # Tex Mapping index - self.header.fw.write_ushort(0) # Tex data. User defined - - self.write_push() - - # Vertex list record - self.header.fw.write_short(72) # Vertex list opcode - num_verts = len(face_desc.vertex_index_lst) - self.header.fw.write_ushort(4*num_verts+4) # Length of record - - for vert_index in face_desc.vertex_index_lst: - # Offset into vertex palette - self.header.fw.write_int(vert_index*64+8) - - #UV list record - if mtex: - #length = 8 + (numverts * multitex * 8) - self.header.fw.write_ushort(53) # UV List Ocode - self.header.fw.write_ushort(8 + (num_verts*mtex*8)) # Record Length - self.header.fw.write_uint(uvmask) # UV mask - for i, vert_index in enumerate(face_desc.vertex_index_lst): - for uv in face_desc.uvlayer[i]: - self.header.fw.write_float(uv[0]) #U coordinate - self.header.fw.write_float(uv[1]) #V coordinate - self.write_pop() - #clean up faces at the end of meshes.... - if sublevel: - self.header.fw.write_short(20) - self.header.fw.write_ushort(4) - - def write_lps(self): - # Vertex list record - self.write_push() - self.header.fw.write_short(72) # Vertex list opcode - num_verts = len(self.vert_lst) - self.header.fw.write_ushort(4*num_verts+4) # Length of record - - for vert_index in self.vert_lst: - # Offset into vertex palette - self.header.fw.write_int(vert_index*64+8) - self.write_pop() - def write(self): - self.header.fw.write_short(self.opcode) - self.header.fw.write_ushort(recordlen[self.opcode]) - exportdict = FLT_Records[self.opcode].copy() - if self.object: - self.props['3t8!id'] = self.object.name[:7] - for key in exportdict.keys(): - if self.props.has_key(key): - exportdict[key] = self.props[key] - - if self.opcode == 63 and options.state['externalspath']: - try: - exportdict['3t200!filename'] = os.path.join(options.state['externalspath'],self.object.DupGroup.name+'.flt').replace("\\", "/") - self.header.xrefnames.append(self.object.DupGroup.name) - except: - pass - - for key in records[self.opcode]: - (ftype,length,propname) = records[self.opcode][key] - write_prop(self.header.fw,ftype,exportdict[propname],length) - - if self.props.has_key('comment'): - self.write_comment(self.props['comment']) - - if self.object and self.object.properties.has_key('FLT') and self.object.properties['FLT'].has_key('EXT'): - datalen = len(self.object.properties['FLT']['EXT']['data']) - self.write_push_extension() - self.header.fw.write_short(100) - self.header.fw.write_ushort(24 + datalen) - for key in records[100]: - (ftype,length,propname) = records[100][key] - write_prop(self.header.fw,ftype,self.object.properties['FLT']['EXT'][propname],length) - #write extension data - for i in xrange(datalen): - self.header.fw.write_uchar(struct.unpack('>B', struct.pack('>B', self.object.properties['FLT']['EXT']['data'][i]))[0]) - self.write_pop_extension() - - - self.write_longid(self.name) #fix this! - - if options.state['transform'] or self.opcode == 63: - #writing transform matrix.... - self.write_matrix() - - if self.opcode == 111: - self.write_lps() - elif self.face_lst != [] or self.children: - self.write_push() - if self.face_lst != []: - #self.write_push() - self.write_faces() - #self.write_pop() - - if self.children: - #self.write_push() - for child in self.children: - child.write() - #self.write_pop() - self.write_pop() - - def __init__(self, parent, header, object,props,ftype): - self.opcode = ftype #both these next two lines need to be in the node class.... - self.childtypes = childtypes[self.opcode] - Node.__init__(self, parent, header, object,props) - self.face_lst = [] - self.vert_lst = [] #for light points. - self.mesh = None - self.uvlayer = 0 - self.flipx = False - self.flipy = False - self.flipz = False - - - if self.object.type == 'Mesh': - self.mesh = self.object.getData(mesh=True) - if(self.mesh.faceUV): - self.uvLayer = len(self.mesh.getUVLayerNames()) - -class Database(Node): - def write_header(self): - if options.verbose >= 2: - print 'Writing header.' - self.fw.write_short(1) # Header opcode - self.fw.write_ushort(324) # Length of record - self.fw.write_string('db', 8) # ASCII ID - self.fw.write_int(1600) # Revision Number - self.fw.pad(44) - self.fw.write_short(1) # Unit multiplier. - self.fw.write_char(0) # Units, 0 = meters - self.fw.write_char(0) # texwhite on new faces 0 = false - self.fw.write_uint(0x80000000) # misc flags set to saving vertex normals - self.fw.pad(24) - self.fw.write_int(0) # projection type, 0 = flat earth - self.fw.pad(30) - self.fw.write_short(1) # double precision - self.fw.write_int(100) # database origin type - self.fw.pad(88) - try: - self.fw.write_double(self.header.scene.properties['FLT']['origin lat']) #database origin lattitude - except: - self.fw.write_double(0) - try: - self.fw.write_double(self.header.scene.properties['FLT']['origin lon']) #database origin longitude - except: - self.fw.write_double(0) - self.fw.pad(32) - self.fw.write_int(0) # ellipsoid model, 0 = WSG 1984 - - self.fw.pad(52) - - def write_vert_pal(self): - if options.verbose >= 2: - print 'Writing vertex palette.' - # Write record for vertex palette - self.fw.write_short(67) # Vertex palette opcode. - self.fw.write_short(8) # Length of record - self.fw.write_int(self.GRR.vertex_count() * 64 + 8) # Length of everything. - # Write records for individual vertices. - for i in xrange(self.GRR.vertex_count()): - desc = self.GRR.request_vertex_desc(i) - self.fw.write_short(70) # Vertex with color normal and uv opcode. - self.fw.write_ushort(64) # Length of record - self.fw.write_ushort(0) # Color name index - self.fw.write_short(1 << 14) # Frozen Normal - self.fw.write_double(desc.x) - self.fw.write_double(desc.y) - self.fw.write_double(desc.z) - self.fw.write_float(desc.nx) - self.fw.write_float(desc.ny) - self.fw.write_float(desc.nz) - self.fw.write_float(desc.u) - self.fw.write_float(desc.v) - self.fw.pad(4) - self.fw.write_uint(desc.cindex) - self.fw.pad(4) - - def write_tex_pal(self): - if options.verbose >= 2: - print 'Writing texture palette.' - # Write record for texture palette - for i, img in enumerate(self.GRR.texture_lst): - filename = tex_files[img.name] - self.fw.write_short(64) # Texture palette opcode. - self.fw.write_short(216) # Length of record - self.fw.write_string(filename, 200) # Filename - self.fw.write_int(i) # Texture index - self.fw.write_int(0) # X - self.fw.write_int(0) # Y - - def write_mat_pal(self): - if options.verbose >= 2: - print 'Writing material palette.' - for i in xrange(self.GRR.material_count()): - desc = self.GRR.request_material_desc(i) - self.fw.write_short(113) # Material palette opcode. - self.fw.write_short(84) # Length of record - self.fw.write_int(i) # Material index - self.fw.write_string(desc.name, 12) # Material name - self.fw.write_uint(0x80000000) # Flags - self.fw.write_float(desc.ambient[0]) # Ambient color. - self.fw.write_float(desc.ambient[1]) # Ambient color. - self.fw.write_float(desc.ambient[2]) # Ambient color. - self.fw.write_float(desc.diffuse[0]) # Diffuse color. - self.fw.write_float(desc.diffuse[1]) # Diffuse color. - self.fw.write_float(desc.diffuse[2]) # Diffuse color. - self.fw.write_float(desc.specular[0]) # Specular color. - self.fw.write_float(desc.specular[1]) # Specular color. - self.fw.write_float(desc.specular[2]) # Specular color. - self.fw.write_float(desc.emissive[0]) # Emissive color. - self.fw.write_float(desc.emissive[1]) # Emissive color. - self.fw.write_float(desc.emissive[2]) # Emissive color. - self.fw.write_float(desc.shininess) - self.fw.write_float(desc.alpha) - self.fw.write_int(0) # Reserved - - def write_col_pal(self): - if options.verbose >= 2: - print 'Writing color palette.' - self.fw.write_short(32) # Color palette opcode. - self.fw.write_short(4228) # Length of record - self.fw.pad(128) - try: - cpalette = self.scene.properties['FLT']['Color Palette'] - except: - cpalette = defaultp.pal - count = len(cpalette) - for i in xrange(count): - color = struct.unpack('>BBBB',struct.pack('>i',cpalette[i])) - self.fw.write_uchar(color[3]) # alpha - self.fw.write_uchar(color[2]) # b - self.fw.write_uchar(color[1]) # g - self.fw.write_uchar(color[0]) # r - self.fw.pad(max(4096-count*4, 0)) - - def write(self): - self.write_header() - self.write_vert_pal() - self.write_tex_pal() - self.write_mat_pal() - self.write_col_pal() - - self.write_push() - - for child in self.children: - child.write() - self.write_pop() - - def export_textures(self,texturepath): - for i in xrange(self.GRR.texture_count()): - texture = self.GRR.texture_lst[i] - - if options.state['copytex']: - filename = os.path.normpath(os.path.join(options.state['texturespath'], os.path.basename(self.GRR.request_texture_filename(i)))) - else: - filename = os.path.normpath(self.GRR.request_texture_filename(i)) - - tex_files[texture.name] = filename - - def blender_export(self): - Node.blender_export(self) - self.export_textures(self) - return self.xrefnames - def __init__(self, scene, fw): - self.fw = fw - self.opcode = 1 - self.childtypes = [73,14,2,63] - self.scene = scene - self.childhash = dict() - self.parenthash = dict() - self.child_objects = list() - self.mnodes = list() - self.xrefnames = list() - for i in self.scene.objects: - self.parenthash[i.name] = list() - self.childhash[i.name] = False - for i in self.scene.objects: - if i.parent: - self.childhash[i.parent.name] = True - self.parenthash[i.parent.name].append(i) - else: - self.child_objects.append(i) - - self.GRR = GlobalResourceRepository() - Node.__init__(self, None, self, None,None) - -def write_attribute_files(): - for imgname in tex_files: - blentex = Blender.Image.Get(imgname) - exportdict = FLT_Records['Image'].copy() - - if blentex.properties.has_key('FLT'): - for key in exportdict.keys(): - if blentex.properties.has_key(key): - exportdict[key] = blentex.properties['FLT'][key] - - # ClampX/Y override - if blentex.clampX: - exportdict['11i!WrapU'] = 1 - if blentex.clampY: - exportdict['12i!WrapV'] = 1 - - exportdict['16i!Enviorment'] = 0 - - # File type - typecode = 0 - try: - typestring = os.path.splitext(blentex.getFilename())[1] - - if typestring == '.rgba': - typecode = 5 - elif typestring == '.rgb': - typecode = 4 - elif typestring == '.inta': - typecode = 3 - elif typestring == '.int': - typecode = 2 - except: - pass - - exportdict['7i!File Format'] = typecode - - fw = FltOut(tex_files[imgname] + '.attr') - size = blentex.getSize() - fw.write_int(size[0]) - fw.write_int(size[1]) - for key in records['Image']: - (ftype,length,propname) = records['Image'][key] - write_prop(fw,ftype,exportdict[propname],length) - fw.close_file() - -#globals used by the scene export function -exportlevel = None -xrefsdone = None - -def dbexport_internal(scene): - global exportlevel - global xrefsdone - global options - - if exportlevel == 0 or not options.state['externalspath']: - fname = os.path.join(options.state['basepath'],scene.name + '.flt') - else: - fname = os.path.join(options.state['externalspath'],scene.name + '.flt') - - fw = FltOut(fname) - db = Database(scene,fw) - - if options.verbose >= 1: - print 'Pass 1: Exporting ', scene.name,'.flt from Blender.\n' - - xreflist = db.blender_export() - if options.verbose >= 1: - print 'Pass 2: Writing %s\n' % fname - db.write() - fw.close_file() - - if options.state['doxrefs']: - for xname in xreflist: - try: - xrefscene = Blender.Scene.Get(xname) - except: - xrefscene = None - if xrefscene and xname not in xrefsdone: - xrefsdone.append(xname) - exportlevel+=1 - dbexport_internal(xrefscene) - exportlevel-=1 - return fname -#main database export function -def dbexport(): - global exportlevel - global xrefsdone - exportlevel = 0 - xrefsdone = list() - - Blender.Window.WaitCursor(True) - time1 = Blender.sys.time() # Start timing - - if options.verbose >= 1: - print '\nOpenFlight Exporter' - print 'Version:', __version__ - print 'Author: Greg MacDonald, Geoffrey Bantle' - print __url__[2] - print - - fname = dbexport_internal(Blender.Scene.GetCurrent()) - if options.verbose >=1: - print 'Done in %.4f sec.\n' % (Blender.sys.time() - time1) - Blender.Window.WaitCursor(False) - - #optional: Copy textures - if options.state['copytex']: - for imgname in tex_files: - #Check to see if texture exists in target directory - if not os.path.exists(tex_files[imgname]): - #Get original Blender file name - origpath = Blender.sys.expandpath(Blender.Image.Get(imgname).getFilename()) - #copy original to new - if os.path.exists(origpath): - shutil.copyfile(origpath,tex_files[imgname]) - - #optional: Write attribute files - if options.state['attrib']: - write_attribute_files() - - if options.state['xapp']: - cmd= options.state['xappath'] + " " + fname - status = os.system(cmd) - - -#Begin UI code -FLTExport = None -FLTClose = None -FLTLabel = None - -FLTBaseLabel = None -FLTTextureLabel = None -FLTXRefLabel = None - -FLTBaseString = None -FLTTextureString = None -FLTXRefString = None - -FLTBasePath = None -FLTTexturePath = None -FLTXRefPath = None - -FLTShadeExport = None -FLTShadeDefault = None - -FLTCopyTex = None -FLTDoXRef = None -FLTGlobal = None - -FLTScale = None - -FLTXAPP = None -FLTXAPPath = None -FLTXAPPString = None -FLTXAPPLabel = None -FLTXAPPChooser = None - -FLTAttrib = None - - -FLTWarn = None - -def setshadingangle(ID,val): - global options - options.state['shading_default'] = val -def setBpath(fname): - global options - options.state['basepath'] = os.path.dirname(fname) - #update xref and textures path too.... - if(os.path.exists(os.path.join(options.state['basepath'],'externals'))): - options.state['externalspath'] = os.path.join(options.state['basepath'],'externals') - if(os.path.exists(os.path.join(options.state['basepath'],'textures'))): - options.state['texturespath'] = os.path.join(options.state['basepath'],'textures') -def setexportscale(ID,val): - global options - options.state['scale'] = val - -def setTpath(fname): - global options - options.state['texturespath'] = os.path.dirname(fname) -def setXpath(fname): - global options - options.state['externalspath'] = os.path.dirname(fname) -def setXApath(fname): - global options - options.state['xappath'] = fname -def event(evt, val): - x = 1 -def but_event(evt): - global options - - global FLTExport - global FLTClose - global FLTLabel - - global FLTBaseLabel - global FLTTextureLabel - global FLTXRefLabel - - global FLTBaseString - global FLTTextureString - global FLTXRefString - - global FLTBasePath - global FLTTexturePath - global FLTXRefPath - - global FLTShadeExport - global FLTShadeDefault - - global FLTCopyTex - global FLTDoXRef - global FLTGlobal - - global FLTScale - - - global FLTXAPP - global FLTXAPPath - global FLTXAPPString - global FLTXAPPLabel - global FLTXAPPChooser - - global FLTAttrib - - global FLTWarn - - #choose base path for export - if evt == 4: - Blender.Window.FileSelector(setBpath, "DB Root", options.state['basepath']) - - #choose XREF path - if evt == 6: - Blender.Window.FileSelector(setXpath,"DB Externals",options.state['externalspath']) - - #choose texture path - if evt == 8: - Blender.Window.FileSelector(setTpath,"DB Textures",options.state['texturespath']) - - #export shading toggle - if evt == 9: - options.state['export_shading'] = FLTShadeExport.val - #export Textures - if evt == 11: - options.state['copytex']= FLTCopyTex.val - #export XRefs - if evt == 13: - options.state['doxrefs'] = FLTDoXRef.val - #export Transforms - if evt == 12: - options.state['transform'] = FLTGlobal.val - - if evt == 14: - options.state['xapp'] = FLTXAPP.val - if evt == 16: - Blender.Window.FileSelector(setXApath,"External Application",options.state['xappath']) - if evt == 20: - options.state['attrib'] = FLTAttrib.val - - #Export DB - if evt == 1: - try: - dbexport() - except Exception, inst: - import traceback - FLTWarn = Draw.PupBlock("Export Error", ["See console for output!"]) - traceback.print_exception(sys.exc_type, sys.exc_value, sys.exc_traceback) - - #exit - if evt == 2: - Draw.Exit() - - options.write_state() - -from Blender.BGL import * -from Blender import Draw -def gui(): - - global options - - global FLTExport - global FLTClose - global FLTLabel - - global FLTBaseLabel - global FLTTextureLabel - global FLTXRefLabel - - global FLTBaseString - global FLTTextureString - global FLTXRefString - - global FLTBasePath - global FLTTexturePath - global FLTXRefPath - - global FLTShadeExport - global FLTShadeDefault - - global FLTCopyTex - global FLTDoXRef - global FLTGlobal - - global FLTScale - - global FLTXAPP - global FLTXAPPath - global FLTXAPPString - global FLTXAPPLabel - global FLTXAPPChooser - - global FLTAttrib - - glClearColor(0.880,0.890,0.730,1.0 ) - glClear(GL_COLOR_BUFFER_BIT) - - areas = Blender.Window.GetScreenInfo() - curarea = Blender.Window.GetAreaID() - curRect = None - - for area in areas: - if area['id'] == curarea: - curRect = area['vertices'] - break - - width = curRect[2] - curRect[0] - height = curRect[3] - curRect[1] - #draw from top to bottom.... - cx = 50 - #Draw Title Bar... - #glRasterPos2d(cx, curRect[3]-100) - #FLTLabel = Draw.Text("FLT Exporter V2.0",'large') - cy = height - 80 - - FLTBaseLabel = Draw.Label("Base Path:",cx,cy,100,20) - FLTBaseString = Draw.String("",3,cx+100,cy,300,20,options.state['basepath'],255,"Folder to export to") - FLTBaseChooser = Draw.PushButton("...",4,cx+400,cy,20,20,"Choose Folder") - - cy = cy-40 - - #externals path - FLTXRefLabel = Draw.Label("XRefs:",cx,cy,100,20) - FLTXRefString = Draw.String("",5,cx+100,cy,300,20,options.state['externalspath'],255,"Folder for external references") - FLTXRefChooser = Draw.PushButton("...",6,cx+400,cy,20,20,"Choose Folder") - cy = cy-40 - #Textures path - FLTTextureLabel = Draw.Label("Textures:",cx,cy,100,20) - FLTTextureString = Draw.String("",7,cx+100,cy,300,20,options.state['texturespath'],255,"Folder for texture files") - FLTTextureChooser = Draw.PushButton("...",8,cx+400,cy,20,20,"Choose Folder") - cy=cy-40 - #External application path - FLTXAPPLabel = Draw.Label("XApp:",cx,cy,100,20) - FLTXAPPString = Draw.String("",15,cx+100,cy,300,20,options.state['xappath'],255,"External application to launch when done") - FLTXAPPChooser = Draw.PushButton("...",16,cx+400, cy,20,20,"Choose Folder") - - cy = cy-60 - #Shading Options - FLTShadeExport = Draw.Toggle("Default Shading",9,cx,cy,100,20,options.state['export_shading'],"Turn on export of custom shading") - FLTShadDefault = Draw.Number("",10,cx + 120,cy,100,20,options.state['shading_default'],0.0,180.0,"Default shading angle for objects with no custom shading assigned",setshadingangle) - - cy = cy-40 - FLTScale = Draw.Number("Export Scale",14,cx,cy,220,20,options.state['scale'],0.0,100.0,"Export scaling factor",setexportscale) - - cy = cy-40 - #misc Options - FLTCopyTex = Draw.Toggle("Copy Textures",11,cx,cy,220,20,options.state['copytex'],"Copy textures to folder indicated above") - cy = cy-40 - FLTGlobal = Draw.Toggle("Export Transforms",12,cx,cy,220,20,options.state['transform'],"If unchecked, Global coordinates are used (recommended)") - cy = cy-40 - FLTDoXRef = Draw.Toggle("Export XRefs", 13,cx,cy,220,20,options.state['doxrefs'],"Export External references (only those below current scene!)") - cy = cy-40 - FLTXAPP = Draw.Toggle("Launch External App", 14, cx,cy,220,20,options.state['xapp'],"Launch External Application on export") - cy = cy-40 - FLTAttrib = Draw.Toggle("Write Attribute Files", 20, cx, cy, 220,20,options.state['attrib'], "Write Texture Attribute files") - #FLTXAPPATH = Draw.String("",15,cx,cy,300,20,options.xappath,255,"External application path") - - - #Draw export/close buttons - FLTExport = Draw.PushButton("Export",1,cx,20,100,20,"Export to FLT") - FLTClose = Draw.PushButton("Close", 2, cx+120,20,100,20,"Close window") - - -Draw.Register(gui,event,but_event)
\ No newline at end of file diff --git a/release/scripts/flt_filewalker.py b/release/scripts/flt_filewalker.py deleted file mode 100644 index 4a9b86c45d2..00000000000 --- a/release/scripts/flt_filewalker.py +++ /dev/null @@ -1,286 +0,0 @@ -#!BPY - -# flt_filewalker.py is an utility module for OpenFlight IO scripts for blender. -# Copyright (C) 2005 Greg MacDonald -# -# 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. - -__bpydoc__ ="""\ -File read/write module used by OpenFlight I/O and tool scripts. OpenFlight is a -registered trademark of MultiGen-Paradigm, Inc. -""" - -import Blender -from struct import * -import re - -class FltIn: - def __init__(self, filename): - self.file = open(filename, 'rb') - self.position = 0 - self.next_position = 100000 - self.opcode = 0 - self.length = 0 - self.level = 0 - self.repeat = False # Repeat the last record. - - def begin_record(self): - if self.repeat == True: - self.repeat = False - else: - self.position += self.length - try: - self.file.seek(self.position) - input = self.file.read(4) - except: - print 'Parse Error!' - return False - - if not input: - self.close_file() - return False - - self.opcode = unpack('>h', input[:2])[0] - self.length = unpack('>H', input[-2:])[0] - - self.next_position = self.position + self.length - - return True - - def repeat_record(self): - self.repeat = True - - def get_opcode(self): - return self.opcode - - def get_level(self): - return self.level - - def up_level(self): - self.level += 1 - - def down_level(self): - self.level -= 1 - - def read_string(self, length): - s = '' - if self.file.tell() + length <= self.next_position: - start = self.file.tell() - for i in xrange(length): - char = self.file.read(1) - if char == '\x00': - break - s = s + char - - self.file.seek(start+length) -# else: -# print 'Warning: string truncated' - - return s - - def read_int(self): - if self.file.tell() + 4 <= self.next_position: - return unpack('>i', self.file.read(4))[0] - else: - #print 'Warning: int truncated' - return 0 - - def read_uint(self): - if self.file.tell() + 4 <= self.next_position: - return unpack('>I', self.file.read(4))[0] - else: - #print 'Warning: uint truncated' - return 0 - - def read_double(self): - if self.file.tell() + 8 <= self.next_position: - return unpack('>d', self.file.read(8))[0] - else: - #print 'Warning: double truncated' - return 0.0 - - def read_float(self): - if self.file.tell() + 4 <= self.next_position: - return unpack('>f', self.file.read(4))[0] - else: - #print 'Warning: float truncated' - return 0.0 - - def read_ushort(self): - if self.file.tell() + 2 <= self.next_position: - return unpack('>H', self.file.read(2))[0] - else: - #print 'Warning: ushort truncated' - return 0 - - def read_short(self): - if self.file.tell() + 2 <= self.next_position: - return unpack('>h', self.file.read(2))[0] - else: - #print 'Warning: short trunated' - return 0 - - def read_uchar(self): - if self.file.tell() + 1 <= self.next_position: - return unpack('>B', self.file.read(1))[0] - else: - #print 'Warning: uchar truncated' - return 0 - - def read_char(self): - if self.file.tell() + 1 <= self.next_position: - return unpack('>b', self.file.read(1))[0] - else: - #print 'Warning: char truncated' - return 0 - - def read_ahead(self, i): - if self.file.tell() + i <= self.next_position: - self.file.seek(i, 1) -# else: -# print 'Warning: attempt to seek past record' - - def get_length(self): - return self.length - - def close_file(self): - self.file.close() - -class FltOut: - # Length includes terminating null - def write_string(self, string, length): - if len(string) > length - 1: - str_len = length - 1 - else: - str_len = len(string) - - pad_len = length - str_len - - self.file.write(string[:str_len]) - - self.pad(pad_len) - - def write_int(self, a): - self.file.write( pack('>i', a) ) - - def write_uint(self, a): - self.file.write( pack('>I', a) ) - - def write_double(self, a): - self.file.write( pack('>d', a) ) - - def write_float(self, a): - self.file.write( pack('>f', a) ) - - def write_ushort(self, a): - self.file.write( pack('>H', a) ) - - def write_short(self, a): - self.file.write( pack('>h', a) ) - - def write_uchar(self, a): - self.file.write( pack('>B', a) ) - - def write_char(self, a): - self.file.write( pack('>b', a) ) - - def pad(self, reps): - for i in xrange(reps): - self.file.write('\x00') - - def close_file(self): - self.file.close() - - def __init__(self, filename): - self.file = open(filename, 'wb') - self.filename = filename - - -class FileFinder: - def add_file_to_search_path(self, filename): - dir = Blender.sys.dirname(filename) - if dir != None and dir != '': - self.search_dirs.append(dir) - - def strip_path(self, full_path): - # One of my flt files had a windows path with unix seperation. Basename - # returned the whole path + filename, which isn't expected. So my - # attempt to fix it is to replace all / or \ with the platform specific - # dir seperator. - # - # note: \\\\ is actually just one \ indirected twice, once for python - # then again for re.sub - if Blender.sys.sep == '\\': - full_path = re.sub('/', '\\\\', full_path) - elif Blender.sys.sep == '/': - full_path = re.sub('\\\\', '/', full_path) - - filename = Blender.sys.basename(full_path) - return filename - - def find(self, full_path): - if full_path == '': - return None - - # Seperate out the path. - dirname = Blender.sys.dirname(full_path) - - # Try it first. - if Blender.sys.exists(full_path): - if not dirname in self.search_dirs: - self.search_dirs.append(dirname) - return full_path - - # Maybe it's relative. - for path in self.search_dirs: - rel_full_path = Blender.sys.join(path, full_path) - if Blender.sys.exists(rel_full_path): - return rel_full_path - - # Search previous directories that have worked. - filename = self.strip_path(full_path) - for path in self.search_dirs: - t = Blender.sys.join(path, filename) - if Blender.sys.exists(t): - return t - - # Ask user where it is. - self.user_input = Blender.Draw.PupStrInput(filename + "? ", '', 100) - #self.user_input = None - if self.user_input != None: - t = Blender.sys.join(self.user_input, filename) - if Blender.sys.exists(t): - user_dirname = Blender.sys.dirname(t) - if not user_dirname in self.search_dirs: - self.search_dirs.append(user_dirname) - return t - - # Couldn't find it. - return None - - def __init__(self): - self.user_input = '' - self.current_file = '' - self.search_dirs = [] - - dir = Blender.Get('texturesdir') - if dir != None and dir != '': - self.search_dirs.append(dir) - - dir = Blender.sys.dirname(Blender.Get('filename')) - if dir != None and dir != '': - print dir - self.search_dirs.append(dir) -
\ No newline at end of file diff --git a/release/scripts/flt_import.py b/release/scripts/flt_import.py deleted file mode 100644 index f8d31f7bb57..00000000000 --- a/release/scripts/flt_import.py +++ /dev/null @@ -1,2534 +0,0 @@ -#!BPY -""" Registration info for Blender menus: -Name: 'OpenFlight (.flt)...' -Blender: 245 -Group: 'Import' -Tip: 'Import OpenFlight (.flt)' -""" - - - -__author__ = "Greg MacDonald, Campbell Barton, Geoffrey Bantle" -__version__ = "2.0 11/21/07" -__url__ = ("blender", "blenderartists.org", "Author's homepage, http://sourceforge.net/projects/blight/") -__bpydoc__ = """\ -This script imports OpenFlight files into Blender. OpenFlight is a -registered trademark of MultiGen-Paradigm, Inc. - -Feature overview and more availible at: -http://wiki.blender.org/index.php/Scripts/Manual/Import/openflight_fltss - -Note: This file is a grab-bag of old and new code. It needs some cleanup still. -""" - -# flt_import.py is an OpenFlight importer for blender. -# Copyright (C) 2005 Greg MacDonald, 2007 Blender Foundation -# -# 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. - -import Blender -import os -import BPyMesh -import BPyImage -import flt_filewalker -import flt_properties -import sys -reload(flt_properties) -from flt_properties import * - -#Globals. Should Clean these up and minimize their usage. - -typecodes = ['c','C','s','S','i','I','f','d','t'] -records = dict() - -FLTBaseLabel = None -FLTBaseString = None -FLTBaseChooser = None -FLTExport = None -FLTClose = None -FLTDoXRef = None -FLTScale = None -FLTShadeImport = None -FLTAttrib = None -FLTWarn = None - -Vector= Blender.Mathutils.Vector -FLOAT_TOLERANCE = 0.01 - -FF = flt_filewalker.FileFinder() -current_layer = 0x01 - -global_prefs = dict() -global_prefs['verbose']= 4 -global_prefs['get_texture'] = True -global_prefs['get_diffuse'] = True -global_prefs['get_specular'] = False -global_prefs['get_emissive'] = False -global_prefs['get_alpha'] = True -global_prefs['get_ambient'] = False -global_prefs['get_shininess'] = True -global_prefs['color_from_face'] = True -global_prefs['fltfile']= '' -global_prefs['smoothshading'] = 1 -global_prefs['doxrefs'] = 1 -global_prefs['scale'] = 1.0 -global_prefs['attrib'] = 0 -msg_once = False - -reg = Blender.Registry.GetKey('flt_import',1) -if reg: - for key in global_prefs: - if reg.has_key(key): - global_prefs[key] = reg[key] - - - -throw_back_opcodes = [2, 73, 4, 11, 96, 14, 91, 98, 63,111] # Opcodes that indicate its time to return control to parent. -do_not_report_opcodes = [76, 78, 79, 80, 81, 82, 94, 83, 33, 112, 101, 102, 97, 31, 103, 104, 117, 118, 120, 121, 124, 125] - -#Process FLT record definitions -for record in FLT_Records: - props = dict() - for prop in FLT_Records[record]: - position = '' - slice = 0 - (format,name) = prop.split('!') - for i in format: - if i not in typecodes: - position = position + i - slice = slice + 1 - else: - break - type = format[slice:] - length = type[1:] - if len(length) == 0: - length = 1 - else: - type = type[0] - length = int(length) - - props[int(position)] = (type,length,prop) - records[record] = props - -def col_to_gray(c): - return 0.3*c[0] + 0.59*c[1] + 0.11*c[2] -class MaterialDesc: - # Was going to use int(f*1000.0) instead of round(f,3), but for some reason - # round produces better results, as in less dups. - def make_key(self): - key = list() - if global_prefs['get_texture']: - if self.tex0: - key.append(self.tex0.getName()) - else: - key.append(None) - - if global_prefs['get_alpha']: - key.append(round(self.alpha, 3)) - else: - key.append(None) - - if global_prefs['get_shininess']: - key.append(round(self.shininess, 3)) - else: - key.append(None) - - if global_prefs['get_emissive']: - key.append(round(self.emissive, 3)) - else: - key.append(None) - - if global_prefs['get_ambient']: - key.append(round(self.ambient, 3)) - else: - key.append(None) - - if global_prefs['get_specular']: - for n in self.specular: - key.append(round(n, 3)) - else: - key.extend([None, None, None]) - - if global_prefs['get_diffuse']: - for n in self.diffuse: - key.append(round(n, 3)) - else: - key.extend([None, None, None]) - -# key.extend(self.face_props.values()) - - return tuple(key) - - def __init__(self): - self.name = 'Material' - # Colors, List of 3 floats. - self.diffuse = [1.0, 1.0, 1.0] - self.specular = [1.0, 1.0, 1.0] - - # Scalars - self.ambient = 0.0 # [0.0, 1.0] - self.emissive = 0.0 # [0.0, 1.0] - self.shininess = 0.5 # Range is [0.0, 2.0] - self.alpha = 1.0 # Range is [0.0, 1.0] - - self.tex0 = None - - # OpenFlight Face attributes - self.face_props = dict.fromkeys(['comment', 'ir color', 'priority', - 'draw type', 'texture white', 'template billboard', - 'smc', 'fid', 'ir material', 'lod generation control', - 'flags', 'light mode']) - -class VertexDesc: - def make_key(self): - return round(self.x, 6), round(self.y, 6), round(self.z, 6) - - def __init__(self): - - # Assign later, save memory, all verts have a loc - self.x = 0.0 - self.y = 0.0 - self.z = 0.0 - - - self.nx = 0.0 - self.ny = 0.0 - self.nz = 0.0 - - self.uv= Vector(0,0) - self.cindex = 127 #default/lowest - self.cnorm = False - -class LightPointAppDesc: - def make_key(self): - d = dict(self.props) - del d['id'] - del d['type'] - - if d['directionality'] != 0: # not omni - d['nx'] = 0.0 - d['ny'] = 0.0 - d['nz'] = 0.0 - - return tuple(d.values()) - - def __init__(self): - self.props = dict() - self.props.update({'type': 'LPA'}) - self.props.update({'id': 'ap'}) - # Attribs not found in inline lightpoint. - self.props.update({'visibility range': 0.0}) - self.props.update({'fade range ratio': 0.0}) - self.props.update({'fade in duration': 0.0}) - self.props.update({'fade out duration': 0.0}) - self.props.update({'LOD range ratio': 0.0}) - self.props.update({'LOD scale': 0.0}) - -class GlobalResourceRepository: - def request_lightpoint_app(self, desc, scene): - match = self.light_point_app.get(desc.make_key()) - - if match: - return match.getName() - else: - # Create empty and fill with properties. - name = desc.props['type'] + ': ' + desc.props['id'] - object = Blender.Object.New('Empty', name) - scene.objects.link(object) - object.Layers= current_layer - object.sel= 1 - - # Attach properties - for name, value in desc.props.iteritems(): - object.addProperty(name, value) - - self.light_point_app.update({desc.make_key(): object}) - - return object.getName() - - # Dont use request_vert - faster to make it from the vector direct. - """ - def request_vert(self, desc): - match = self.vert_dict.get(desc.make_key()) - - if match: - return match - else: - vert = Blender.Mathutils.Vector(desc.x, desc.y, desc.z) - ''' IGNORE_NORMALS - vert.no[0] = desc.nx - vert.no[1] = desc.ny - vert.no[2] = desc.nz - ''' - self.vert_dict.update({desc.make_key(): vert}) - return vert - """ - def request_mat(self, mat_desc): - match = self.mat_dict.get(mat_desc.make_key()) - if match: return match - - mat = Blender.Material.New(mat_desc.name) - - if mat_desc.tex0 != None: - mat.setTexture(0, mat_desc.tex0, Blender.Texture.TexCo.UV) - - mat.setAlpha(mat_desc.alpha) - mat.setSpec(mat_desc.shininess) - mat.setHardness(255) - mat.setEmit(mat_desc.emissive) - mat.setAmb(mat_desc.ambient) - mat.setSpecCol(mat_desc.specular) - mat.setRGBCol(mat_desc.diffuse) - - # Create a text object to store openflight face attribs until - # user properties can be set on materials. -# t = Blender.Text.New('FACE: ' + mat.getName()) -# -# for name, value in mat_desc.face_props.items(): -# t.write(name + '\n' + str(value) + '\n\n') - - self.mat_dict.update({mat_desc.make_key(): mat}) - - return mat - - def request_image(self, filename_with_path): - if not global_prefs['get_texture']: return None - return BPyImage.comprehensiveImageLoad(filename_with_path, global_prefs['fltfile']) # Use join in case of spaces - - def request_texture(self, image): - if not global_prefs['get_texture']: - return None - - tex = self.tex_dict.get(image.filename) - if tex: return tex - - tex = Blender.Texture.New(Blender.sys.basename(image.filename)) - tex.setImage(image) - tex.setType('Image') - self.tex_dict.update({image.filename: tex}) - return tex - - def __init__(self): - - #list of scenes xrefs belong to. - self.xrefs = dict() - # material - self.mat_dict = dict() - mat_lst = Blender.Material.Get() - for mat in mat_lst: - mat_desc = MaterialDesc() - mapto_lst = mat.getTextures() - if mapto_lst[0]: - mat_desc.tex0 = mapto_lst[0].tex - else: - mat_desc.tex0 = None - mat_desc.alpha = mat.getAlpha() - mat_desc.shininess = mat.getSpec() - mat_desc.emissive = mat.getEmit() - mat_desc.ambient = mat.getAmb() - mat_desc.specular = mat.getSpecCol() - mat_desc.diffuse = mat.getRGBCol() - - self.mat_dict.update({mat_desc.make_key(): mat}) - - # texture - self.tex_dict = dict() - tex_lst = Blender.Texture.Get() - - for tex in tex_lst: - img = tex.getImage() - # Only interested in textures with images. - if img: - self.tex_dict.update({img.filename: tex}) - - # vertex - # self.vert_dict = dict() - - # light point - self.light_point_app = dict() - -class Handler: - def in_throw_back_lst(self, opcode): - return opcode in self.throw_back_lst - - def handle(self, opcode): - return self.handler[opcode]() - - def handles(self, opcode): - return opcode in self.handler.iterkeys() - - def throws_back_all_unhandled(self): - return self.throw_back_unhandled - - def set_throw_back_lst(self, a): - self.throw_back_lst = a - - def set_throw_back_all_unhandled(self): - self.throw_back_unhandled = True - - def set_only_throw_back_specified(self): - self.throw_back_unhandled = False - - def set_handler(self, d): - self.handler = d - - def __init__(self): - # Dictionary of opcodes to handler methods. - self.handler = dict() - # Send all opcodes not handled to the parent node. - self.throw_back_unhandled = False - # If throw_back_unhandled is False then only throw back - # if the opcodes in throw_back are encountered. - self.throw_back_lst = list() - -class Node: - def blender_import(self): - if self.opcode in opcode_name and global_prefs['verbose'] >= 2: - for i in xrange(self.get_level()): - print ' ', - print opcode_name[self.opcode], - print '-', self.props['id'], - print '-', self.props['comment'], - - print - - for child in self.children: - child.blender_import() - -# Import comment. -# if self.props['comment'] != '': -# name = 'COMMENT: ' + self.props['id'] -# t = Blender.Text.New(name) -# t.write(self.props['comment']) -# self.props['comment'] = name - - # Always ignore extensions and anything in between them. - def parse_push_extension(self): - self.saved_handler = self.active_handler - self.active_handler = self.extension_handler - return True - - def parse_pop_extension(self): - self.active_handler = self.saved_handler - return True - - def parse_push(self): - self.header.fw.up_level() - # Ignore unknown children. - self.ignore_unhandled = True - # Don't do child records that might overwrite parent info. ex: longid - self.active_handler = self.child_handler - return True - - def parse_pop(self): - self.header.fw.down_level() - - if self.header.fw.get_level() == self.level: - return False - - return True - - def parse(self): - while self.header.fw.begin_record(): - opcode = self.header.fw.get_opcode() - - # Print out info on opcode and tree level. - if global_prefs['verbose'] >= 3: - p = '' - for i in xrange(self.header.fw.get_level()): - p = p + ' ' - if opcode in opcode_name: - p = p + opcode_name[opcode] - else: - if global_prefs['verbose'] >= 1: - print 'undocumented opcode', opcode - continue - - if self.global_handler.handles(opcode): - if global_prefs['verbose'] >= 3: - print p + ' handled globally' - if self.global_handler.handle(opcode) == False: - break - - elif self.active_handler.handles(opcode): - if global_prefs['verbose'] >= 4: - print p + ' handled' - if self.active_handler.handle(opcode) == False: - break - - else: - if self.active_handler.throws_back_all_unhandled(): - if global_prefs['verbose'] >= 3: - print p + ' handled elsewhere' - self.header.fw.repeat_record() - break - - elif self.active_handler.in_throw_back_lst(opcode): - if global_prefs['verbose'] >= 3: - print p + ' handled elsewhere' - self.header.fw.repeat_record() - break - - else: - if global_prefs['verbose'] >= 3: - print p + ' ignored' - elif global_prefs['verbose'] >= 1 and not opcode in do_not_report_opcodes and opcode in opcode_name: - print 'not handled' - - def get_level(self): - return self.level - - def parse_long_id(self): - self.props['id'] = self.header.fw.read_string(self.header.fw.get_length()-4) - return True - - def parse_comment(self): - self.props['comment'] = self.header.fw.read_string(self.header.fw.get_length()-4) - return True - - def parse_extension(self): - extension = dict() - props = records[100] - propkeys = props.keys() - propkeys.sort() - for position in propkeys: - (type,length,name) = props[position] - extension[name] = read_prop(self.header.fw,type,length) - #read extension data. - dstring = list() - for i in xrange(self.header.fw.get_length()-24): - dstring.append(self.header.fw.read_char()) - extension['data'] = dstring - self.extension = extension - def parse_record(self): - self.props['type'] = self.opcode - props = records[self.opcode] - propkeys = props.keys() - propkeys.sort() - for position in propkeys: - (type,length,name) = props[position] - self.props[name] = read_prop(self.header.fw,type,length) - try: #remove me! - self.props['id'] = self.props['3t8!id'] - except: - pass - def __init__(self, parent, header): - self.root_handler = Handler() - self.child_handler = Handler() - self.extension_handler = Handler() - self.global_handler = Handler() - - self.global_handler.set_handler({21: self.parse_push_extension}) - self.active_handler = self.root_handler - - # used by parse_*_extension - self.extension_handler.set_handler({22: self.parse_pop_extension}) - self.saved_handler = None - - self.header = header - self.children = list() - - self.parent = parent - - if parent: - parent.children.append(self) - - self.level = self.header.fw.get_level() - self.opcode = self.header.fw.get_opcode() - - self.props = {'id': 'unnamed', 'comment': '', 'type': 'untyped'} - -class VertexPalette(Node): - def __init__(self, parent): - Node.__init__(self, parent, parent.header) - self.root_handler.set_handler({68: self.parse_vertex_c, - 69: self.parse_vertex_cn, - 70: self.parse_vertex_cnuv, - 71: self.parse_vertex_cuv}) - self.root_handler.set_throw_back_all_unhandled() - - self.vert_desc_lst = list() - self.blender_verts = list() - self.offset = 8 - # Used to create a map from byte offset to vertex index. - self.index = dict() - - - def blender_import(self): - self.blender_verts.extend([Vector(vert_desc.x, vert_desc.y, vert_desc.z) for vert_desc in self.vert_desc_lst ]) - - def parse_vertex_common(self): - # Add this vertex to an offset to index dictionary. - #self.index_lst.append( (self.offset, self.next_index) ) - self.index[self.offset]= len(self.index) - - # Get ready for next record. - self.offset += self.header.fw.get_length() - - v = VertexDesc() - - self.header.fw.read_ahead(2) - v.flags = self.header.fw.read_short() - - v.x = self.header.fw.read_double() - v.y = self.header.fw.read_double() - v.z = self.header.fw.read_double() - - return v - - def parse_vertex_post_common(self, v): - #if not v.flags & 0x2000: # 0x2000 = no color - #if v.flags & 0x1000: # 0x1000 = packed color - # v.a = self.header.fw.read_uchar() - # v.b = self.header.fw.read_uchar() - # v.g = self.header.fw.read_uchar() - # v.r = self.header.fw.read_uchar() - #else: - self.header.fw.read_ahead(4) #skip packed color - v.cindex = self.header.fw.read_uint() - self.vert_desc_lst.append(v) - return True - - def parse_vertex_c(self): - v = self.parse_vertex_common() - - self.parse_vertex_post_common(v) - - return True - - def parse_vertex_cn(self): - v = self.parse_vertex_common() - v.cnorm = True - v.nx = self.header.fw.read_float() - v.ny = self.header.fw.read_float() - v.nz = self.header.fw.read_float() - - self.parse_vertex_post_common(v) - - return True - - def parse_vertex_cuv(self): - v = self.parse_vertex_common() - - v.uv[:] = self.header.fw.read_float(), self.header.fw.read_float() - - self.parse_vertex_post_common(v) - - return True - - def parse_vertex_cnuv(self): - v = self.parse_vertex_common() - v.cnorm = True - v.nx = self.header.fw.read_float() - v.ny = self.header.fw.read_float() - v.nz = self.header.fw.read_float() - - v.uv[:] = self.header.fw.read_float(), self.header.fw.read_float() - - self.parse_vertex_post_common(v) - - return True - - def parse(self): # Run once per import - Node.parse(self) - - -class InterNode(Node): - def __init__(self): - self.object = None - self.mesh = None - self.swapmesh = None - self.hasMesh = False - self.faceLs= [] - self.matrix = None - self.vis = True - self.hasmtex = False - self.uvlayers = dict() - self.blayernames = dict() - self.subfacelevel = 0 - self.extension = None - - mask = 2147483648 - for i in xrange(7): - self.uvlayers[mask] = False - mask = mask / 2 - - ####################################################### - ## Begin Remove Doubles Replacement ## - ####################################################### - def __xvertsort(self,__a,__b): - (__vert, __x1) = __a - (__vert2,__x2) = __b - - if __x1 > __x2: - return 1 - elif __x1 < __x2: - return -1 - return 0 - def __calcFaceNorm(self,__face): - if len(__face) == 3: - return Blender.Mathutils.TriangleNormal(__face[0].co, __face[1].co, __face[2].co) - elif len(__face) == 4: - return Blender.Mathutils.QuadNormal(__face[0].co, __face[1].co, __face[2].co, __face[3].co) - - def __replaceFaceVert(self,__weldface, __oldvert, __newvert): - __index = None - for __i, __v in enumerate(__weldface): - if __v == __oldvert: - __index = __i - break - __weldface[__index] = __newvert - - def __matchEdge(self,__weldmesh, __edge1, __edge2): - if __edge1[0] in __weldmesh['Vertex Disk'][__edge2[1]] and __edge1[1] in __weldmesh['Vertex Disk'][__edge2[0]]: - return True - return False - #have to compare original faces! - def __faceWinding(self, __weldmesh, __face1, __face2): - - __f1edges = list() - __f2edges = list() - - __f1edges.append((__face1.verts[0], __face1.verts[1])) - __f1edges.append((__face1.verts[1], __face1.verts[2])) - if len(__face1.verts) == 3: - __f1edges.append((__face1.verts[2], __face1.verts[0])) - else: - __f1edges.append((__face1.verts[2], __face1.verts[3])) - __f1edges.append((__face1.verts[3], __face1.verts[0])) - - __f2edges.append((__face2.verts[0], __face2.verts[1])) - __f2edges.append((__face2.verts[1], __face2.verts[2])) - if len(__face2.verts) == 3: - __f2edges.append((__face2.verts[2], __face2.verts[0])) - else: - __f2edges.append((__face2.verts[2], __face2.verts[3])) - __f2edges.append((__face2.verts[3], __face2.verts[0])) - - - #find a matching edge - for __edge1 in __f1edges: - for __edge2 in __f2edges: - if self.__matchEdge(__weldmesh, __edge1, __edge2): #no more tests nessecary - return True - - return False - - def __floatcompare(self, __f1, __f2): - epsilon = 0.1 - if ((__f1 + epsilon) > __f2) and ((__f1 - epsilon) < __f2): - return True - return False - def __testFace(self,__weldmesh,__v1face, __v2face, __v1bface, __v2bface): - limit = 0.01 - __matchvert = None - #frst test (for real this time!). Are the faces the same face? - if __v1face == __v2face: - return False - - #first test: Do the faces possibly geometrically share more than two vertices? we should be comparing original faces for this? - Yes..... - __match = 0 - for __vert in __v1bface.verts: - for __vert2 in __v2bface.verts: - #if (abs(__vert.co[0] - __vert2.co[0]) <= limit) and (abs(__vert.co[1] - __vert2.co[1]) <= limit) and (abs(__vert.co[2] - __vert2.co[2]) <= limit): #this needs to be fixed! - if __vert2 in __weldmesh['Vertex Disk'][__vert] or __vert == __vert2: - __match += 1 - __matchvert = __vert2 - #avoid faces sharing more than two verts - if __match > 2: - return False - - #consistent winding for face normals - if __match == 2: - if not self.__faceWinding(__weldmesh, __v1bface, __v2bface): - return False - - #second test: Compatible normals.Anything beyond almost exact opposite is 'ok' - __v1facenorm = self.__calcFaceNorm(__v1face) - __v2facenorm = self.__calcFaceNorm(__v2face) - - #dont even mess with zero length faces - if __v1facenorm.length < limit: - return False - if __v2facenorm.length < limit: - return False - - __v1facenorm.normalize() - __v2facenorm.normalize() - - if __match == 1: - #special case, look for comparison of normals angle - __angle = Blender.Mathutils.AngleBetweenVecs(__v1facenorm, __v2facenorm) - if __angle > 70.0: - return False - - - - __v2facenorm = __v2facenorm.negate() - - if self.__floatcompare(__v1facenorm[0], __v2facenorm[0]) and self.__floatcompare(__v1facenorm[1], __v2facenorm[1]) and self.__floatcompare(__v1facenorm[2], __v2facenorm[2]): - return False - - #next test: dont weld a subface to a non-subface! - if __v1bface.getProperty("FLT_SFLEVEL") != __v2bface.getProperty("FLT_SFLEVEL"): - return False - - #final test: edge test - We dont want to create a non-manifold edge through our weld operation - - return True - - def __copyFaceData(self, __source, __target): - #copy vcolor layers. - __actColLayer = self.mesh.activeColorLayer - for __colorlayer in self.mesh.getColorLayerNames(): - self.mesh.activeColorLayer = __colorlayer - for __i, __col in enumerate(__source.col): - __target.col[__i].r = __col.r - __target.col[__i].g = __col.g - __target.col[__i].b = __col.b - - self.mesh.activeColorLayer = __actColLayer - #copy uv layers. - __actUVLayer = self.mesh.activeUVLayer - for __uvlayer in self.mesh.getUVLayerNames(): - self.mesh.activeUVLayer = __uvlayer - __target.image = __source.image - __target.mode = __source.mode - __target.smooth = __source.smooth - __target.transp = __source.transp - for __i, __uv in enumerate(__source.uv): - __target.uv[__i][0] = __uv[0] - __target.uv[__i][1] = __uv[1] - - self.mesh.activeUVLayer = __actUVLayer - #copy property layers - for __property in self.mesh.faces.properties: - __target.setProperty(__property, __source.getProperty(__property)) - - def findDoubles(self): - limit = 0.01 - sortblock = list() - double = dict() - for vert in self.mesh.verts: - double[vert] = None - sortblock.append((vert, vert.co[0] + vert.co[1] + vert.co[2])) - sortblock.sort(self.__xvertsort) - - a = 0 - while a < len(self.mesh.verts): - (vert,xsort) = sortblock[a] - b = a+1 - if not double[vert]: - while b < len(self.mesh.verts): - (vert2, xsort2) = sortblock[b] - if not double[vert2]: - #first test, simple distance - if (xsort2 - xsort) > limit: - break - #second test, more expensive - if (abs(vert.co[0] - vert2.co[0]) <= limit) and (abs(vert.co[1] - vert2.co[1]) <= limit) and (abs(vert.co[2] - vert2.co[2]) <= limit): - double[vert2] = vert - b+=1 - a+=1 - - return double - - def buildWeldMesh(self): - - weldmesh = dict() - weldmesh['Vertex Disk'] = dict() #this is geometric adjacency - weldmesh['Vertex Faces'] = dict() #topological adjacency - - #find the doubles for this mesh - double = self.findDoubles() - - for vert in self.mesh.verts: - weldmesh['Vertex Faces'][vert] = list() - - #create weld faces - weldfaces = list() - originalfaces = list() - for face in self.mesh.faces: - weldface = list() - for vert in face.verts: - weldface.append(vert) - weldfaces.append(weldface) - originalfaces.append(face) - for i, weldface in enumerate(weldfaces): - for vert in weldface: - weldmesh['Vertex Faces'][vert].append(i) - weldmesh['Weld Faces'] = weldfaces - weldmesh['Original Faces'] = originalfaces - - #Now we need to build the vertex disk data. first we do just the 'target' vertices - for vert in self.mesh.verts: - if not double[vert]: #its a target - weldmesh['Vertex Disk'][vert] = list() - for vert in self.mesh.verts: - if double[vert]: #its a double - weldmesh['Vertex Disk'][double[vert]].append(vert) - - #Now we need to create the disk information for the remaining vertices - targets = weldmesh['Vertex Disk'].keys() - for target in targets: - for doublevert in weldmesh['Vertex Disk'][target]: - weldmesh['Vertex Disk'][doublevert] = [target] - for othervert in weldmesh['Vertex Disk'][target]: - if othervert != doublevert: - weldmesh['Vertex Disk'][doublevert].append(othervert) - - return weldmesh - - def weldFuseFaces(self,weldmesh): - - #retain original loose vertices - looseverts = dict() - for vert in self.mesh.verts: - looseverts[vert] = 0 - for edge in self.mesh.edges: - looseverts[edge.v1] += 1 - looseverts[edge.v2] += 1 - - - - #slight modification here: we need to walk around the mesh as many times as it takes to have no more matches - done = 0 - while not done: - done = 1 - for windex, weldface in enumerate(weldmesh['Weld Faces']): - for vertex in weldface: - #we walk around the faces of the doubles of this vertex and if possible, we weld them. - for doublevert in weldmesh['Vertex Disk'][vertex]: - removeFaces = list() #list of faces to remove from doubleverts face list - for doublefaceindex in weldmesh['Vertex Faces'][doublevert]: - doubleface = weldmesh['Weld Faces'][doublefaceindex] - oface1 = self.mesh.faces[windex] - oface2 = self.mesh.faces[doublefaceindex] - ok = self.__testFace(weldmesh, weldface, doubleface, oface1, oface2) - if ok: - done = 0 - removeFaces.append(doublefaceindex) - self.__replaceFaceVert(doubleface, doublevert, vertex) - for doublefaceindex in removeFaces: - weldmesh['Vertex Faces'][doublevert].remove(doublefaceindex) - #old faces first - oldindices = list() - for face in self.mesh.faces: - oldindices.append(face.index) - #make our new faces. - newfaces = list() - for weldface in weldmesh['Weld Faces']: - newfaces.append(weldface) - newindices = self.mesh.faces.extend(newfaces, indexList=True, ignoreDups=True) - #copy custom data over - for i, newindex in enumerate(newindices): - try: - self.__copyFaceData(self.mesh.faces[oldindices[i]], self.mesh.faces[newindex]) - except: - print "warning, could not copy face data!" - #delete the old faces - self.mesh.faces.delete(1, oldindices) - - #Clean up stray vertices - vertuse = dict() - for vert in self.mesh.verts: - vertuse[vert] = 0 - for face in self.mesh.faces: - for vert in face.verts: - vertuse[vert] += 1 - delverts = list() - for vert in self.mesh.verts: - if not vertuse[vert] and vert.index != 0 and looseverts[vert]: - delverts.append(vert) - - self.mesh.verts.delete(delverts) - - - ####################################################### - ## End Remove Doubles Replacement ## - ####################################################### - - def blender_import_my_faces(self): - - # Add the verts onto the mesh - blender_verts= self.header.vert_pal.blender_verts - vert_desc_lst= self.header.vert_pal.vert_desc_lst - - vert_list= [ i for flt_face in self.faceLs for i in flt_face.indices] #splitting faces apart. Is this a good thing? - face_edges= [] - face_verts= [] - self.mesh.verts.extend([blender_verts[i] for i in vert_list]) - - new_faces= [] - new_faces_props= [] - ngon= BPyMesh.ngon - vert_index= 1 - - #add vertex color layer for baked face colors. - self.mesh.addColorLayer("FLT_Fcol") - self.mesh.activeColorLayer = "FLT_Fcol" - - FLT_OrigIndex = 0 - for flt_face in self.faceLs: - if flt_face.tex_index != -1: - try: - image= self.header.tex_pal[flt_face.tex_index][1] - except KeyError: - image= None - else: - image= None - face_len= len(flt_face.indices) - - #create dummy uvert dicts - if len(flt_face.uverts) == 0: - for i in xrange(face_len): - flt_face.uverts.append(dict()) - #May need to patch up MTex info - if self.hasmtex: - #For every layer in mesh, there should be corresponding layer in the face - for mask in self.uvlayers.keys(): - if self.uvlayers[mask]: - if not flt_face.uvlayers.has_key(mask): #Does the face have this layer? - #Create Layer info for this face - flt_face.uvlayers[mask] = dict() - flt_face.uvlayers[mask]['texture index'] = -1 - flt_face.uvlayers[mask]['texture enviorment'] = 3 - flt_face.uvlayers[mask]['texture mapping'] = 0 - flt_face.uvlayers[mask]['texture data'] = 0 - - #now go through and create dummy uvs for this layer - for uvert in flt_face.uverts: - uv = Vector(0.0,0.0) - uvert[mask] = uv - - # Get the indicies in reference to the mesh. - uvs= [vert_desc_lst[j].uv for j in flt_face.indices] - if face_len == 1: - pass - elif face_len == 2: - face_edges.append((vert_index, vert_index+1)) - elif flt_face.props['draw type'] == 2 or flt_face.props['draw type'] == 3: - i = 0 - while i < (face_len-1): - face_edges.append((vert_index + i, vert_index + i + 1)) - i = i + 1 - if flt_face.props['draw type'] == 2: - face_edges.append((vert_index + i,vert_index)) - elif face_len == 3 or face_len == 4: # tri or quad - #if face_len == 1: - # pass - #if face_len == 2: - # face_edges.append((vert_index, vert_index+1)) - new_faces.append( [i+vert_index for i in xrange(face_len)] ) - new_faces_props.append((None, image, uvs, flt_face.uverts, flt_face.uvlayers, flt_face.color_index, flt_face.props,FLT_OrigIndex,0, flt_face.subfacelevel)) - - else: # fgon - mesh_face_indicies = [i+vert_index for i in xrange(face_len)] - tri_ngons= ngon(self.mesh, mesh_face_indicies) - if len(tri_ngons) != 1: - new_faces.extend([ [mesh_face_indicies[t] for t in tri] for tri in tri_ngons]) - new_faces_props.extend( [ (None, image, (uvs[tri[0]], uvs[tri[1]], uvs[tri[2]]), [flt_face.uverts[tri[0]], flt_face.uverts[tri[1]], flt_face.uverts[tri[2]]], flt_face.uvlayers, flt_face.color_index, flt_face.props,FLT_OrigIndex,1, flt_face.subfacelevel) for tri in tri_ngons ]) - - vert_index+= face_len - FLT_OrigIndex+=1 - - self.mesh.faces.extend(new_faces) - self.mesh.edges.extend(face_edges) - - #add in the FLT_ORIGINDEX layer - if len(self.mesh.faces): - try: self.mesh.faceUV= True - except: pass - - if self.mesh.faceUV == True: - self.mesh.renameUVLayer(self.mesh.activeUVLayer, 'Layer0') - - #create name layer for faces - self.mesh.faces.addPropertyLayer("FLT_ID",Blender.Mesh.PropertyTypes["STRING"]) - #create layer for face color indices - self.mesh.faces.addPropertyLayer("FLT_COL",Blender.Mesh.PropertyTypes["INT"]) - #create index layer for faces. This is needed by both FGONs and subfaces - self.mesh.faces.addPropertyLayer("FLT_ORIGINDEX",Blender.Mesh.PropertyTypes["INT"]) - #create temporary FGON flag layer. Delete after remove doubles - self.mesh.faces.addPropertyLayer("FLT_FGON",Blender.Mesh.PropertyTypes["INT"]) - self.mesh.faces.addPropertyLayer("FLT_SFLEVEL", Blender.Mesh.PropertyTypes["INT"]) - - for i, f in enumerate(self.mesh.faces): - props = new_faces_props[i] - if props[6]['template billboard'] > 0: - f.transp |= Blender.Mesh.FaceTranspModes["ALPHA"] - if props[6]['template billboard'] == 2: - f.mode |= Blender.Mesh.FaceModes["BILLBOARD"] - f.mode |= Blender.Mesh.FaceModes["LIGHT"] - if props[6]['draw type'] == 1: - f.mode |= Blender.Mesh.FaceModes["TWOSIDE"] - - #f.mat = props[0] - f.image = props[1] - f.uv = props[2] - #set vertex colors - color = self.header.get_color(props[5]) - if not color: - color = [255,255,255,255] - for mcol in f.col: - mcol.a = color[3] - mcol.r = color[0] - mcol.g = color[1] - mcol.b = color[2] - - f.setProperty("FLT_SFLEVEL", props[9]) - f.setProperty("FLT_ORIGINDEX",i) - f.setProperty("FLT_ID",props[6]['id']) - #if props[5] > 13199: - # print "Warning, invalid color index read in! Using default!" - # f.setProperty("FLT_COL",127) - #else: - if(1): #uh oh.... - value = struct.unpack('>i',struct.pack('>I',props[5]))[0] - f.setProperty("FLT_COL",value) - - #if props[8]: - # f.setProperty("FLT_FGON",1) - #else: - # f.setProperty("FLT_FGON",0) - - - #Create multitex layers, if present. - actuvlayer = self.mesh.activeUVLayer - if(self.hasmtex): - #For every multi-tex layer, we have to add a new UV layer to the mesh - for i,mask in enumerate(reversed(sorted(self.uvlayers))): - if self.uvlayers[mask]: - self.blayernames[mask] = "Layer" + str(i+1) - self.mesh.addUVLayer(self.blayernames[mask]) - - #Cycle through availible multi-tex layers and add face UVS - for mask in self.uvlayers: - if self.uvlayers[mask]: - self.mesh.activeUVLayer = self.blayernames[mask] - for j, f in enumerate(self.mesh.faces): - if props[6]['draw type'] == 1: - f.mode |= Blender.Mesh.FaceModes["TWOSIDE"] - f.transp |= Blender.Mesh.FaceTranspModes["ALPHA"] - f.mode |= Blender.Mesh.FaceModes["LIGHT"] - props = new_faces_props[j] - uvlayers = props[4] - if uvlayers.has_key(mask): #redundant - uverts = props[3] - for k, uv in enumerate(f.uv): - uv[0] = uverts[k][mask][0] - uv[1] = uverts[k][mask][1] - - uvlayer = uvlayers[mask] - tex_index = uvlayer['texture index'] - if tex_index != -1: - try: - f.image = self.header.tex_pal[tex_index][1] - except KeyError: - f.image = None - - if global_prefs['smoothshading'] == True and len(self.mesh.faces): - #We need to store per-face vertex normals in the faces as UV layers and delete them later. - self.mesh.addUVLayer("FLTNorm1") - self.mesh.addUVLayer("FLTNorm2") - self.mesh.activeUVLayer = "FLTNorm1" - for f in self.mesh.faces: - f.smooth = 1 - #grab the X and Y components of normal and store them in UV - for i, uv in enumerate(f.uv): - vert = f.v[i].index - vert_desc = vert_desc_lst[vert_list[vert-1]] - if vert_desc.cnorm: - uv[0] = vert_desc.nx - uv[1] = vert_desc.ny - else: - uv[0] = 0.0 - uv[1] = 0.0 - - #Now go through and populate the second UV Layer with the z component - self.mesh.activeUVLayer = "FLTNorm2" - for f in self.mesh.faces: - for i, uv in enumerate(f.uv): - vert = f.v[i].index - vert_desc = vert_desc_lst[vert_list[vert-1]] - if vert_desc.cnorm: - uv[0] = vert_desc.nz - uv[1] = 0.0 - else: - uv[0] = 0.0 - uv[1] = 0.0 - - - - #Finally, go through, remove dummy vertex, remove doubles and add edgesplit modifier. - Blender.Mesh.Mode(Blender.Mesh.SelectModes['VERTEX']) - self.mesh.sel= 1 - self.header.scene.update(1) #slow! - - #self.mesh.remDoubles(0.0001) - weldmesh = self.buildWeldMesh() - welded = self.weldFuseFaces(weldmesh) - self.mesh.verts.delete(0) # remove the dummy vert - - edgeHash = dict() - - for edge in self.mesh.edges: - edgeHash[edge.key] = edge.index - - - if global_prefs['smoothshading'] == True and len(self.mesh.faces): - - #rip out the custom vertex normals from the mesh and place them in a face aligned list. Easier to compare this way. - facenorms = [] - self.mesh.activeUVLayer = "FLTNorm1" - for face in self.mesh.faces: - facenorm = [] - for uv in face.uv: - facenorm.append(Vector(uv[0],uv[1],0.0)) - facenorms.append(facenorm) - self.mesh.activeUVLayer = "FLTNorm2" - for i, face in enumerate(self.mesh.faces): - facenorm = facenorms[i] - for j, uv in enumerate(face.uv): - facenorm[j][2] = uv[0] - self.mesh.removeUVLayer("FLTNorm1") - self.mesh.removeUVLayer("FLTNorm2") - - #find hard edges - #store edge data for lookup by faces - #edgeHash = dict() - #for edge in self.mesh.edges: - # edgeHash[edge.key] = edge.index - - edgeNormHash = dict() - #make sure to align the edgenormals to key value! - for i, face in enumerate(self.mesh.faces): - - facenorm = facenorms[i] - faceEdges = [] - faceEdges.append((face.v[0].index,face.v[1].index,facenorm[0],facenorm[1],face.edge_keys[0])) - faceEdges.append((face.v[1].index,face.v[2].index,facenorm[1],facenorm[2],face.edge_keys[1])) - if len(face.v) == 3: - faceEdges.append((face.v[2].index,face.v[0].index,facenorm[2],facenorm[0],face.edge_keys[2])) - elif len(face.v) == 4: - faceEdges.append((face.v[2].index,face.v[3].index,facenorm[2],facenorm[3],face.edge_keys[2])) - faceEdges.append((face.v[3].index,face.v[0].index,facenorm[3],facenorm[0],face.edge_keys[3])) - - #check to see if edgeNormal has been placed in the edgeNormHash yet - #this is a redundant test, and should be optimized to not be called as often as it is. - for j, faceEdge in enumerate(faceEdges): - #the value we are looking for is (faceEdge[2],faceEdge[3]) - hashvalue = (faceEdge[2],faceEdge[3]) - if (faceEdge[0],faceEdge[1]) != faceEdge[4]: - hashvalue = (hashvalue[1],hashvalue[0]) - assert (faceEdge[1],faceEdge[0]) == faceEdge[4] - if edgeNormHash.has_key(faceEdge[4]): - #compare value in the hash, if different, mark as sharp - edgeNorm = edgeNormHash[faceEdge[4]] - if\ - abs(hashvalue[0][0] - edgeNorm[0][0]) > FLOAT_TOLERANCE or\ - abs(hashvalue[0][1] - edgeNorm[0][1]) > FLOAT_TOLERANCE or\ - abs(hashvalue[0][2] - edgeNorm[0][2]) > FLOAT_TOLERANCE or\ - abs(hashvalue[1][0] - edgeNorm[1][0]) > FLOAT_TOLERANCE or\ - abs(hashvalue[1][1] - edgeNorm[1][1]) > FLOAT_TOLERANCE or\ - abs(hashvalue[1][2] - edgeNorm[1][2]) > FLOAT_TOLERANCE: - edge = self.mesh.edges[edgeHash[faceEdge[4]]] - edge.flag |= Blender.Mesh.EdgeFlags.SHARP - - else: - edgeNormHash[faceEdge[4]] = hashvalue - - #add in edgesplit modifier - mod = self.object.modifiers.append(Blender.Modifier.Types.EDGESPLIT) - mod[Blender.Modifier.Settings.EDGESPLIT_FROM_SHARP] = True - mod[Blender.Modifier.Settings.EDGESPLIT_FROM_ANGLE] = False - - if(actuvlayer): - self.mesh.activeUVLayer = actuvlayer - - def blender_import(self): - if self.vis and self.parent.object: - self.vis = self.parent.vis - name = self.props['id'] - - - if self.hasMesh: - self.mesh = Blender.Mesh.New() - self.mesh.name = 'FLT_FaceList' - self.mesh.fakeUser = True - self.mesh.verts.extend( Vector()) #DUMMYVERT - self.object = self.header.scene.objects.new(self.mesh) - else: - self.object = self.header.scene.objects.new('Empty') - - self.object.name = name - self.header.group.objects.link(self.object) - - #id props import - self.object.properties['FLT'] = dict() - for key in self.props: - try: - self.object.properties['FLT'][key] = self.props[key] - except: #horrible... - pass - - - if self.extension: - self.object.properties['FLT']['EXT'] = dict() - for key in self.extension: - self.object.properties['FLT']['EXT'][key] = self.extension[key] - - if self.parent and self.parent.object and (self.header.scene == self.parent.header.scene): - self.parent.object.makeParent([self.object],1) - - if self.matrix: - self.object.setMatrix(self.matrix) - - if self.vis == False: - self.object.restrictDisplay = True - self.object.restrictRender = True - - else: #check for LOD children and set the proper flags - lodlist = list() - for child in self.children: - if child.props.has_key('type') and child.props['type'] == 73: - if child.props['6d!switch out'] != 0.0: - child.vis = False - #lodlist.append(child) - - #def LODmin(a,b): - # if a.props['5d!switch in'] < b.props['5d!switch in']: - # return a - # return b - - #min= None - #if len(lodlist) > 1: - # for lod in lodlist: - # lod.vis = False - # min = lodlist[0] - # for i in xrange(len(lodlist)): - # min= LODmin(min,lodlist[i]) - # min.vis = True - - - Node.blender_import(self) # Attach faces to self.faceLs - - if self.hasMesh: - # Add all my faces into the mesh at once - self.blender_import_my_faces() - - def parse_face(self): - child = Face(self, self.subfacelevel) - child.parse() - return True - - def parse_group(self): - child = Group(self) - child.parse() - return True - - def move_to_next_layer(self): - global current_layer - current_layer = current_layer << 1 - if current_layer > 0x80000: - current_layer = 1 - - def parse_lod(self): - child = LOD(self) - child.parse() - return True - - def parse_unhandled(self): - child = Unhandled(self) - child.parse() - return True - - def parse_object(self): - child = Object(self) - child.parse() - return True - - def parse_xref(self): - child = XRef(self) - child.parse() - return True - - def parse_dof(self): - child = DOF(self) - child.parse() - return True - - def parse_indexed_light_point(self): - child = IndexedLightPoint(self) - child.parse() - return True - - def parse_inline_light_point(self): - child = InlineLightPoint(self) - child.parse() - return True - - def parse_matrix(self): - m = list() - for i in xrange(4): - m.append([]) - for j in xrange(4): - f = self.header.fw.read_float() - m[i].append(f) - self.matrix = Blender.Mathutils.Matrix(m[0], m[1], m[2], m[3]) - - def parse_subpush(self): - self.parse_push() - self.subfacelevel+= 1 - return True - def parse_subpop(self): - self.parse_pop() - self.subfacelevel -= 1 - return True - - - -class Face(Node): - def __init__(self, parent,subfacelevel): - Node.__init__(self, parent, parent.header) - self.root_handler.set_handler({31: self.parse_comment, - 10: self.parse_push, - 52: self.parse_multitex}) - self.root_handler.set_throw_back_lst(throw_back_opcodes) - - self.child_handler.set_handler({72: self.parse_vertex_list, - 10: self.parse_push, - 11: self.parse_pop, - 53: self.parse_uvlist}) - - if parent: - parent.hasMesh = True - - self.subfacelevel = subfacelevel - self.indices = list() # face verts here - self.uvlayers = dict() # MultiTexture layers keyed to layer bitmask. - self.uverts = list() # Vertex aligned list of dictionaries keyed to layer bitmask. - self.uvmask = 0 # Bitfield read from MTex record - - self.comment = '' - self.props = dict() - self.props['id'] = self.header.fw.read_string(8) - # Load face. - self.props['ir color'] = self.header.fw.read_int() - self.props['priority'] = self.header.fw.read_short() - self.props['draw type'] = self.header.fw.read_char() - self.props['texture white'] = self.header.fw.read_char() - self.header.fw.read_ahead(4) # color name indices - self.header.fw.read_ahead(1) # reserved - self.props['template billboard'] = self.header.fw.read_uchar() - self.detail_tex_index = self.header.fw.read_short() - self.tex_index = self.header.fw.read_short() - self.mat_index = self.header.fw.read_short() - self.props['smc'] = self.header.fw.read_short() - self.props['fid'] = self.header.fw.read_short() - self.props['ir material'] = self.header.fw.read_int() - self.alpha = 1.0 - float(self.header.fw.read_ushort()) / 65535.0 - self.props['lod generation control'] = self.header.fw.read_uchar() - self.header.fw.read_ahead(1) # line style index - self.props['flags'] = self.header.fw.read_int() - self.props['light mode'] = self.header.fw.read_uchar() - self.header.fw.read_ahead(7) - a = self.header.fw.read_uchar() - b = self.header.fw.read_uchar() - g = self.header.fw.read_uchar() - r = self.header.fw.read_uchar() - self.packed_color = [r, g, b, a] - a = self.header.fw.read_uchar() - b = self.header.fw.read_uchar() - g = self.header.fw.read_uchar() - r = self.header.fw.read_uchar() - self.alt_packed_color = [r, g, b, a] - self.tex_map_index = self.header.fw.read_short() - self.header.fw.read_ahead(2) - self.color_index = self.header.fw.read_uint() - self.alt_color_index = self.header.fw.read_uint() - #self.header.fw.read_ahead(2) - #self.shader_index = self.header.fw.read_short() - - def parse_comment(self): - self.comment = self.header.fw.read_string(self.header.fw.get_length()-4) - return True - - def blender_import(self): - vert_count = len(self.indices) - if vert_count < 1: - if global_prefs['verbose'] >= 2: - print 'Warning: Ignoring face with no vertices.' - return - - # Assign material and image - - self.parent.faceLs.append(self) - #need to store comment in mesh prop layer! - - # Store comment info in parent. - #if self.comment != '': - # if self.parent.props['comment'] != '': - # self.parent.props['comment'] += '\n\nFrom Face:\n' + self.comment - # else: - # self.parent.props['comment'] = self.comment - - if self.uvlayers: - #Make sure that the mesh knows about the layers that this face uses - self.parent.hasmtex = True - for mask in self.uvlayers.keys(): - self.parent.uvlayers[mask] = True - - def parse_vertex_list(self): - length = self.header.fw.get_length() - fw = self.header.fw - vert_pal = self.header.vert_pal - - count = (length-4)/4 - - # If this ever fails the chunk below does error checking - self.indices= [vert_pal.index[fw.read_int()] for i in xrange(count)] - ''' - for i in xrange(count): - byte_offset = fw.read_int() - if byte_offset in vert_pal.index: - index = vert_pal.index[byte_offset] - self.indices.append(index) - elif global_prefs['verbose'] >= 1: - print 'Warning: Unable to map byte offset %s' + \ - ' to vertex index.' % byte_offset - ''' - return True - - def parse_multitex(self): - #Parse MultiTex Record. - length = self.header.fw.get_length() - fw = self.header.fw - #num layers == (length - 8) / 4 - uvmask = fw.read_uint() - mask = 2147483648 - for i in xrange(7): - if mask & uvmask: - uvlayer = dict() - self.uvlayers[mask] = uvlayer - mask = mask / 2 - - #read in record for each individual layer. - for key in reversed(sorted(self.uvlayers)): - uvlayer = self.uvlayers[key] - uvlayer['texture index'] = fw.read_ushort() - uvlayer['texture enviorment'] = fw.read_ushort() - uvlayer['texture mapping'] = fw.read_ushort() - uvlayer['texture data'] = fw.read_ushort() - - self.uvmask = uvmask - - def parse_uvlist(self): - #for each uvlayer, add uv vertices - length = self.header.fw.get_length() - fw = self.header.fw - uvmask = fw.read_uint() - if uvmask != self.uvmask: #This should never happen! - fw.read_ahead(self.length - 4) #potentially unnessecary? - else: - #need to store in uvverts dictionary for each vertex. - totverts = len(self.indices) - for i in xrange(totverts): - uvert = dict() - for key in reversed(sorted(self.uvlayers)): - uv = Vector(0.0,0.0) - uv[0] = fw.read_float() - uv[1] = fw.read_float() - uvert[key] = uv - self.uverts.append(uvert) - -class Object(InterNode): - def __init__(self, parent): - Node.__init__(self, parent, parent.header) - InterNode.__init__(self) - - self.root_handler.set_handler({33: self.parse_long_id, - 21: self.parse_push_extension, - 31: self.parse_comment, - 10: self.parse_push, - 49: self.parse_matrix}) - self.root_handler.set_throw_back_lst(throw_back_opcodes) - - self.child_handler.set_handler({5: self.parse_face, - 19: self.parse_subpush, - 20: self.parse_subpop, - 111: self.parse_inline_light_point, - 10: self.parse_push, - 11: self.parse_pop}) - self.extension_handler.set_handler({22: self.parse_pop_extension, - 100: self.parse_extension}) - - self.extension = dict() - self.props = dict() - self.props['comment'] = '' - self.parse_record() - -class Group(InterNode): - def __init__(self, parent): - Node.__init__(self, parent, parent.header) - InterNode.__init__(self) - - self.root_handler.set_handler({33: self.parse_long_id, - 31: self.parse_comment, - 10: self.parse_push, - 49: self.parse_matrix, - 21: self.parse_push_extension}) - self.root_handler.set_throw_back_lst(throw_back_opcodes) - - self.child_handler.set_handler({5: self.parse_face, - 19: self.parse_subpush, - 20: self.parse_subpop, - 111: self.parse_inline_light_point, - 2: self.parse_group, - 73: self.parse_lod, - 4: self.parse_object, - 10: self.parse_push, - 11: self.parse_pop, - 96: self.parse_unhandled, - 14: self.parse_dof, - 91: self.parse_unhandled, - 98: self.parse_unhandled, - 63: self.parse_xref}) - - self.extension_handler.set_handler({22: self.parse_pop_extension, - 100: self.parse_extension}) - - self.props = dict.fromkeys(['type', 'id', 'comment', 'priority', 'flags', 'special1', - 'special2', 'significance', 'layer code', 'loop count', - 'loop duration', 'last frame duration']) - - self.props['comment'] = '' - self.parse_record() - - #self.props['type'] = str(self.opcode) + ':' + opcode_name[self.opcode] - #props = records[self.opcode] - #propkeys = props.keys() - #propkeys.sort() - #for position in propkeys: - # (type,length,name) = props[position] - # self.props[name] = read_prop(self.header.fw,type,length) - #self.props['id'] = self.props['3t8!id'] - -class DOF(InterNode): - def blender_import(self): - InterNode.blender_import(self) - - def __init__(self, parent): - Node.__init__(self, parent, parent.header) - InterNode.__init__(self) - - self.root_handler.set_handler({33: self.parse_long_id, - 31: self.parse_comment, - 10: self.parse_push, - 49: self.parse_matrix, - 21: self.parse_push_extension}) - self.root_handler.set_throw_back_lst(throw_back_opcodes) - - self.child_handler.set_handler({#130: self.parse_indexed_light_point, - 111: self.parse_inline_light_point, - 2: self.parse_group, - 73: self.parse_lod, - 4: self.parse_object, - 10: self.parse_push, - 11: self.parse_pop, - 96: self.parse_unhandled, - 14: self.parse_dof, - 91: self.parse_unhandled, - 98: self.parse_unhandled, - 63: self.parse_xref}) - self.extension_handler.set_handler({22: self.parse_pop_extension, - 100: self.parse_extension}) - self.props = dict() - self.props['comment'] = '' - self.parse_record() - - -class XRef(InterNode): - def parse(self): - if self.xref: - self.xref.parse() - Node.parse(self) - - def __init__(self, parent): - Node.__init__(self, parent, parent.header) - InterNode.__init__(self) - - self.root_handler.set_handler({49: self.parse_matrix}) - self.root_handler.set_throw_back_lst(throw_back_opcodes) - - self.props = dict() - self.props['comment'] = '' - self.parse_record() - - xref_filename = self.props['3t200!filename'] #I dont even think there is a reason to keep this around... - - if not os.path.isabs(xref_filename): - absname = os.path.join(os.path.dirname(self.header.filename), xref_filename) - else: - absname = xref_filename - - self.props['id'] = 'X: ' + Blender.sys.splitext(Blender.sys.basename(xref_filename))[0] #this is really wrong as well.... - - if global_prefs['doxrefs'] and os.path.exists(absname) and not self.header.grr.xrefs.has_key(xref_filename): - self.xref = Database(absname, self.header.grr, self) - self.header.grr.xrefs[xref_filename] = self.xref - else: - self.xref = None - - - def blender_import(self): - #name = self.props['type'] + ': ' + self.props['id'] - name = self.props['id'] - self.object = self.header.scene.objects.new('Empty') - self.object.name = name - self.object.enableDupGroup = True - self.header.group.objects.link(self.object) - - #for broken links its ok to leave this empty! they purely for visual purposes anyway..... - try: - self.object.DupGroup = self.header.grr.xrefs[self.props['3t200!filename']].group - except: - pass - - - - - if self.parent and self.parent.object: - self.parent.object.makeParent([self.object],1) - - if self.matrix: - self.object.setMatrix(self.matrix) - - - #id props import - self.object.properties['FLT'] = dict() - for key in self.props: - try: - self.object.properties['FLT'][key] = self.props[key] - except: #horrible... - pass - - self.object.Layer = current_layer - self.object.sel = 1 - - Node.blender_import(self) - - -class LOD(InterNode): - def blender_import(self): - #self.move_to_next_layer() - InterNode.blender_import(self) - #self.object.properties['FLT'] = self.props.copy() - - def __init__(self, parent): - Node.__init__(self, parent, parent.header) - InterNode.__init__(self) - - self.root_handler.set_handler({33: self.parse_long_id, - 31: self.parse_comment, - 10: self.parse_push, - 49: self.parse_matrix, - 21: self.parse_push_extension}) - self.root_handler.set_throw_back_lst(throw_back_opcodes) - - self.child_handler.set_handler({2: self.parse_group, - 111: self.parse_inline_light_point, - 73: self.parse_lod, - 4: self.parse_object, - 10: self.parse_push, - 11: self.parse_pop, - 96: self.parse_unhandled, # switch - 14: self.parse_dof, # DOF - 91: self.parse_unhandled, # sound - 98: self.parse_unhandled, # clip - 63: self.parse_xref}) - self.extension_handler.set_handler({22: self.parse_pop_extension, - 100: self.parse_extension}) - - - self.props = dict() - self.props['comment'] = '' - self.parse_record() - -class InlineLightPoint(InterNode): - def __init__(self, parent): - Node.__init__(self, parent, parent.header) - InterNode.__init__(self) - self.root_handler.set_handler({33: self.parse_long_id, - 31: self.parse_comment, - 10: self.parse_push, - 21: self.parse_push_extension, - 49: self.parse_matrix}) - self.root_handler.set_throw_back_lst(throw_back_opcodes) - - self.child_handler.set_handler({72: self.parse_vertex_list, - 10: self.parse_push, - 11: self.parse_pop}) - self.extension_handler.set_handler({22: self.parse_pop_extension, - 100: self.parse_extension}) - - self.indices = list() - self.props = dict() - self.props['comment'] = '' - self.parse_record() - - - def blender_import(self): - - - name = self.props['id'] - self.mesh= Blender.Mesh.New() - self.mesh.name = 'FLT_LP' - self.object = self.header.scene.objects.new(self.mesh) - self.object.name = name - #self.mesh.verts.extend(Vector() ) # DUMMYVERT - self.object.Layer = current_layer - self.object.sel= 1 - - self.object.properties['FLT'] = dict() - for key in self.props: - try: - self.object.properties['FLT'][key] = self.props[key] - except: #horrible... - pass - - if self.extension: - self.object.properties['FLT']['EXT'] = dict() - for key in self.extension: - self.object.properties['FLT']['EXT'][key] = self.extension[key] - - if self.parent and self.parent.object and self.header.scene == self.parent.header.scene: - self.parent.object.makeParent([self.object]) - - if self.matrix: - self.object.setMatrix(self.matrix) - - self.mesh.verts.extend([self.header.vert_pal.blender_verts[i] for i in self.indices]) - - #add color index information. - self.mesh.verts.addPropertyLayer("FLT_VCOL",Blender.Mesh.PropertyTypes["INT"]) - for i, vindex in enumerate(self.indices): - vdesc = self.header.vert_pal.vert_desc_lst[vindex] - v = self.mesh.verts[i] - v.setProperty("FLT_VCOL",vdesc.cindex) - #for i, v in enumerate(self.mesh.verts): - # vdesc = self.header.vert_pal.vert_desc_lst[i] - # v.setProperty("FLT_VCOL",vdesc.cindex) - self.mesh.update() - - def parse_vertex_list(self): - length = self.header.fw.get_length() - fw = self.header.fw - vert_pal = self.header.vert_pal - - count = (length-4)/4 - - # If this ever fails the chunk below does error checking - self.indices= [vert_pal.index[fw.read_int()] for i in xrange(count)] - - ''' - for i in xrange(count): - byte_offset = fw.read_int() - if byte_offset in vert_pal.index: - index = vert_pal.index[byte_offset] - self.indices.append(index) - elif global_prefs['verbose'] >= 1: - print 'Warning: Unable to map byte offset %s' + \ - ' to vertex index.' % byte_offset - ''' - - return True - - - -class IndexedLightPoint(InterNode): - # return dictionary: lp_app name => index list - def group_points(self, props): - - name_to_indices = {} - - for i in self.indices: - vert_desc = self.header.vert_pal.vert_desc_lst[i] - app_desc = LightPointAppDesc() - app_desc.props.update(props) - # add vertex normal and color - app_desc.props.update({'nx': vert_desc.nx}) - app_desc.props.update({'ny': vert_desc.ny}) - app_desc.props.update({'nz': vert_desc.nz}) - - app_desc.props.update({'r': vert_desc.r}) - app_desc.props.update({'g': vert_desc.g}) - app_desc.props.update({'b': vert_desc.b}) - app_desc.props.update({'a': vert_desc.a}) - - app_name = self.header.grr.request_lightpoint_app(app_desc, self.header.scene) - - if name_to_indices.get(app_name): - name_to_indices[app_name].append(i) - else: - name_to_indices.update({app_name: [i]}) - - return name_to_indices - - def blender_import(self): - name = self.props['type'] + ': ' + self.props['id'] - - name_to_indices = self.group_points(self.header.lightpoint_appearance_pal[self.index]) - - for app_name, indices in name_to_indices.iteritems(): - self.object = Blender.Object.New('Mesh', name) - self.mesh= Blender.Mesh.New() - self.mesh.verts.extend( Vector() ) # DUMMYVERT - self.object.link(self.mesh) - - if self.parent: - self.parent.object.makeParent([self.object]) - - for i in indices: - vert = self.header.vert_pal.blender_verts[i] - self.mesh.verts.append(vert) - - self.header.scene.objects.link(self.object) - - self.object.Layer = current_layer - - if self.matrix: - self.object.setMatrix(self.matrix) - - # Import comment. - if self.props['comment'] != '': - name = 'COMMENT: ' + self.props['id'] - t = Blender.Text.New(name) - t.write(self.props['comment']) - self.props['comment'] = name - - # Attach properties. - self.props.update({'appearance': app_name}) - for name, value in self.props.iteritems(): - self.object.addProperty(name, value) - - self.mesh.update() - - def parse_vertex_list(self): - length = self.header.fw.get_length() - fw = self.header.fw - vert_pal = self.header.vert_pal - - count = (length-4)/4 - - # If this ever fails the chunk below does error checking - self.indices= [vert_pal.index[fw.read_int()] for i in xrange(count)] - - ''' - for i in xrange(count): - byte_offset = fw.read_int() - if byte_offset in vert_pal.index: - index = vert_pal.index[byte_offset] - self.indices.append(index) - elif global_prefs['verbose'] >= 1: - print 'Warning: Unable to map byte offset %s' + \ - ' to vertex index.' % byte_offset - ''' - return True - - def __init__(self, parent): - Node.__init__(self, parent, parent.header) - InterNode.__init__(self) - self.root_handler.set_handler({33: self.parse_long_id, - 31: self.parse_comment, - 10: self.parse_push, - 49: self.parse_matrix}) - self.root_handler.set_throw_back_lst(throw_back_opcodes) - - self.child_handler.set_handler({72: self.parse_vertex_list, - 10: self.parse_push, - 11: self.parse_pop}) - - self.indices = list() - - self.props = dict.fromkeys(['id', 'type', 'comment', 'draw order', 'appearance']) - self.props['comment'] = '' - self.props['type'] = 'Light Point' - self.props['id'] = self.header.fw.read_string(8) - self.index = self.header.fw.read_int() - self.header.fw.read_ahead(4) # animation index - self.props['draw order'] = self.header.fw.read_int() - -class Unhandled(InterNode): - def __init__(self, parent): - Node.__init__(self, parent, parent.header) - InterNode.__init__(self) - - self.root_handler.set_handler({33: self.parse_long_id, - 31: self.parse_comment, - 10: self.parse_push, - 49: self.parse_matrix}) - self.root_handler.set_throw_back_lst(throw_back_opcodes) - - self.child_handler.set_handler({2: self.parse_group, - 73: self.parse_lod, - 4: self.parse_object, - 10: self.parse_push, - 11: self.parse_pop, - 96: self.parse_unhandled, # switch - 14: self.parse_dof, # DOF - 91: self.parse_unhandled, # sound - 98: self.parse_unhandled, # clip - 63: self.parse_xref}) - - self.props['id'] = self.header.fw.read_string(8) - -class Database(InterNode): - def blender_import(self): - for key in self.tex_pal.keys(): - path_filename= FF.find(self.tex_pal[key][0]) - if path_filename != None: - img = self.grr.request_image(path_filename) - if img: - self.tex_pal[key][1] = img - elif global_prefs['verbose'] >= 1: - print 'Warning: Unable to find', self.tex_pal[key][0] - - self.scene.properties['FLT'] = dict() - for key in self.props: - try: - self.scene.properties['FLT'][key] = self.props[key] - except: #horrible... - pass - - self.scene.properties['FLT']['Main'] = 0 - self.scene.properties['FLT']['Filename'] = self.bname - - for child in self.children: - if child.props.has_key('type') and child.props['type'] == 73: - if child.props['6d!switch out'] != 0.0: - child.vis = False - - #import color palette - carray = list() - for color in self.col_pal: - carray.append(struct.unpack('>i',struct.pack('>BBBB',color[0],color[1],color[2],color[3]))[0]) - self.scene.properties['FLT']['Color Palette'] = carray - Node.blender_import(self) - - def parse_appearance_palette(self): - props = dict() - self.fw.read_ahead(4) # reserved - props.update({'id': self.fw.read_string(256)}) - index = self.fw.read_int() - props.update({'smc': self.fw.read_short()}) - props.update({'fid': self.fw.read_short()}) - props.update({'back color: a': self.fw.read_uchar()}) - props.update({'back color: b': self.fw.read_uchar()}) - props.update({'back color: g': self.fw.read_uchar()}) - props.update({'back color: r': self.fw.read_uchar()}) - props.update({'display mode': self.fw.read_int()}) - props.update({'intensity': self.fw.read_float()}) - props.update({'back intensity': self.fw.read_float()}) - props.update({'minimum defocus': self.fw.read_float()}) - props.update({'maximum defocus': self.fw.read_float()}) - props.update({'fading mode': self.fw.read_int()}) - props.update({'fog punch mode': self.fw.read_int()}) - props.update({'directional mode': self.fw.read_int()}) - props.update({'range mode': self.fw.read_int()}) - props.update({'min pixel size': self.fw.read_float()}) - props.update({'max pixel size': self.fw.read_float()}) - props.update({'actual size': self.fw.read_float()}) - props.update({'trans falloff pixel size': self.fw.read_float()}) - props.update({'trans falloff exponent': self.fw.read_float()}) - props.update({'trans falloff scalar': self.fw.read_float()}) - props.update({'trans falloff clamp': self.fw.read_float()}) - props.update({'fog scalar': self.fw.read_float()}) - props.update({'fog intensity': self.fw.read_float()}) - props.update({'size threshold': self.fw.read_float()}) - props.update({'directionality': self.fw.read_int()}) - props.update({'horizontal lobe angle': self.fw.read_float()}) - props.update({'vertical lobe angle': self.fw.read_float()}) - props.update({'lobe roll angle': self.fw.read_float()}) - props.update({'dir falloff exponent': self.fw.read_float()}) - props.update({'dir ambient intensity': self.fw.read_float()}) - props.update({'significance': self.fw.read_float()}) - props.update({'flags': self.fw.read_int()}) - props.update({'visibility range': self.fw.read_float()}) - props.update({'fade range ratio': self.fw.read_float()}) - props.update({'fade in duration': self.fw.read_float()}) - props.update({'fade out duration': self.fw.read_float()}) - props.update({'LOD range ratio': self.fw.read_float()}) - props.update({'LOD scale': self.fw.read_float()}) - - self.lightpoint_appearance_pal.update({index: props}) - - def parse_header(self): - self.props['type'] = 'Header' - self.props['comment'] = '' - self.props['id'] = self.fw.read_string(8) - self.props['version'] = self.fw.read_int() - self.fw.read_ahead(46) - self.props['units'] = self.fw.read_char() - self.props['set white'] = bool(self.fw.read_char()) - self.props['flags'] = self.fw.read_int() - self.fw.read_ahead(24) - self.props['projection type'] = self.fw.read_int() - self.fw.read_ahead(36) - self.props['sw x'] = self.fw.read_double() - self.props['sw y'] = self.fw.read_double() - self.props['dx'] = self.fw.read_double() - self.props['dy'] = self.fw.read_double() - self.fw.read_ahead(24) - self.props['sw lat'] = self.fw.read_double() - self.props['sw lon'] = self.fw.read_double() - self.props['ne lat'] = self.fw.read_double() - self.props['ne lon'] = self.fw.read_double() - self.props['origin lat'] = self.fw.read_double() - self.props['origin lon'] = self.fw.read_double() - self.props['lambert lat1'] = self.fw.read_double() - self.props['lambert lat2'] = self.fw.read_double() - self.fw.read_ahead(16) - self.props['ellipsoid model'] = self.fw.read_int() - self.fw.read_ahead(4) - self.props['utm zone'] = self.fw.read_short() - self.fw.read_ahead(6) - self.props['dz'] = self.fw.read_double() - self.props['radius'] = self.fw.read_double() - self.fw.read_ahead(8) - self.props['major axis'] = self.fw.read_double() - self.props['minor axis'] = self.fw.read_double() - - if global_prefs['verbose'] >= 1: - print 'OpenFlight Version:', float(self.props['version']) / 100.0 - print - - return True - - def parse_mat_palette(self): - mat_desc = MaterialDesc() - index = self.fw.read_int() - - name = self.fw.read_string(12) - if len(mat_desc.name) > 0: - mat_desc.name = name - - flag = self.fw.read_int() - # skip material if not used - if not flag & 0x80000000: - return True - - ambient_col = [self.fw.read_float(), self.fw.read_float(), self.fw.read_float()] - mat_desc.diffuse = [self.fw.read_float(), self.fw.read_float(), self.fw.read_float()] - mat_desc.specular = [self.fw.read_float(), self.fw.read_float(), self.fw.read_float()] - emissive_col = [self.fw.read_float(), self.fw.read_float(), self.fw.read_float()] - - mat_desc.shininess = self.fw.read_float() / 64.0 # [0.0, 128.0] => [0.0, 2.0] - mat_desc.alpha = self.fw.read_float() - - # Convert ambient and emissive colors into intensitities. - mat_desc.ambient = col_to_gray(ambient_col) - mat_desc.emissive = col_to_gray(emissive_col) - - self.mat_desc_pal_lst.append( (index, mat_desc) ) - - return True - - def get_color(self, color_index): - color = None - index = color_index / 128 - intensity = float(color_index - 128.0 * index) / 127.0 - - if index >= 0 and index <= 1023: - brightest = self.col_pal[index] - r = int(brightest[0] * intensity) - g = int(brightest[1] * intensity) - b = int(brightest[2] * intensity) - a = int(brightest[3]) - - color = [r, g, b, a] - - return color - - def parse_color_palette(self): - self.header.fw.read_ahead(128) - for i in xrange(1024): - a = self.header.fw.read_uchar() - b = self.header.fw.read_uchar() - g = self.header.fw.read_uchar() - r = self.header.fw.read_uchar() - self.col_pal.append((r, g, b, a)) - return True - - def parse_vertex_palette(self): - self.vert_pal = VertexPalette(self) - self.vert_pal.parse() - return True - - def parse_texture_palette(self): - name = self.fw.read_string(200) - index = self.fw.read_int() - self.tex_pal[index]= [name, None] - return True - - def read_attribute_files(self): - for tex in self.tex_pal.keys(): - [name,image] = self.tex_pal[tex] - basename = os.path.basename(name) - if(image): - basename = basename + ".attr" - dirname = os.path.dirname(Blender.sys.expandpath(image.getFilename())) #can't rely on original info stored in pallette since it might be relative link - newpath = os.path.join(dirname, basename) - if os.path.exists(newpath) and not image.properties.has_key('FLT'): - fw = flt_filewalker.FltIn(newpath) - fw.read_ahead(8) #We dont care what the attribute file says about x/y dimensions - image.properties['FLT']={} - - #need to steal code from parse records.... - props = records['Image'] - propkeys = props.keys() - propkeys.sort() - for position in propkeys: - (type,length,name) = props[position] - image.properties['FLT'][name] = read_prop(fw,type,length) - fw.close_file() - - #copy clamp settings - wrap = image.properties['FLT']['10i!Wrap'] - wrapu = image.properties['FLT']['11i!WrapU'] - wrapv = image.properties['FLT']['12i!WrapV'] - - if wrapu == 3 or wrapv == 3: - wrapuv = (wrap,wrap) - else: - wrapuv = (wrapu, wrapv) - image.clampX = wrapuv[0] - image.clampY = wrapuv[1] - - elif not os.path.exists(newpath): - print "Cannot read attribute file:" + newpath - - def __init__(self, filename, grr, parent=None): - if global_prefs['verbose'] >= 1: - print 'Parsing:', filename - print - - #check to see if filename is a relative path - #filename = os.path.abspath(filename) - - self.fw = flt_filewalker.FltIn(filename) - self.filename = filename - self.bname = os.path.splitext(os.path.basename(filename))[0] - self.grr = grr - - Node.__init__(self, parent, self) - InterNode.__init__(self) - - self.root_handler.set_handler({1: self.parse_header, - 67: self.parse_vertex_palette, - 33: self.parse_long_id, - 31: self.parse_comment, - 64: self.parse_texture_palette, - 32: self.parse_color_palette, - 113: self.parse_mat_palette, - 128: self.parse_appearance_palette, - 10: self.parse_push}) - if parent: - self.root_handler.set_throw_back_lst(throw_back_opcodes) - - self.child_handler.set_handler({#130: self.parse_indexed_light_point, - 111: self.parse_inline_light_point, - 2: self.parse_group, - 73: self.parse_lod, - 4: self.parse_object, - 10: self.parse_push, - 11: self.parse_pop, - 96: self.parse_unhandled, - 14: self.parse_dof, - 91: self.parse_unhandled, - 98: self.parse_unhandled, - 63: self.parse_xref}) - - self.scene = Blender.Scene.New(self.bname) - self.group = Blender.Group.New(self.bname) - - self.vert_pal = None - self.lightpoint_appearance_pal = dict() - self.tex_pal = dict() - #self.tex_pal_lst = list() - #self.bl_tex_pal = dict() - self.col_pal = list() - self.mat_desc_pal_lst = list() - self.mat_desc_pal = dict() - self.props = dict.fromkeys(['id', 'type', 'comment', 'version', 'units', 'set white', - 'flags', 'projection type', 'sw x', 'sw y', 'dx', 'dy', 'dz', 'sw lat', - 'sw lon', 'ne lat', 'ne lon', 'origin lat', 'origin lon', 'lambert lat1', - 'lambert lat2', 'ellipsoid model', 'utm zone', 'radius', 'major axis', 'minor axis']) - - -def clearparent(root,childhash): - for child in childhash[root]: - clearparent(child,childhash) - root.clrParent(2,0) - -def fixscale(root,childhash): - for child in childhash[root]: - fixscale(child,childhash) - location = Blender.Mathutils.Vector(root.getLocation('worldspace')) - if location[0] != 0.0 or location[1] != 0.0 or location[2] != 0.0: - #direction = Blender.Mathutils.Vector(0-location[0],0-location[1],0-location[2]) #reverse vector - smat = Blender.Mathutils.ScaleMatrix(global_prefs['scale'],4) - root.setLocation(location * smat) - #if its a mesh, we need to scale all of its vertices too - if root.type == 'Mesh': - smat = Blender.Mathutils.ScaleMatrix(global_prefs['scale'],4) - rmesh = root.getData(mesh=True) - for v in rmesh.verts: - v.co = v.co * smat - -def reparent(root,childhash,sce): - for child in childhash[root]: - reparent(child,childhash,sce) - - root.makeParent(childhash[root]) - sce.update(1) - -def update_scene(root,sdone): - for object in root.objects: - if object.DupGroup: - try: - child = Blender.Scene.Get(object.DupGroup.name) - except: - child = None - if child and child not in sdone: - update_scene(child,sdone) - root.makeCurrent() - #create a list of children for each object - childhash = dict() - for object in root.objects: - childhash[object] = list() - - for object in root.objects: - if object.parent: - childhash[object.parent].append(object) - - for object in root.objects: - if not object.parent: - #recursivley go through and clear all the children of their transformation, starting at deepest level first. - clearparent(object,childhash) - #now fix the location of everything - fixscale(object,childhash) - #now fix the parenting - reparent(object,childhash,root) - - for object in root.objects: - object.makeDisplayList() - root.update(1) - sdone.append(root) - - -def select_file(filename, grr): - if not Blender.sys.exists(filename): - msg = 'Error: File ' + filename + ' does not exist.' - Blender.Draw.PupMenu(msg) - return - - if not filename.lower().endswith('.flt'): - msg = 'Error: Not a flight file.' - Blender.Draw.PupMenu(msg) - print msg - print - return - - global_prefs['fltfile']= filename - global_prefs['verbose']= 1 - global_prefs['get_texture'] = True - global_prefs['get_diffuse'] = True - global_prefs['get_specular'] = False - global_prefs['get_emissive'] = False - global_prefs['get_alpha'] = True - global_prefs['get_ambient'] = False - global_prefs['get_shininess'] = True - global_prefs['color_from_face'] = True - global_prefs['log to blender'] = True - - - - Blender.Window.WaitCursor(True) - Blender.Window.EditMode(0) - - - FF.add_file_to_search_path(filename) - - if global_prefs['verbose'] >= 1: - print 'Pass 1: Loading.' - print - - load_time = Blender.sys.time() - db = Database(filename,grr) - db.parse() - load_time = Blender.sys.time() - load_time - - if global_prefs['verbose'] >= 1: - print - print 'Pass 2: Importing to Blender.' - print - - import_time = Blender.sys.time() - db.blender_import() - - if global_prefs['attrib']: - print "reading attribute files" - db.read_attribute_files() - - Blender.Window.ViewLayer(range(1,21)) - - update_scene(db.scene,[]) - import_time = Blender.sys.time() - import_time - if global_prefs['verbose'] >= 1: - print 'Done.' - print - print 'Time to parse file: %.3f seconds' % load_time - print 'Time to import to blender: %.3f seconds' % import_time - print 'Total time: %.3f seconds' % (load_time + import_time) - - Blender.Window.WaitCursor(False) - -def setimportscale(ID,val): - global global_prefs - global_prefs['scale'] = val -def setBpath(fname): - global_prefs['fltfile'] = fname - d = dict() - for key in global_prefs: - d[key] = global_prefs[key] - Blender.Registry.SetKey('flt_import', d, 1) - -def event(evt,val): - pass - -from Blender.BGL import * -from Blender import Draw - -def but_event(evt): - - global FLTBaseLabel - global FLTBaseString - global FLTBaseChooser - - global FLTExport - global FLTClose - - global FLTDoXRef - global FLTShadeImport - global FLTAttrib - - global FLTWarn - - #Import DB - if evt == 1: - if global_prefs['verbose'] >= 1: - print - print 'OpenFlight Importer' - print 'Version:', __version__ - print 'Author: Greg MacDonald, Campbell Barton, Geoffrey Bantle' - print __url__[2] - print - - GRR = GlobalResourceRepository() - - try: - select_file(global_prefs['fltfile'], GRR) - except: - import traceback - FLTWarn = Draw.PupBlock("Ixport Error", ["See console for output!"]) - traceback.print_exception(sys.exc_type, sys.exc_value, sys.exc_traceback) - - #choose base path for export - if evt == 4: - Blender.Window.FileSelector(setBpath, "DB Root", global_prefs['fltfile']) - #Import custom shading? - if evt == 9: - global_prefs['smoothshading'] = FLTShadeImport.val - #Import Image attribute files - if evt == 10: - global_prefs['attrib'] = FLTAttrib.val - #export XRefs - if evt == 13: - global_prefs['doxrefs'] = FLTDoXRef.val - - if evt == 2: - Draw.Exit() - - d = dict() - for key in global_prefs: - d[key] = global_prefs[key] - Blender.Registry.SetKey('flt_import', d, 1) - -def gui(): - - global FLTBaseLabel - global FLTBaseString - global FLTBaseChooser - - global FLTExport - global FLTClose - - global FLTDoXRef - global FLTShadeImport - - global FLTAttrib - - - glClearColor(0.772,0.832,0.847,1.0) - glClear(GL_COLOR_BUFFER_BIT) - - areas = Blender.Window.GetScreenInfo() - curarea = Blender.Window.GetAreaID() - curRect = None - - for area in areas: - if area['id'] == curarea: - curRect = area['vertices'] - break - - width = curRect[2] - curRect[0] - height = curRect[3] - curRect[1] - cx = 50 - cy = height - 80 - - FLTBaseLabel = Draw.Label("Base file:",cx,cy,100,20) - FLTBaseString = Draw.String("",3,cx+100,cy,300,20,global_prefs['fltfile'],255,"Root DB file") - FLTBaseChooser = Draw.PushButton("...",4,cx+400,cy,20,20,"Choose Folder") - - cy = cy-40 - FLTScale = Draw.Number("Import Scale",14,cx,cy,220,20,global_prefs['scale'],0.0,100.0,"Export scaleing factor",setimportscale) - - cy = cy-40 - FLTDoXRef = Draw.Toggle("Import XRefs", 13,cx,cy,220,20,global_prefs['doxrefs'],"Import External references") - - cy = cy-40 - FLTShadeImport = Draw.Toggle("Import Custom Shading",9,cx,cy,220,20,global_prefs['smoothshading'],"Import custom shading via edgesplit modifiers") - - cy = cy-40 - FLTAttrib = Draw.Toggle("Import Attribute Files", 10,cx,cy,220,20,global_prefs['attrib'],"Import Image Attribute files") - - cy = cy - 40 - FLTExport = Draw.PushButton("Import",1,cx,20,100,20,"Import FLT Database") - FLTClose = Draw.PushButton("Close",2,cx+120,20,100,20,"Close Window") - - - -Draw.Register(gui,event,but_event)
\ No newline at end of file diff --git a/release/scripts/flt_lodedit.py b/release/scripts/flt_lodedit.py deleted file mode 100644 index 58319b9e525..00000000000 --- a/release/scripts/flt_lodedit.py +++ /dev/null @@ -1,502 +0,0 @@ -#!BPY - -""" -Name: 'FLT LOD Editor' -Blender: 240 -Group: 'Misc' -Tooltip: 'Level of Detail Edtior for FLT nodes' -""" - -__author__ = "Geoffrey Bantle" -__version__ = "1.0 11/21/07" -__email__ = ('scripts', 'Author, ') -__url__ = ('blender', 'blenderartists.org') - -__bpydoc__ ="""\ -This script provides tools for working with OpenFlight databases in Blender. OpenFlight is a -registered trademark of MultiGen-Paradigm, Inc. - -Feature overview and more availible at: -http://wiki.blender.org/index.php/Scripts/Manual/FLTools -""" - -# -------------------------------------------------------------------------- -# flt_palettemanager.py version 0.1 2005/04/08 -# -------------------------------------------------------------------------- -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Copyright (C) 2007: Blender Foundation -# -# 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 ***** -# -------------------------------------------------------------------------- - -import Blender.Draw as Draw -from Blender.BGL import * -import Blender -import flt_properties -reload(flt_properties) -from flt_properties import * - -#event codes -evcode = { - "LOD_MAKE" : 100, - "LOD_DELETE" : 101, - "LOD_CALC_CENTER" : 102, - "LOD_GRAB_CENTER" : 103, - "LOD_X" : 104, - "LOD_Y" : 105, - "LOD_Z" : 106, - "LOD_FREEZE" : 107, - "LOD_SIG" : 108, - "LOD_IN" : 109, - "LOD_OUT" : 110, - "LOD_TRANS" : 111, - "LOD_PREVIOUS" : 112 -} - - -#system -LOD_MAKE = None #PushButton -LOD_DELETE = None #PushButton -LOD_CALC_CENTER = None #PushButton -LOD_GRAB_CENTER = None #Pushbutton -LOD_FREEZE = None #Toggle -LOD_PREVIOUS = None #Toggle - -LOD_X = None #Input -LOD_Y = None #Input -LOD_Z = None #Input - -LOD_SIG = None #Input -LOD_IN = None #Input -LOD_OUT = None #Input -LOD_TRANS = None #Input - -#labels -LOD_EDITLABEL = None -LOD_SWITCHLABEL = None -LOD_CENTERLABEL = None - -LOD_XLABEL = None -LOD_YLABEL = None -LOD_ZLABEL = None -LOD_SIGLABEL = None -LOD_INLABEL = None -LOD_OUTLABEL = None -LOD_TRANSLABEL = None - - -#ID Props -switch_in = '5d!switch in' -switch_out = '6d!switch out' -xco = '10d!X co' -yco = '11d!Y co' -zco = '12d!Z co' -trans = '13d!Transition' -sig_size = '14d!Sig Size' - -#Flags -lodflag = '9I!flags' -previous_mask = (1 << 31) -freeze_mask = (1 << 29) - -def update_state(): - state = dict() - state["activeScene"] = Blender.Scene.GetCurrent() - state["activeObject"] = state["activeScene"].objects.active - if state["activeObject"] and not state["activeObject"].sel: - state["activeObject"] = None - state["activeMesh"] = None - if state["activeObject"] and state["activeObject"].type == 'Mesh': - state["activeMesh"] = state["activeObject"].getData(mesh=True) - - state["activeFace"] = None - if state["activeMesh"]: - if state["activeMesh"].faceUV and state["activeMesh"].activeFace != None: - state["activeFace"] = state["activeMesh"].faces[state["activeMesh"].activeFace] - - - #update editmode - state["editmode"] = Blender.Window.EditMode() - - return state - -def idprops_append(object, typecode, props): - object.properties["FLT"] = dict() - object.properties["FLT"]['type'] = typecode - for prop in props: - object.properties["FLT"][prop] = props[prop] - object.properties["FLT"]['3t8!id'] = object.name - -def idprops_kill(): - state = update_state() - if state["activeObject"] and state["activeObject"].properties.has_key('FLT'): - state["activeObject"].properties.pop('FLT') - -def idprops_copy(source): - state = update_state() - if source.properties.has_key('FLT'): - for object in state["activeScene"].objects: - if object.sel and object != source and (state["activeScene"].Layers & object.Layers): - idprops_kill(object) - object.properties['FLT'] = dict() - for key in source.properties['FLT']: - object.properties['FLT'][key] = source.properties['FLT'][key] - -def select_by_typecode(typecode): - state = update_state() - - for object in state["activeScene"].objects: - if object.properties.has_key('FLT') and object.properties['FLT']['type'] == typecode and state["activeScene"].Layers & object.Layers: - object.select(1) - -def idprops_type(object, typecode): - if object.properties.has_key('FLT') and object.properties['FLT'].has_key('type') and object.properties['FLT']['type'] == typecode: - return True - return False - -#ui type code -def get_prop(typecode, prop): - - state = update_state() - if state["activeObject"] and idprops_type(state["activeObject"], typecode): - props = state["activeObject"].properties['FLT'] - else: - props = flt_properties.FLTLOD - - return props[prop] - -def set_prop(typecode, prop, value): - state = update_state() - if state["activeObject"] and idprops_type(state["activeObject"],typecode): - state["activeObject"].properties['FLT'][prop] = value - - - -def get_lockmask(mask): - global lodflag - state = update_state() - if state["activeObject"]: - flag = get_prop(73,lodflag) - if flag & mask: - return True - return False - -def set_lockmask(mask): - state = update_state() - if state["activeObject"] and idprops_type(state["activeObject"], 73): - oldvalue = state["activeObject"].properties['FLT'][lodflag] - oldvalue = struct.unpack('>I', struct.pack('>i', oldvalue))[0] - oldvalue |= mask - state["activeObject"].properties['FLT'][lodflag] = struct.unpack('>i', struct.pack(">I", oldvalue))[0] - -def clear_lockmask(mask): - state = update_state() - if state["activeObject"] and idprops_type(state["activeObject"], 73): - oldvalue = state["activeObject"].properties['FLT'][lodflag] - oldvalue = struct.unpack('>I', struct.pack('>i', oldvalue))[0] - oldvalue &= ~mask - state["activeObject"].properties['FLT'][lodflag] = struct.unpack('>i',struct.pack('>I',oldvalue))[0] - -def findchildren(object): - state = update_state() - children = list() - for candidate in state["activeScene"].objects: - if candidate.parent == object: - children.append(candidate) - retlist = list(children) - for child in children: - retlist = retlist + findchildren(child) - return retlist - -def get_object_center(object): - bbox = object.getBoundBox(1) - average = Blender.Mathutils.Vector(0.0, 0.0, 0.0) - - for point in bbox: - average[0] += point[0] - average[1] += point[1] - average[2] += point[2] - - average[0] = average[0] / 8.0 - average[1] = average[1] / 8.0 - average[2] = average[2] / 8.0 - - return average - - -def calc_center(): - - global xco - global yco - global zco - - state = update_state() - if state["activeObject"] and idprops_type(state["activeObject"], 73): - average = Blender.Mathutils.Vector(0.0, 0.0, 0.0) - children = findchildren(state["activeObject"]) #get children objects - if children: - for child in children: - center = get_object_center(child) - average[0] += center[0] - average[1] += center[1] - average[2] += center[2] - - average[0] = average[0] / len(children) - average[1] = average[1] / len(children) - average[2] = average[2] / len(children) - - set_prop(73, xco, average[0]) - set_prop(73, yco, average[1]) - set_prop(73, zco, average[2]) - - -def grab_center(): - - global xco - global yco - global zco - - state = update_state() - if state["activeObject"] and idprops_type(state["activeObject"], 73): - center = Blender.Window.GetCursorPos() - - set_prop(73, xco, center[0]) - set_prop(73, yco, center[1]) - set_prop(73, zco, center[2]) - - -def create_lod(): - state = update_state() - actobj = state["activeObject"] - if actobj and not idprops_type(actobj, 73): - idprops_kill() - idprops_append(actobj,73, flt_properties.FLTLOD) - calc_center() - - - -def event(evt,val): - if evt == Draw.ESCKEY: - Draw.Exit() - -def but_event(evt): - - global LOD_MAKE - global LOD_DELETE - global LOD_CALC_CENTER - global LOD_GRAB_CENTER - global LOD_FREEZE - global LOD_PREVIOUS - global LOD_X - global LOD_Y - global LOD_Z - global LOD_SIG - global LOD_IN - global LOD_OUT - global LOD_TRANS - - global switch_in - global switch_out - global xco - global yco - global zco - global trans - global sig_size - - global lodflag - global previous_mask - global freeze_mask - - global evcode - - #do "system" events - if evt == evcode["LOD_MAKE"]: - create_lod() - - if evt == evcode["LOD_CALC_CENTER"]: - calc_center() - - if evt == evcode["LOD_DELETE"]: - idprops_kill() - - if evt == evcode["LOD_GRAB_CENTER"]: - grab_center() - - #do mask events - if evt == evcode["LOD_FREEZE"]: - if LOD_FREEZE.val == True: - set_lockmask(freeze_mask) - else: - clear_lockmask(freeze_mask) - - if evt == evcode["LOD_PREVIOUS"]: - if LOD_PREVIOUS.val == True: - set_lockmask(previous_mask) - else: - clear_lockmask(previous_mask) - - #do input events - if evt == evcode["LOD_X"]: - set_prop(73, xco, LOD_X.val) - if evt == evcode["LOD_Y"]: - set_prop(73, yco, LOD_Y.val) - if evt == evcode["LOD_Z"]: - set_prop(73, zco, LOD_Z.val) - if evt == evcode["LOD_SIG"]: - set_prop(73, sig_size, LOD_SIG.val) - if evt == evcode["LOD_IN"]: - set_prop(73, switch_in, LOD_IN.val) - if evt == evcode["LOD_OUT"]: - set_prop(73, switch_out, LOD_OUT.val) - if evt == evcode["LOD_TRANS"]: - set_prop(73, trans, LOD_TRANS.val) - - - Draw.Redraw(1) - Blender.Window.RedrawAll() - -def draw_propsheet(x,y): - - global LOD_MAKE - global LOD_DELETE - global LOD_CALC_CENTER - global LOD_GRAB_CENTER - global LOD_FREEZE - global LOD_PREVIOUS - global LOD_X - global LOD_Y - global LOD_Z - global LOD_SIG - global LOD_IN - global LOD_OUT - global LOD_TRANS - - #labels - global LOD_EDITLABEL - global LOD_SWITCHLABEL - global LOD_CENTERLABEL - global LOD_XLABEL - global LOD_YLABEL - global LOD_ZLABEL - global LOD_SIGLABEL - global LOD_INLABEL - global LOD_OUTLABEL - global LOD_TRANSLABEL - - - global switch_in - global switch_out - global xco - global yco - global zco - global trans - global sig_size - - global lodflag - global previous_mask - global freeze_mask - - global evcode - - - global evcode - - state = update_state() - - label_width = 100 - row_height = 20 - toggle_width = 50 - input_width = 100 - pad = 10 - origx = x - origy = (row_height * 16) + (pad * 16) - - - #editor label - x = origx - y = origy - LOD_EDITLABEL = Blender.Draw.Label("FLT Level of Detail Editor", x, y, 250, row_height) - - - #Center inputs - x = origx - y = y- (row_height + pad) - LOD_CENTERLABEL = Blender.Draw.Label("LOD center", x, y, label_width, row_height) - y = y- (row_height + pad) - LOD_XLABEL = Blender.Draw.Label("X Coordinate", x, y, label_width, row_height) - x = origx + (label_width + pad) - LOD_X = Blender.Draw.Number("", evcode["LOD_X"], x, y, input_width, row_height,get_prop(73,xco), -1000000.0, 1000000.0, "") - x = origx - y = y- (row_height + pad) - LOD_YLABEL = Blender.Draw.Label("Y Coordinate", x, y, label_width, row_height) - x = origx + (label_width + pad) - LOD_Y = Blender.Draw.Number("", evcode["LOD_Y"], x, y, input_width, row_height,get_prop(73,yco), -1000000.0, 1000000.0, "") - x = origx - y = y- (row_height + pad) - LOD_ZLABEL = Blender.Draw.Label("Z Coordinate", x, y, label_width, row_height) - x = origx + (label_width + pad) - LOD_Z = Blender.Draw.Number("", evcode["LOD_Z"], x, y, input_width, row_height,get_prop(73,zco), -1000000.0, 1000000.0, "") - - - #Switch inputs - x = origx - y = y- (row_height + pad) - LOD_SWITCHLABEL = Blender.Draw.Label("Switch Settings", x, y, input_width, row_height) - y = y- (row_height + pad) - LOD_SIGLABEL = Blender.Draw.Label("Significant Size", x, y, label_width, row_height) - x = origx + (label_width + pad) - LOD_SIG = Blender.Draw.Number("", evcode["LOD_SIG"], x, y, input_width, row_height, get_prop(73,sig_size), -1000000.0, 1000000.0, "") - x = origx - y = y- (row_height + pad) - LOD_INLABEL = Blender.Draw.Label("Switch In", x, y, label_width, row_height) - x = origx + (label_width + pad) - LOD_IN = Blender.Draw.Number("", evcode["LOD_IN"], x, y, input_width, row_height, get_prop(73,switch_in), -1000000.0, 1000000.0, "") - x = origx - y = y- (row_height + pad) - LOD_OUTLABEL = Blender.Draw.Label("Switch Out", x, y, label_width, row_height) - x = origx + (label_width + pad) - LOD_OUT = Blender.Draw.Number("", evcode["LOD_OUT"], x, y, input_width, row_height, get_prop(73,switch_out), -1000000.0, 1000000.0, "") - x = origx - y = y- (row_height + pad) - LOD_TRANSLABEL = Blender.Draw.Label("Transition", x, y, label_width, row_height) - x = origx + (label_width + pad) - LOD_TRANS = Blender.Draw.Number("", evcode["LOD_TRANS"], x, y, input_width, row_height, get_prop(73,trans), -1000000.0, 1000000.0, "") - - - x = origx - y = y - (row_height + pad) - LOD_MAKE = Blender.Draw.PushButton("Make LOD", evcode["LOD_MAKE"], x, y, input_width + label_width + pad, row_height, "Make a LOD Node out of Active Object") - y = y - (row_height + pad) - LOD_DELETE = Blender.Draw.PushButton("Delete LOD", evcode["LOD_DELETE"], x, y, input_width + label_width + pad, row_height, "Delete the LOD Node properties") - y = y - (row_height + pad) - LOD_CALC_CENTER = Blender.Draw.PushButton("Calculate Center", evcode["LOD_CALC_CENTER"], x, y, input_width + label_width + pad, row_height, "Calculate the center of this LOD") - y = y - (row_height + pad) - LOD_GRAB_CENTER = Blender.Draw.PushButton("Grab Center", evcode["LOD_GRAB_CENTER"], x, y, input_width + label_width + pad, row_height, "Grab center from 3d cursor") - y = y - (row_height + pad) - LOD_FREEZE = Blender.Draw.Toggle("Freeze Center", evcode["LOD_FREEZE"], x, y, input_width + label_width + pad, row_height, get_lockmask(freeze_mask), "") - y = y - (row_height + pad) - LOD_PREVIOUS = Blender.Draw.Toggle("Previous Range", evcode["LOD_PREVIOUS"], x, y, input_width + label_width + pad, row_height, get_lockmask(previous_mask), "") - -def gui(): - #draw the propsheet/toolbox. - psheety = 800 - #psheetx = psheety + 10 - draw_propsheet(20,psheety) - -Draw.Register(gui,event,but_event) -
\ No newline at end of file diff --git a/release/scripts/flt_palettemanager.py b/release/scripts/flt_palettemanager.py deleted file mode 100644 index c2f1380a6fa..00000000000 --- a/release/scripts/flt_palettemanager.py +++ /dev/null @@ -1,505 +0,0 @@ -#!BPY - -""" -Name: 'FLT Palette Manager' -Blender: 240 -Group: 'Misc' -Tooltip: 'Manage FLT colors' -""" - -__author__ = "Geoffrey Bantle" -__version__ = "1.0 11/21/2007" -__email__ = ('scripts', 'Author, ') -__url__ = ('blender', 'blenderartists.org') - -__bpydoc__ ="""\ - -This script manages colors in OpenFlight databases. OpenFlight is a -registered trademark of MultiGen-Paradigm, Inc. - -Todo: --Figure out whats causing the PC speaker to beep when initializing... - -Feature overview and more availible at: -http://wiki.blender.org/index.php/Scripts/Manual/FLTools -""" - -# -------------------------------------------------------------------------- -# flt_palettemanager.py version 1.0 2005/04/08 -# -------------------------------------------------------------------------- -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Copyright (C) 2007: Blender Foundation -# -# 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 ***** -# -------------------------------------------------------------------------- - -import Blender.Draw as Draw -from Blender.BGL import * -import Blender -import flt_properties -import flt_defaultp as defaultp -from flt_properties import * - -def RGBtoHSV( r, g, b): - minc = min( r, g, b ) - maxc = max( r, g, b ) - v = maxc - - delta = maxc - minc - - if( max != 0 ): - s = delta / maxc - else: - s = 0 - h = -1 - return (h,s,v) - - if( r == maxc ): - h = ( g - b ) / delta - elif( g == maxc ): - h = 2 + ( b - r ) / delta - else: - h = 4 + ( r - g ) / delta - - h *= 60 - if( h < 0 ): - h += 360 - - return(h,s,v) - -def HSVtoRGB(h,s,v): - - if( s == 0 ): - return (v,v,v) - - - h /= 60 - i = math.floor( h) - f = h - i - p = v * ( 1 - s ) - q = v * ( 1 - s * f ) - t = v * ( 1 - s * ( 1 - f ) ) - - if i == 0: - r = v - g = t - b = p - elif i == 1: - r = q - g = v - b = p - - elif i== 2: - r = p - g = v - b = t - elif i==3: - r = p - g = q - b = v - elif i==4: - r = t - g = p - b = v - - else: - r = v - g = p - b = q - - return(r,g,b) - - -palette_size = 12 -palette_x = 0 -palette_y = 0 - -colors = list() -curint = 1.0 -curswatch = 0 -#make a default palette, not very useful. -cinc = 1.0 / 1024.0 -cstep = 0.0 -picker = None -ptt = "" - - -ts1=None -ts2=None -ts3=None -ts4=None -ts5=None - -for i in xrange(1024): - colors.append([cstep,cstep,cstep]) - cstep = cstep + cinc -def update_state(): - state = dict() - state["activeScene"] = Blender.Scene.getCurrent() - state["activeObject"] = state["activeScene"].getActiveObject() - state["activeMesh"] = None - if state["activeObject"] and state["activeObject"].type == 'Mesh': - state["activeMesh"] = state["activeObject"].getData(mesh=True) - - state["activeFace"] = None - if state["activeMesh"]: - if state["activeMesh"].faceUV and state["activeMesh"].activeFace != None: - state["activeFace"] = state["activeMesh"].faces[state["activeMesh"].activeFace] - - return state - -def pack_face_index(index, intensity): - return ((127*intensity)+(128*index)) -def unpack_face_index(face_index): - index = face_index / 128 - intensity = float(face_index - 128.0 * index) / 127.0 - return(index,intensity) - -def event(evt,val): - global palette_size - global palette_x - global palette_y - global colors - global curint - global curswatch - - areas = Blender.Window.GetScreenInfo() - curarea = Blender.Window.GetAreaID() - curRect = None - editmode = 0 - - for area in areas: - if area['id'] == curarea: - curRect = area['vertices'] - break - - if evt == Draw.LEFTMOUSE: - mval = Blender.Window.GetMouseCoords() - rastx = mval[0] - curRect[0] - rasty = mval[1] - curRect[1] - - swatchx = (rastx -palette_x) / palette_size #+state["palette_x"] - swatchy = (rasty -palette_y) / palette_size #+state["palette_y"] - if rastx > palette_x and rastx < (palette_x + palette_size * 32) and rasty > palette_y and rasty < (palette_y+ palette_size* 32): - if swatchx < 32 and swatchy < 32: - curswatch = (swatchx * 32) + swatchy - Draw.Redraw(1) - - elif swatchy < 34 and swatchx < 32: - curint = 1.0 - (float(rastx-palette_x)/(palette_size*32.0)) - Draw.Redraw(1) - - #copy current color and intensity to selected faces. - elif evt == Draw.VKEY: - - if Blender.Window.EditMode(): - Blender.Window.EditMode(0) - editmode = 1 - state = update_state() - - #retrieve color from palette - color = struct.unpack('>BBBB',struct.pack('>i',colors[curswatch])) - actmesh = state["activeMesh"] - if actmesh: - if(Blender.Window.GetKeyQualifiers() != Blender.Window.Qual["CTRL"]): - selfaces = list() - for face in actmesh.faces: - if face.sel: - selfaces.append(face) - - if not "FLT_COL" in actmesh.faces.properties: - actmesh.faces.addPropertyLayer("FLT_COL",Blender.Mesh.PropertyTypes["INT"]) - for face in actmesh.faces: - face.setProperty("FLT_COL",127) #default - try: - actmesh.activeColorLayer = "FLT_Fcol" - except: - actmesh.addColorLayer("FLT_Fcol") - actmesh.activeColorLayer = "FLT_Fcol" - - - for face in selfaces: - #First append packed index + color and store in face property - face.setProperty("FLT_COL",int(pack_face_index(curswatch,curint))) - #Save baked color to face vertex colors - for col in face.col: - col.r = int(color[0] * curint) - col.g = int(color[1] * curint) - col.b = int(color[2] * curint) - col.a = int(color[3] * curint) - else: - if Blender.Mesh.Mode() == Blender.Mesh.SelectModes['VERTEX']: - if not 'FLT_VCOL' in actmesh.verts.properties: - actmesh.verts.addPropertyLayer("FLT_VCOL",Blender.Mesh.PropertyTypes["INT"]) - for vert in actmesh.verts: - vert.setProperty("FLT_VCOL",127) - else: - for vert in actmesh.verts: - if vert.sel: - vert.setProperty("FLT_VCOL",int(pack_face_index(curswatch,curint))) - - if editmode: - Blender.Window.EditMode(1) - - Blender.Window.RedrawAll() - - #grab color and intensity from active face - elif evt == Draw.CKEY: - if Blender.Window.EditMode(): - Blender.Window.EditMode(0) - editmode = 1 - state = update_state() - - actmesh = state["activeMesh"] - activeFace = state["activeFace"] - - - if activeFace: - if not "FLT_COL" in actmesh.faces.properties: - actmesh.faces.addPropertyLayer("FLT_COL",Blender.Mesh.PropertyTypes["INT"]) - for face in actmesh.faces: - face.setProperty("FLT_COL",127) #default - try: - actmesh.activeColorLayer = "FLT_Fcol" - except: - actmesh.addColorLayer("FLT_Fcol") - actmesh.activeColorLayer = "FLT_Fcol" - tcol = activeFace.getProperty("FLT_COL") - (index,intensity) = unpack_face_index(tcol) - curswatch = index - curint = intensity - - if editmode: - Blender.Window.EditMode(1) - - Blender.Window.RedrawAll() - - elif evt == Draw.GKEY: - if Blender.Window.EditMode(): - Blender.Window.EditMode(0) - editmode =1 - state = update_state() - - actmesh = state["activeMesh"] - activeFace = state["activeFace"] - - if activeFace and "FLT_COL" in actmesh.faces.properties: - (index,intensity) = unpack_face_index(activeFace.getProperty("FLT_COL")) - for face in actmesh.faces: - (index2, intensity2) = unpack_face_index(face.getProperty("FLT_COL")) - if index == index2: - face.sel = 1 - - - elif evt == Draw.ESCKEY: - Draw.Exit() - - if editmode: - Blender.Window.EditMode(1) - -def update_all(): - global colors - state = update_state() - #update the baked FLT colors for all meshes. - for object in state["activeScene"].objects: - if object.type == "Mesh": - mesh = object.getData(mesh=True) - if 'FLT_COL' in mesh.faces.properties and "FLT_Fcol" in mesh.getColorLayerNames(): - mesh.activeColorLayer = "FLT_Fcol" - for face in mesh.faces: - (index,intensity) = unpack_face_index(face.getProperty('FLT_COL')) - color = struct.unpack('>BBBB',struct.pack('>i',colors[index])) - #update the vertex colors for this face - for col in face.col: - col.r = int(color[0] * intensity) - col.g = int(color[1] * intensity) - col.b = int(color[2] * intensity) - col.a = 255 - - -def but_event(evt): - global palette_size - global palette_x - global palette_y - global colors - global curint - global curswatch - global picker - state = update_state() - - if evt == 1: - if picker.val: - rval = (int(picker.val[0]*255),int(picker.val[1]*255),int(picker.val[2]*255),255) - rval = struct.pack('>BBBB',rval[0],rval[1],rval[2],rval[3]) - rval = struct.unpack('>i',rval) - colors[curswatch] = rval[0] - #go cd through all meshes and update their FLT colors - update_all() - - Draw.Redraw(1) -def init_pal(): - global palette_size - global palette_x - global palette_y - global colors - global curint - global curswatch - - state = update_state() - - if not state["activeScene"].properties.has_key('FLT'): - state["activeScene"].properties['FLT'] = dict() - - try: - colors = state["activeScene"].properties['FLT']['Color Palette'] - except: - state["activeScene"].properties['FLT']['Color Palette'] = defaultp.pal - colors = state["activeScene"].properties['FLT']['Color Palette'] - -def draw_palette(): - global palette_size - global palette_x - global palette_y - global colors - global curint - global curswatch - global picker - global ts1 - global ts2 - global ts3 - global ts4 - global ts5 - - state = update_state() - init_pal() - - ssize = palette_size - xpos = palette_x - cid = 0 - - highlight = [(palette_x,palette_y),(palette_x+palette_size,palette_y),(palette_x+palette_size,palette_y+palette_size),(palette_x,palette_y+palette_size)] - for x in xrange(32): - ypos = palette_y - for y in xrange(32): - color = struct.unpack('>BBBB',struct.pack('>i',colors[cid])) - glColor3f(color[0]/255.0,color[1]/255.0,color[2]/255.0) - glBegin(GL_POLYGON) - glVertex2i(xpos,ypos) - glVertex2i(xpos+ssize,ypos) - glVertex2i(xpos+ssize,ypos+ssize) - glVertex2i(xpos,ypos+ssize) - glEnd() - - if curswatch == cid: - highlight[0] = (xpos,ypos) - highlight[1] = (xpos+ssize,ypos) - highlight[2] = (xpos+ssize,ypos+ssize) - highlight[3] = (xpos,ypos+ssize) - - glColor3f(0.0,0.0,0.0) - glBegin(GL_LINE_LOOP) - glVertex2i(xpos,ypos) - glVertex2i(xpos+ssize,ypos) - glVertex2i(xpos+ssize,ypos+ssize) - glVertex2i(xpos,ypos+ssize) - glVertex2i(xpos,ypos) - glEnd() - - - cid = cid + 1 - ypos = ypos + ssize - - xpos = xpos + ssize - - #draw intensity gradient - color = struct.unpack('>BBBB',struct.pack('>i',colors[curswatch])) - color = [color[0]/255.0,color[1]/255.0,color[2]/255.0] - colsteps = [color[0]/255.0,color[1]/255.0,color[2]/255.0] - stripwidth = (palette_size * 32.0) / 256 - strippad = palette_size / 2.0 - - xpos = palette_x - grady = (palette_y + (palette_size * 32.0)) + strippad - for x in xrange(256): - color[0] = color[0] - colsteps[0] - color[1] = color[1] - colsteps[1] - color[2] = color[2] - colsteps[2] - - glColor3f(color[0], color[1] ,color[2]) - glBegin(GL_POLYGON) - glVertex2f(xpos,grady) - glVertex2f(xpos+stripwidth,grady) - glVertex2f(xpos+stripwidth,grady+palette_size) - glVertex2f(xpos,grady+palette_size) - glEnd() - xpos = xpos + stripwidth - - #draw intensity slider bar - #xposition == 512 - ((curint) * 512) - xpos = ((palette_size*32) * (1.0 - curint)) + palette_x - glColor3f(1.0,1.0,1.0) - glBegin(GL_LINE_LOOP) - glVertex2i(int(xpos-6),int(grady-1)) - glVertex2i(int(xpos+6),int(grady-1)) - glVertex2i(int(xpos+6),int(grady+palette_size+1)) - glVertex2i(int(xpos-6),int(grady+palette_size+1)) - #glVertex2i(xpos-6,grady+7) - glEnd() - - #draw color picker - color = struct.unpack('>BBBB',struct.pack('>i',colors[curswatch])) - pickcol = (color[0]/255.0,color[1]/255.0,color[2]/255.0) - picker = Blender.Draw.ColorPicker(1,highlight[0][0]+1,highlight[0][1]+1,ssize-2,ssize-2,pickcol,ptt) - - #draw highlight swatch - glColor3f(1.0,1.0,1.0) - glBegin(GL_LINE_LOOP) - glVertex2i(highlight[0][0],highlight[0][1]) - glVertex2i(highlight[1][0],highlight[1][1]) - glVertex2i(highlight[2][0],highlight[2][1]) - glVertex2i(highlight[3][0],highlight[3][1]) - glVertex2i(highlight[0][0],highlight[0][1]) - glEnd() - - #draw text string explanations - xpos = palette_size*32+20 - ypos = palette_size*32+10 - glRasterPos2d(xpos,ypos) - ts1 = Blender.Draw.Text("FLT Palette Manager V 1.0") - ypos = ypos - 20 - glRasterPos2d(xpos,ypos) - ts3 = Blender.Draw.Text("CKEY - Copy Active Face Color*") - ypos = ypos - 20 - glRasterPos2d(xpos,ypos) - ts2 = Blender.Draw.Text("VKEY - Paste Color to Selected Faces") - ypos = ypos - 20 - glRasterPos2d(xpos,ypos) - ts4 = Blender.Draw.Text("GKEY - Select Faces With Same Color") - ypos = ypos - 15 - glRasterPos2d(xpos,ypos) - ts5 = Blender.Draw.Text("(*Requires mesh with UV coordinates)", 'small') - -def gui(): - glClearColor(0.5,0.5,0.5,1.0) - glClear(GL_COLOR_BUFFER_BIT) - draw_palette() - - -init_pal() -Draw.Register(gui,event,but_event) -
\ No newline at end of file diff --git a/release/scripts/flt_properties.py b/release/scripts/flt_properties.py deleted file mode 100644 index b9d93b5f52d..00000000000 --- a/release/scripts/flt_properties.py +++ /dev/null @@ -1,630 +0,0 @@ -# flt_properties.py. For setting default OpenFLight ID property types -# Copyright (C) 2007 Blender Foundation -# -# 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. - -__bpydoc__ ="""\ -Utility functions and data defintions used by OpenFlight I/O and tool scripts. OpenFlight is a -registered trademark of MultiGen-Paradigm, Inc. -""" - - -import struct - -bitsLSB = [2147483648] -for i in xrange(31): - bitsLSB.append(bitsLSB[-1]/2) -bitsRSB = bitsLSB[:] -bitsRSB.reverse() - -def pack_color(col): - return struct.pack('>B',col[3]) + struct.pack('>B',col[2]) + struct.pack('>B',col[1]) + struct.pack('>B',col[0]) - -def unpack_color(col): - string = struct.pack('>I', col) - r = struct.unpack('>B',string[3:4]) - g = struct.unpack('>B',string[2:3]) - b = struct.unpack('>B',string[1:2]) - a = struct.unpack('>B',string[0:1]) - return [r,g,b,a] - -def reverse_bits(len,num): - bitbucket = list() - rval = 0 - - for i in xrange(len): - if num & bitsRSB[i]: - bitbucket.append(1) - else: - bitbucket.append(0) - - bitbucket.reverse() - - for i, bit in enumerate(bitbucket): - if bit: - rval |= bitsLSB[i] - - return rval - - -opcode_name = { 0: 'db', - 1: 'head', - 2: 'grp', - 4: 'obj', - 5: 'face', - 10: 'push', - 11: 'pop', - 14: 'dof', - 19: 'push sub', - 20: 'pop sub', - 21: 'push ext', - 22: 'pop ext', - 23: 'cont', - 31: 'comment', - 32: 'color pal', - 33: 'long id', - 49: 'matrix', - 50: 'vector', - 52: 'multi-tex', - 53: 'uv lst', - 55: 'bsp', - 60: 'rep', - 61: 'inst ref', - 62: 'inst def', - 63: 'ext ref', - 64: 'tex pal', - 67: 'vert pal', - 68: 'vert w col', - 69: 'vert w col & norm', - 70: 'vert w col, norm & uv', - 71: 'vert w col & uv', - 72: 'vert lst', - 73: 'lod', - 74: 'bndin box', - 76: 'rot edge', - 78: 'trans', - 79: 'scl', - 80: 'rot pnt', - 81: 'rot and/or scale pnt', - 82: 'put', - 83: 'eyepoint & trackplane pal', - 84: 'mesh', - 85: 'local vert pool', - 86: 'mesh prim', - 87: 'road seg', - 88: 'road zone', - 89: 'morph vert lst', - 90: 'link pal', - 91: 'snd', - 92: 'rd path', - 93: 'snd pal', - 94: 'gen matrix', - 95: 'txt', - 96: 'sw', - 97: 'line styl pal', - 98: 'clip reg', - 100: 'ext', - 101: 'light src', - 102: 'light src pal', - 103: 'reserved', - 104: 'reserved', - 105: 'bndin sph', - 106: 'bndin cyl', - 107: 'bndin hull', - 108: 'bndin vol cntr', - 109: 'bndin vol orient', - 110: 'rsrvd', - 111: 'light pnt', - 112: 'tex map pal', - 113: 'mat pal', - 114: 'name tab', - 115: 'cat', - 116: 'cat dat', - 117: 'rsrvd', - 118: 'rsrvd', - 119: 'bounding hist', - 120: 'rsrvd', - 121: 'rsrvd', - 122: 'push attrib', - 123: 'pop attrib', - 124: 'rsrvd', - 125: 'rsrvd', - 126: 'curv', - 127: 'road const', - 128: 'light pnt appear pal', - 129: 'light pnt anim pal', - 130: 'indexed lp', - 131: 'lp sys', - 132: 'indx str', - 133: 'shdr pal'} - - -typecodes = ['c','C','s','S','i','I','f','d','t'] - -FLT_GRP = 2 -FLT_OBJ = 4 -FLT_LOD = 73 -FLT_XRF = 63 -FLT_DOF = 14 -FLT_ILP = 111 -FLT_DB = 1 -FLT_FCE = 5 - -#not actual opcodes -FLT_NUL = 0 -FLT_EXP = -1 - -#valid childtypes for each FLT node type -FLT_CHILDTYPES = { - FLT_GRP : [111,2,73,4,14,63], - FLT_OBJ : [111], - FLT_LOD : [111,2,73,4,14,63], - FLT_XRF : [], - FLT_DOF : [111,2,73,4,14,63], - FLT_ILP : [] -} - -#List of nodes that can have faces as children -FLT_FACETYPES = [ - FLT_GRP, - FLT_OBJ, - FLT_LOD, - FLT_DOF -] - -def write_prop(fw,type,value,length): - if type == 'c': - fw.write_char(value) - elif type == 'C': - fw.write_uchar(value) - elif type == 's': - fw.write_short(value) - elif type == 'S': - fw.write_ushort(value) - elif type == 'i': - fw.write_int(value) - elif type == 'I': - #NOTE!: - #there is no unsigned int type in python, but we can only store signed ints in ID props - newvalue = struct.unpack('>I', struct.pack('>i', value))[0] - fw.write_uint(newvalue) - elif type == 'd': - fw.write_double(value) - elif type == 'f': - fw.write_float(value) - elif type == 't': - fw.write_string(value,length) - -def read_prop(fw,type,length): - rval = None - if type == 'c': - rval = fw.read_char() - elif type == 'C': - rval = fw.read_uchar() - elif type == 's': - rval = fw.read_short() - elif type == 'S': - rval = fw.read_ushort() - elif type == 'i': - rval = fw.read_int() - elif type == 'I': - rval = fw.read_uint() - elif type == 'd': - rval = fw.read_double() - elif type == 'f': - rval = fw.read_float() - elif type == 't': - rval = fw.read_string(length) - return rval - - -FLTExt = { - '3t8!id' : 'Ext', - '4t8!sid' : '', - '5c!reserved': 0, - '6c!revision' : 0, - '7S!recordcode' : 0 -} -FLTGroup = { - '3t8!id' : 'G', - '4s!priority' : 0, - '5s!reserved1' : 0, - '6i!flags' : 0, - '7s!special1' : 0, - '8s!special2' : 0, - '9s!significance' : 0, - '10c!layer code' : 0, - '11c!reserved2' : 0, - '12i!reserved3' : 0, - '13i!loop count' : 0, - '14f!loop duration' : 0, - '15f!last frame duration' : 0 -} -FLTGroupDisplay = [5,11,12] - -FLTObject = { - '3t8!id' : 'O', - '4I!flags' : 0, - '5s!priority' : 0, - '6S!transp' : 0, - '7s!SFX1' : 0, - '8s!SFX2' : 0, - '9s!significance' : 0, - '10s!reserved' : 0 -} -FLTObjectDisplay = [10] - -FLTLOD = { - '3t8!id' : 'L', - '4i!reserved' : 0, - '5d!switch in' : 0.0, - '6d!switch out' : 0.0, - '7s!sfx ID1' : 0, - '8s!sfx ID2' : 0, - '9I!flags' : 0, - '10d!X co' : 0.0, - '11d!Y co' : 0.0, - '12d!Z co' : 0.0, - '13d!Transition' : 0.0, - '14d!Sig Size' : 0.0 -} -FLTLODDisplay = [4] - -FLTInlineLP = { - '3t8!id' : 'Lp', - '4s!smc' : 0, - '5s!fid' : 0, - '6C!back color: a' : 255, - '7C!back color: b' : 255, - '8C!back color: g' : 255, - '9C!back color: r' : 255, - '10i!display mode' : 0, - '11f!intensity' : 1.0, - '12f!back intensity' : 0.0, - '13f!minimum defocus' : 0.0, - '14f!maximum defocus' : 1.0, - '15i!fading mode' : 0, - '16i!fog punch mode' : 0, - '17i!directional mode' : 1, - '18i!range mode' : 0, - '19f!min pixel size' : 1.0, - '20f!max pixel size' : 1024, - '21f!actual size' : 0.25, - '22f!trans falloff pixel size' : 0.25, - '23f!trans falloff exponent' : 1.0, - '24f!trans falloff scalar' : 1.0, - '25f!trans falloff clamp' : 1.0, - '26f!fog scalar' : 0.25, - '27f!fog intensity' : 1.0, - '28f!size threshold' : 0.1, - '29i!directionality' : 0, - '30f!horizontal lobe angle' : 180.0, - '31f!vertical lobe angle' : 180.0, - '32f!lobe roll angle' : 0.0, - '33f!dir falloff exponent' : 1.0, - '34f!dir ambient intensity' : 0.1, - '35f!anim period' : 2, - '36f!anim phase' : 0, - '37f!anim enabled' : 1.0, - '38f!significance' : 0.0, - '39i!draw order' : 0, - '40I!flags' : 277004288, - '41f!roti' : 0, - '42f!rotj' : 0, - '43f!rotk' : 1.0 -} - -FLTInlineLPDisplay = [35,36,37,41,42,43] - -FLTXRef = { - '3t200!filename' : '', #we dont actually use this value on export - '4i!reserved' : 0, - '5I!flag' : -478150656, - '6s!bbox' : 0, - '7s!reserved' : 0 -} - -FLTXRefDisplay = [4,7,3] - -FLTDOF = { - '3t8!id' : 'D', - '4i!reserved' : 0, - '5d!ORIGX' : 0.0, - '6d!ORIGY' : 0.0, - '7d!ORIGZ' : 0.0, - '8d!XAXIS-X' : 10.0, - '9d!XAXIS-Y' : 0.0, - '10d!XAXIS-Z' : 0.0, - '11d!XYPLANE-X' : 0.0, - '12d!XYPLANE-Y' : 10.0, - '13d!XZPLANE-Z' : 0.0, - '14d!ZMIN' : 0.0, - '15d!ZMAX' : 0.0, - '16d!ZCUR' : 0.0, - '17d!ZSTEP' : 0.0, - '18d!YMIN' : 0.0, - '19d!YMAX' : 0.0, - '20d!YCUR' : 0.0, - '21d!YSTEP' : 0.0, - '22d!XMIN' : 0.0, - '23d!XMAX' : 0.0, - '24d!XCUR' : 0.0, - '25d!XSTEP' : 0.0, - '26d!PITCH-MIN' : 0.0, - '27d!PITCH-MAX' : 0.0, - '28d!PITCH-CUR' : 0.0, - '29d!PITCH-STEP' : 0.0, - '30d!ROLL-MIN' : 0.0, - '31d!ROLL-MAX' : 0.0, - '32d!ROLL-CUR' : 0.0, - '33d!ROLL-STEP' : 0.0, - '34d!YAW-MIN' : 0.0, - '35d!YAW-MAX' : 0.0, - '36d!YAW-CUR' : 0.0, - '37d!YAW-STEP' : 0.0, - '38d!ZSIZE-MIN' : 0.0, - '39d!ZSIZE-MAX' : 0.0, - '40d!ZSIZE-CUR' : 1.0, - '41d!ZSIZE-STEP' : 0.0, - '42d!YSIZE-MIN' : 0.0, - '43d!YSIZE-MAX' : 0.0, - '44d!YSIZE-CUR' : 1.0, - '45d!YSIZE-STEP' : 0.0, - '46d!XSIZE-MIN' : 0.0, - '47d!XSIZE-MAX' : 0.0, - '48d!XSIZE-CUR' : 1.0, - '49d!XSIZE-STEP' : 0.0, - '50I!FLAG' : 1897582, - '51i!reserved2' : 0 -} - -FLTDOFDisplay = [4] - -FLTImage = { - '3i!RealU Direction' : 0, - '4i!RealV Direction' : 0, - '5i!UpX' : 0, - '6i!UpY' : 0, - '7i!File Format' : 0, - '8i!Min Filter' : 6, - '9i!Mag Filter' : 1, - '10i!Wrap' : 0, - '11i!WrapU' : 0, - '12i!WrapV' : 0, - '13i!Modified' : 0, - '14i!PivotX' : 0, - '15i!PivotY' : 0, - '16i!Enviorment' : 0, - '17i!WhiteAlpha' : 0, - '18i!reserved1' : 0, - '19i!reserved2' : 0, - '20i!reserved3' : 0, - '21i!reserved4' : 0, - '22i!reserved5' : 0, - '23i!reserved6' : 0, - '24i!reserved7' : 0, - '25i!reserved8' : 0, - '26i!reserved9' : 0, - '27d!RealU Direction' : 0, - '28d!RealV Direction' : 0, - '29i!Origin' : 0, - '30i!Kernel no.' : 0, - '31i!Internal Format' : 0, - '32i!External Format' : 0, - '33i!MipMap Filter?' : 0, - '34f!MMF1' : 0.0, - '35f!MMF2' : 0.0, - '36f!MMF3' : 0.0, - '37f!MMF4' : 0.0, - '38f!MMF5' : 0.0, - '39f!MMF6' : 0.0, - '40f!MMF7' : 0.0, - '41f!MMF8' : 0.0, - '42i!Tex CPs?' : 0, - '43f!LOD0 CP' : 0.0, - '44f!Scale0 CP' : 0.0, - '45f!LOD1 CP' : 0.0, - '46f!Scale1 CP' : 0.0, - '47f!LOD2 CP' : 0.0, - '48f!Scale2 CP' : 0.0, - '49f!LOD3 CP' : 0.0, - '50f!Scale3 CP' : 0.0, - '51f!LOD4 CP' : 0.0, - '52f!Scale4 CP' : 0.0, - '53f!LOD5 CP' : 0.0, - '54f!Scale5 CP' : 0.0, - '55f!LOD6 CP' : 0.0, - '56f!Scale6 CP' : 0.0, - '57f!LOD7 CP' : 0.0, - '58f!Scale7 CP' : 0.0, - '59f!Control Clamp' : 0.0, - '60i!Mag Alpha Filter' : 0, - '61i!Mag Color Filter' : 0, - '62f!reserved10' : 0, - '63f!reserved11' : 0, - '64f!reserved12' : 0, - '65f!reserved13' : 0, - '66f!reserved14' : 0, - '67f!reserved15' : 0, - '68f!reserved16' : 0, - '69f!reserved17' : 0, - '70f!reserved18' : 0, - '71d!Lambert Central' : 0.0, - '72d!Lambert Upper' : 0.0, - '73d!Lambert Lower' : 0.0, - '74d!reserved19' : 0, - '75f!reserved20' : 0, - '76f!reserved21' : 0, - '77f!reserved22' : 0, - '78f!reserved23' : 0, - '79f!reserved24' : 0, - '80i!Tex Detail?' : 0, - '81i!Tex J' : 0, - '82i!Tex K' : 0, - '83i!Tex M' : 0, - '84i!Tex N' : 0, - '85i!Tex Scramble' : 0, - '86i!Tex Tile?' : 0, - '87f!Tex Tile LLU' : 0.0, - '88f!Tex Tile LLV' : 0.0, - '89f!Tex Tile URU' : 0.0, - '90f!Tex Tile URV' : 0.0, - '91i!Projection' : 0, - '92i!Earth Model' : 0, - '93i!reserved25' : 0, - '94i!UTM Zone' : 0, - '95i!Image Origin' : 0, - '96i!GPU' : 0, - '97i!reserved26' : 0, - '98i!reserved27' : 0, - '99i!GPU Hemi' : 0, - '100i!reserved41' : 0, - '101i!reserved42' : 0, - '102i!reserved43' : 0, - '103i!Cubemap' : 0, - '104t588!reserved44' : '', - '105t512!Comments' : '', - '106i!reserved28' : 0, - '107i!reserved29' : 0, - '108i!reserved30' : 0, - '109i!reserved31' : 0, - '110i!reserved32' : 0, - '111i!reserved33' : 0, - '112i!reserved34' : 0, - '113i!reserved35' : 0, - '114i!reserved36' : 0, - '115i!reserved37' : 0, - '116i!reserved38' : 0, - '117i!reserved39' : 0, - '118i!reserved40' : 0, - '119i!reserved45' : 0, - '120i!Format Version' : 0, - '121i!GPU num' : 0, -} - -FLTImageDisplay = [18,19,29,21,22,23,24,25,26,62,63,64,65,66,67,68,69,70,74,75,76,77,78,79,93,97,98,102,114] - -FLTHeader = { - '3t8!id' : 'db', - '4i!version' : 1620, - '5i!editversion' : 0, - '6t32!date' : 0, - '7s!NGID' : 0, - '8s!NLID' : 0, - '9s!NOID' : 0, - '10s!NFID' : 0, - '11s!UMULT' : 1, - '12c!units' : 0, - '13c!set white' : 0, - '14I!flags' : 0x80000000, - '15i!reserved1' : 0, - '16i!reserved2' : 0, - '17i!reserved3' : 0, - '18i!reserved4' : 0, - '19i!reserved5' : 0, - '20i!reserved6' : 0, - '21i!projection type' : 0, - '22i!reserved7' : 0, - '23i!reserved8' : 0, - '24i!reserved9' : 0, - '25i!reserved10' : 0, - '26i!reserved11' : 0, - '27i!reserved12' : 0, - '28i!reserved13' : 0, - '29s!NDID' : 0, - '30s!vstore' : 1, - '31i!origin' : 0, - '32d!sw x' : 0, - '33d!sw y' : 0, - '34d!dx' : 0, - '35d!dy' : 0, - '36s!NSID' : 0, - '37s!NPID' : 0, - '38i!reserved14' : 0, - '39i!reserved15' : 0, - '40s!NCID' : 0, - '41s!NTID' : 0, - '42s!NBID' : 0, - '43s!NWID' : 0, - '44i!reserved14' : 0, - '45d!sw lat' : 0, - '46d!sw lon' : 0, - '47d!ne lat' : 0, - '48d!ne lon' : 0, - '49d!origin lat' : 0, - '50d!origin lon' : 0, - '51d!lambert lat1' : 0, - '52d!lambert lat2' : 0, - '53s!NLSID' : 0, - '54s!NLPID' : 0, - '55s!NRID' : 0, - '56s!NCATID' : 0, - '57s!reserved15' : 0, - '58s!reserved16' : 0, - '59s!reserved17' : 0, - '60s!reserved18' : 0, - '61i!ellipsoid model' : 1, - '62s!NAID' : 0, - '63s!NCVID' : 0, - '64s!utm zone' : 0, - '65t6!reserved19' : 0, - '66d!dz' : 0, - '67d!radius' : 0, - '68S!NMID' : 0, - '69S!NLPSID' : 0, - '70i!reserved20' : 0, - '71d!major axis' : 0, - '72d!minor axis' : 0, -} - -FLT_Records = { - 2 : FLTGroup, - 4 : FLTObject, - 73 : FLTLOD, - 63 : FLTXRef, - 14 : FLTDOF, - 1 : FLTHeader, - 111 : FLTInlineLP, - 100 : FLTExt, - 'Image' : FLTImage -} - -def process_recordDefs(): - records = dict() - for record in FLT_Records: - props = dict() - for prop in FLT_Records[record]: - position = '' - slice = 0 - (format,name) = prop.split('!') - for i in format: - if i not in typecodes: - position = position + i - slice = slice + 1 - else: - break - type = format[slice:] - length = type[1:] - if len(length) == 0: - length = 1 - else: - type = type[0] - length = int(length) - - props[int(position)] = (type,length,prop) - records[record] = props - return records - - diff --git a/release/scripts/flt_toolbar.py b/release/scripts/flt_toolbar.py deleted file mode 100644 index a707b87f846..00000000000 --- a/release/scripts/flt_toolbar.py +++ /dev/null @@ -1,809 +0,0 @@ -#!BPY - -""" -Name: 'FLT Toolbar' -Blender: 240 -Group: 'Misc' -Tooltip: 'Tools for working with FLT databases' -""" - -__author__ = "Geoffrey Bantle" -__version__ = "1.0 11/21/07" -__email__ = ('scripts', 'Author, ') -__url__ = ('blender', 'blenderartists.org') - -__bpydoc__ ="""\ -This script provides tools for working with OpenFlight databases in Blender. OpenFlight is a -registered trademark of MultiGen-Paradigm, Inc. - -Feature overview and more availible at: -http://wiki.blender.org/index.php/Scripts/Manual/FLTools -""" - -# -------------------------------------------------------------------------- -# flt_palettemanager.py version 0.1 2005/04/08 -# -------------------------------------------------------------------------- -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Copyright (C) 2007: Blender Foundation -# -# 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 ***** -# -------------------------------------------------------------------------- - -import Blender.Draw as Draw -from Blender.BGL import * -import Blender -import flt_properties -reload(flt_properties) -from flt_properties import * - -xrefprefix = "" -xrefstack = list() -vofsstack = list() -vquatstack = list() -prop_w = 256 -prop_h = 256 - - -#event codes -evcode = { - "XREF_MAKE" : 100, - "XREF_EDIT" : 101, - "XREF_FILE" : 102, - "XREF_PICK" : 103, - "XREF_SELECT" : 104, - "XREF_POP" : 105, - "XREF_PREFIX" : 106, - "FACE_NAME" : 200, - "FACE_MAKESUB" : 201, - "FACE_KILLSUB" : 202, - "FACE_SELSUB" : 203, - "SCENE_UPDATE" : 303, - "IDPROP_COPY" : 501, - "IDPROP_KILL" : 502, - "CLIGHT_MAKE" : 700, - "DFROMACT" : 701, - "FIXCOL" : 702 -} - -XREF_PREFIX = None -XREF_MAKE = None -XREF_EDIT = None -XREF_SELECT = None -XREF_POP = None -FACE_MAKESUB = None -FACE_SELSUB = None -FACE_KILLSUB = None -IDPROP_KILL = None -IDPROP_COPY = None -SCENE_UPDATE = None -CLIGHT_MAKE = None -DFROMACT = None -FIXCOL = None - - -def RGBtoHSV( r, g, b): - cmin = min( r, g, b ) - cmax = max( r, g, b ) - v = cmax - - if(cmax!=0.0): - s = (cmax-cmin)/cmax - else: - s = 0.0 - h = 0.0 - - if(s == 0.0): - h = -1.0 - else: - cdelta = cmax-cmin - rc = (cmax-r)/cdelta - gc = (cmax-g)/cdelta - bc = (cmax-b)/cdelta - if(r==cmax): - h = bc-gc - else: - if(g==cmax): - h = 2.0+rc-bc - else: - h = 4.0+gc-rc - h = h*60.0 - if(h<0.0): - h += 360.0 - - - h = h/360.0 - if(h < 0.0): - h = 0.0 - return (h,s,v) - - -def update_state(): - state = dict() - state["activeScene"] = Blender.Scene.GetCurrent() - state["activeObject"] = state["activeScene"].objects.active - if state["activeObject"] and not state["activeObject"].sel: - state["activeObject"] = None - state["activeMesh"] = None - if state["activeObject"] and state["activeObject"].type == 'Mesh': - state["activeMesh"] = state["activeObject"].getData(mesh=True) - - state["activeFace"] = None - if state["activeMesh"]: - if state["activeMesh"].faceUV and state["activeMesh"].activeFace != None: - state["activeFace"] = state["activeMesh"].faces[state["activeMesh"].activeFace] - - #update editmode - state["editmode"] = Blender.Window.EditMode() - - return state -def pack_face_index(index, intensity): - return ((127*intensity)+(128*index)) -def unpack_face_index(face_index): - index = face_index / 128 - intensity = float(face_index - 128.0 * index) / 127.0 - return(index,intensity) - -def idprops_append(object, typecode, props): - object.properties["FLT"] = dict() - object.properties["FLT"]['type'] = typecode - for prop in props: - object.properties["FLT"][prop] = props[prop] - object.properties["FLT"]['3t8!id'] = object.name - -def idprops_kill(object): - state = update_state() - if object and object.properties.has_key('FLT'): - object.properties.pop('FLT') - -def idprops_copy(source): - state = update_state() - if source.properties.has_key('FLT'): - for object in state["activeScene"].objects: - if object.sel and object != source and (state["activeScene"].Layers & object.Layers): - idprops_kill(object) - object.properties['FLT'] = dict() - for key in source.properties['FLT']: - object.properties['FLT'][key] = source.properties['FLT'][key] - -def unpack_color(color): - return struct.unpack('>BBBB',struct.pack('>I',color)) - - -def findColorKey(colordict, hsv): - hdelta = 0.001 - for key in colordict: - if not (((hsv[0] < (key[0] + hdelta)) and (hsv[0] > (key[0] - hdelta))) and ((hsv[1] < (key[1] + hdelta)) and (hsv[1] > (key[1] - hdelta)))): - return key - return None - -def hsvsort(a, b): - (index1, mag1) = a - (index2, mag2) = b - if mag1 > mag2: - return 1 - elif mag1 < mag2: - return -1 - return 0 - -def fix_colors(): - - editmode = 0 - if Blender.Window.EditMode(): - Blender.Window.EditMode(0) - editmode = 1 - state = update_state() - - scene = state["activeScene"] - colors = None - if state["activeScene"].properties.has_key('FLT'): - try: - colors = state["activeScene"].properties['FLT']['Color Palette'] - except: - pass - if not colors: - return - - #first build a HSV version of our palette - hsvpalette = list() - for swatch in colors: - color = unpack_color(swatch) - hsv = RGBtoHSV(color[0] / 255.0, color[1] / 255.0, color[2] / 255.0) - hsvpalette.append(hsv) - - #collect all of our meshes - meshes = list() - for object in scene.objects.context: - if object.sel and object.type == 'Mesh': - mesh = object.getData(mesh=True) - if "FLT_COL" in mesh.faces.properties: - meshes.append(mesh) - - - #Now go through our meshes, and build a dictionary of face lists keyed according to (hue,saturation) of the baked color - colordict = dict() - for mesh in meshes: - for face in mesh.faces: - hsv = RGBtoHSV(face.col[0].r/255.0, face.col[0].g/255.0, face.col[0].b/255.0) #retrieve baked color - if colordict.has_key((hsv[0],hsv[1])): - colordict[(hsv[0],hsv[1])].append(face) - else: - colordict[(hsv[0],hsv[1])] = [face] - - - #for each color key in the color dict, build a list of distances from it to the values in hsvpalette and then quicksort them for closest match - for key in colordict: - maglist = list() - for i, hsv in enumerate(hsvpalette): - norm = Blender.Mathutils.Vector(hsv[0], hsv[1]) - Blender.Mathutils.Vector(key[0],key[1]) - maglist.append((i,norm.length)) - maglist.sort(hsvsort) - print maglist[0] - for face in colordict[key]: - (index, intensity) = unpack_face_index(face.getProperty("FLT_COL")) - newfindex = pack_face_index(maglist[0][0],intensity) - face.setProperty("FLT_COL", int(newfindex)) - - for mesh in meshes: - update_mesh_colors(colors,mesh) - - if editmode: - Blender.Window.EditMode(1) - - -def update_mesh_colors(colors, mesh): - if 'FLT_COL' in mesh.faces.properties: - mesh.activeColorLayer = "FLT_Fcol" - for face in mesh.faces: - (index,intensity) = unpack_face_index(face.getProperty('FLT_COL')) - color = struct.unpack('>BBBB',struct.pack('>I',colors[index])) - - if index == 0 and intensity == 0: - color = (255,255,255) - intensity = 1.0 - #update the vertex colors for this face - for col in face.col: - col.r = int(color[0] * intensity) - col.g = int(color[1] * intensity) - col.b = int(color[2] * intensity) - col.a = 255 - - -def update_all(): - - editmode = 0 - if Blender.Window.EditMode(): - Blender.Window.EditMode(0) - editmode = 1 - state = update_state() - colors = None - if state["activeScene"].properties.has_key('FLT'): - try: - colors = state["activeScene"].properties['FLT']['Color Palette'] - except: - pass - if colors: - #update the baked FLT colors for all meshes. - for object in state["activeScene"].objects: - if object.type == "Mesh": - mesh = object.getData(mesh=True) - update_mesh_colors(colors,mesh) - if editmode: - Blender.Window.EditMode(1) - -#Change this to find the deep parent -def xref_create(): - global xrefprefix - global xrefstack - global vofsstack - global vquatstack - global prop_w - global prop_h - - state = update_state() - - def findchildren(object): - children = list() - for candidate in state["activeScene"].objects: - if candidate.parent == object: - children.append(candidate) - retlist = list(children) - for child in children: - retlist = retlist + findchildren(child) - return retlist - - actObject = state["activeObject"] - if actObject and xrefprefix: - scenenames = list() - for scene in Blender.Scene.Get(): - scenenames.append(scene.name) - - if xrefprefix in scenenames: - #build a unique name for the xref... - suffix = 1 - found = False - while not found: - candidate = xrefprefix + str(suffix) - if not candidate in scenenames: - xrefname = candidate - found = True - suffix+=1 - else: - xrefname = xrefprefix - #create our XRef node - xnode = state["activeScene"].objects.new('Empty') - xnode.name = 'X:' + xrefname - xnode.properties['FLT'] = dict() - for prop in FLTXRef: - xnode.properties['FLT'][prop] = FLTXRef[prop] - xnode.properties['FLT']['3t200!filename'] = xrefname + '.flt' - xnode.properties['FLT']['type'] = 63 - xnode.enableDupGroup = True - xnode.DupGroup = Blender.Group.New(xrefname) #this is dangerous... be careful! - - #copy rot and loc of actObject - xnode.setLocation(actObject.getLocation()) - xnode.setEuler(actObject.getEuler()) - - #build the new scene - xrefscene = Blender.Scene.New(xrefname) - xrefscene.properties['FLT'] = dict() - xrefscene.properties['FLT']['Filename'] = xrefname - xrefscene.properties['FLT']['Main'] = 0 - - #find the children of actObject so that we can add them to the group - linkobjects = findchildren(actObject) - linkobjects.append(actObject) - for object in linkobjects: - xrefscene.objects.link(object) - state["activeScene"].objects.unlink(object) - xnode.DupGroup.objects.link(object) - #clear rotation of actObject and location - actObject.setLocation(0.0,0.0,0.0) - actObject.setEuler(0.0,0.0,0.0) - - xrefscene.update(1) - state["activeScene"].update(1) - -def xref_select(): - state = update_state() - candidates = list() - scenelist = [scene.name for scene in Blender.Scene.Get()] - for object in state["activeScene"].objects: - if object.type == 'Empty' and object.enableDupGroup == True and object.DupGroup: - candidates.append(object) - - for object in candidates: - if object.DupGroup.name in scenelist: - object.sel = 1 - -def xref_edit(): - global xrefprefix - global xrefstack - global vofsstack - global vquatstack - global prop_w - global prop_h - - state = update_state() - - actObject = state["activeObject"] - - if actObject and actObject.type == 'Empty' and actObject.DupGroup: -# if actObject.properties.has_key('FLT') and actObject.properties['FLT']['type'] == 63: - for FLTscene in Blender.Scene.Get(): - if FLTscene.properties.has_key('FLT') and FLTscene.name == actObject.DupGroup.name: - actObject.sel = 0 - xrefstack.append(state["activeScene"]) - vofsstack.append(Blender.Window.GetViewOffset()) - vquatstack.append(Blender.Window.GetViewQuat()) - FLTscene.makeCurrent() - Blender.Window.SetViewOffset(0.0,0.0,0.0) - -def xref_finish(): - global xrefprefix - global xrefstack - global vofsstack - global vquatstack - global prop_w - global prop_h - - state = update_state() - if xrefstack: - scene = xrefstack.pop() - Blender.Window.SetViewQuat(vquatstack.pop()) - Blender.Window.SetViewOffset(vofsstack.pop()) - scene.makeCurrent() - - -def sortSub(a,b): - aindex = a.getProperty("FLT_ORIGINDEX") - bindex = b.getProperty("FLT_ORIGINDEX") - - if aindex > bindex: - return 1 - elif aindex < bindex: - return -1 - return 0 - -def subface_make(): - global xrefprefix - global xrefstack - global vofsstack - global vquatstack - global prop_w - global prop_h - - editmode = 0 - if Blender.Window.EditMode(): - Blender.Window.EditMode(0) - editmode = 1 - - state = update_state() - - actmesh = state["activeMesh"] - activeFace = state["activeFace"] - if actmesh: - if not "FLT_ORIGINDEX" in actmesh.faces.properties: - actmesh.faces.addPropertyLayer("FLT_ORIGINDEX",Blender.Mesh.PropertyTypes["INT"]) - for i, face in enumerate(actmesh.faces): - face.setProperty("FLT_ORIGINDEX",i) - if not "FLT_SFLEVEL" in actmesh.faces.properties: - actmesh.faces.addPropertyLayer("FLT_SFLEVEL",Blender.Mesh.PropertyTypes["INT"]) - - #attach the subfaces to the active face. Note, this doesnt really work 100 percent properly yet, just enough for one level! - if activeFace: - #steps: - #remove actface and selected faces from the facelist - #quicksort facelist - #append actface and subfaces to end of facelist. - #generate new indices - facelist = list() - sublist = list() - for face in actmesh.faces: - facelist.append(face) - for face in facelist: - if face == activeFace: - face.setProperty("FLT_SFLEVEL",0) - sublist.insert(0,face) - elif face.sel: - face.setProperty("FLT_SFLEVEL",1) - sublist.append(face) - for face in sublist: - facelist.remove(face) - facelist.sort(sortSub) - for face in sublist: - facelist.append(face) - for i, face in enumerate(facelist): - face.setProperty("FLT_ORIGINDEX",i) - else: - pass - - if editmode: - Blender.Window.EditMode(1) - -def subface_kill(): - global xrefprefix - global xrefstack - global vofsstack - global vquatstack - global prop_w - global prop_h - - editmode = 0 - if Blender.Window.EditMode(): - Blender.Window.EditMode(0) - editmode = 1 - state = update_state() - - actmesh = state["activeMesh"] - if actmesh: - if "FLT_ORIGINDEX" in actmesh.faces.properties and "FLT_SFLEVEL" in actmesh.faces.properties: - for i,face in enumerate(actmesh.faces): - face.setProperty("FLT_ORIGINDEX",i) - face.setProperty("FLT_SFLEVEL",0) - if editmode: - Blender.Window.EditMode(1) - -def subface_select(): - global xrefprefix - global xrefstack - global vofsstack - global vquatstack - global prop_w - global prop_h - - editmode = 0 - if Blender.Window.EditMode(): - Blender.Window.EditMode(0) - editmode = 1 - state = update_state() - - actmesh = state["activeMesh"] - activeFace = state["activeFace"] - if actmesh and activeFace: - if "FLT_ORIGINDEX" in actmesh.faces.properties and "FLT_SFLEVEL" in actmesh.faces.properties: - facelist = list() - actIndex = None - sublevel = None - for face in actmesh.faces: - facelist.append(face) - facelist.sort(sortSub) - for i, face in enumerate(facelist): - if face == activeFace: - actIndex = i - sublevel = face.getProperty("FLT_SFLEVEL")+1 - break - leftover = facelist[actIndex+1:] - for face in leftover: - if face.getProperty("FLT_SFLEVEL") == sublevel: - face.sel = 1 - else: - break - if editmode: - Blender.Window.EditMode(1) - -def select_by_typecode(typecode): - global xrefprefix - global xrefstack - global vofsstack - global vquatstack - global prop_w - global prop_h - - state = update_state() - - for object in state["activeScene"].objects: - if object.properties.has_key('FLT') and object.properties['FLT']['type'] == typecode and state["activeScene"].Layers & object.Layers: - object.select(1) -def clight_make(): - state = update_state() - actmesh = state["activeMesh"] - actobj = state["activeObject"] - - if actobj and actmesh: - actobj.properties['FLT'] = dict() - actobj.properties['FLT']['type'] = 111 - for prop in FLTInlineLP: - actobj.properties['FLT'][prop] = FLTInlineLP[prop] - - actmesh.verts.addPropertyLayer("FLT_VCOL", Blender.Mesh.PropertyTypes["INT"]) - for v in actmesh.verts: - v.setProperty("FLT_VCOL", 83815) - -def dfromact(): - state = update_state() - actobj = state["activeObject"] - actscene = state["activeScene"] - dof = None - - for object in actscene.objects.context: - if object.sel and (object != actobj): - if not dof: - dof = object - else: - break - - if not dof: - return - - if 'FLT' not in dof.properties: - dof.properties['FLT'] = dict() - - #Warning! assumes 1 BU == 10 meters. - #do origin - dof.properties['FLT']['5d!ORIGX'] = actobj.getLocation('worldspace')[0]*10.0 - dof.properties['FLT']['6d!ORIGY'] = actobj.getLocation('worldspace')[1]*10.0 - dof.properties['FLT']['7d!ORIGZ'] = actobj.getLocation('worldspace')[2]*10.0 - #do X axis - x = Blender.Mathutils.Vector(1.0,0.0,0.0) - x = x * actobj.getMatrix('worldspace') - x = x * 10.0 - dof.properties['FLT']['8d!XAXIS-X'] = x[0] - dof.properties['FLT']['9d!XAXIS-Y'] = x[1] - dof.properties['FLT']['10d!XAXIS-Z'] = x[2] - #do X/Y plane - x = Blender.Mathutils.Vector(1.0,1.0,0.0) - x.normalize() - x = x * actobj.getMatrix('worldspace') - x = x * 10.0 - dof.properties['FLT']['11d!XYPLANE-X'] = x[0] - dof.properties['FLT']['12d!XYPLANE-Y'] = x[1] - dof.properties['FLT']['13d!XZPLANE-Z'] = x[2] - - - - - -def event(evt,val): - if evt == Draw.ESCKEY: - Draw.Exit() - -def but_event(evt): - global xrefprefix - global xrefstack - global vofsstack - global vquatstack - global prop_w - global prop_h - global evcode - - state = update_state() - - #do Xref buttons - if evt == evcode["XREF_PREFIX"]: - xrefprefix = XREF_PREFIX.val - if evt == evcode["XREF_EDIT"]: - xref_edit() - if evt == evcode["XREF_SELECT"]: - xref_select() - if evt == evcode["XREF_MAKE"]: - xref_create() - #do scene buttons - if evt == evcode["SCENE_UPDATE"]: - update_all() - #do face buttons - if evt == evcode["FACE_MAKESUB"]: - subface_make() - if evt== evcode["FACE_KILLSUB"]: - subface_kill() - if evt== evcode["FACE_SELSUB"]: - subface_select() - #common buttons - if evt == evcode["IDPROP_KILL"]: - if state["activeObject"]: - idprops_kill(state["activeObject"]) - if evt == evcode["IDPROP_COPY"]: - if state["activeObject"]: - idprops_copy(state["activeObject"]) - if evt == evcode["XREF_POP"]: - xref_finish() - if evt == evcode["CLIGHT_MAKE"]: - clight_make() - if evt == evcode["DFROMACT"]: - dfromact() - if evt == evcode["FIXCOL"]: - fix_colors() - Draw.Redraw(1) - Blender.Window.RedrawAll() - - -def box(x,y,w,h,c,mode): - glColor3f(c[0],c[1],c[2]) - if mode == "outline": - glBegin(GL_LINE_LOOP) - else: - glBegin(GL_POLYGON) - glVertex2i(x,y) - glVertex2i(x+w,y) - glVertex2i(x+w,y+h) - glVertex2i(x,y+h) - glEnd() - -def draw_postcommon(x,y,finaly): - global sheetlabel - global xrefprefix - global xrefstack - global vofsstack - global vquatstack - global prop_w - global prop_h - global evcode - - state = update_state() - - width = prop_w - height = prop_h - - #draw the header - glColor3f(0.15,0.15,0.15) - glBegin(GL_POLYGON) - glVertex2i(x-1,y) - glVertex2i(x+width+1,y) - glVertex2i(x+width+1,y-25) - glVertex2i(x-1,y-25) - glEnd() - glColor3f(1,1,1) - glRasterPos2i(x,y-20) - sheetlabel = Blender.Draw.Text("FLT Tools Panel") - #draw the box outline - glColor3f(0,0,0) - glBegin(GL_LINE_LOOP) - glVertex2i(x-1,y) - glVertex2i(x+1+width,y) - glVertex2i(x+1+width,finaly-1) - glVertex2i(x-1,finaly-1) - glEnd() - return finaly - - -def draw_propsheet(x,y): - global XREF_PREFIX - global XREF_MAKE - global XREF_EDIT - global XREF_SELECT - global XREF_POP - global FACE_MAKESUB - global FACE_SELSUB - global FACE_KILLSUB - global IDPROP_KILL - global IDPROP_COPY - global SCENE_UPDATE - global DFROMACT - global FIXCOL - - global CLIGHT_MAKE - global xrefprefix - global xrefstack - global vofsstack - global vquatstack - global prop_w - global prop_h - global evcode - - state = update_state() - - width = prop_w - height = prop_h - origx = x - origy = y - - #draw Xref tools - y = y-20 - XREF_PREFIX = Blender.Draw.String("XRef Name:",evcode["XREF_PREFIX"],x,y,width,20,xrefprefix,18,"Xref prefix name, Actual name is generated from this") - y = y-20 - XREF_MAKE = Blender.Draw.PushButton("Make XRef",evcode["XREF_MAKE"],x,y,width,20,"Make External Reference") - y = y-20 - XREF_EDIT = Blender.Draw.PushButton("Edit XRef",evcode["XREF_EDIT"],x,y,width,20,"Edit External Reference") - y = y-20 - XREF_SELECT = Blender.Draw.PushButton("Select XRefs",evcode["XREF_SELECT"],x,y,width,20,"Select External References") - y = y - 20 - XREF_POP = Blender.Draw.PushButton("Return to previous scene",evcode["XREF_POP"],x,y,width,20,"Go up one level in xref hierarchy") - - #Draw facetools - y = y-20 - FACE_MAKESUB = Blender.Draw.PushButton("Make Subfaces",evcode["FACE_MAKESUB"],x,y,width,20,"Make subfaces") - y = y-20 - FACE_SELSUB = Blender.Draw.PushButton("Select Subfaces",evcode["FACE_SELSUB"],x,y,width,20,"Select subfaces") - y = y-20 - FACE_KILLSUB = Blender.Draw.PushButton("Kill Subfaces",evcode["FACE_KILLSUB"],x,y,width,20,"Kill subfaces") - - #Draw ID Property tools - y = y - 20 - IDPROP_KILL = Blender.Draw.PushButton("Delete ID props",evcode["IDPROP_KILL"],x,y,width,20,"Delete ID props") - y = y - 20 - IDPROP_COPY = Blender.Draw.PushButton("Copy to selected",evcode["IDPROP_COPY"],x,y,width,20, "Copy from active to all selected") - - y= y - 20 - CLIGHT_MAKE = Blender.Draw.PushButton("Make Light Point", evcode["CLIGHT_MAKE"],x,y,width,20,"Create inline light points from current mesh") - #General tools - y = y-20 - SCENE_UPDATE = Blender.Draw.PushButton("Update All",evcode["SCENE_UPDATE"],x,y,width,20,"Update all vertex colors") - - y=y-20 - DFROMACT = Blender.Draw.PushButton("Dof from Active", evcode["DFROMACT"],x,y,width,20,"Get Dof origin from active object") - y=y-20 - FIXCOL = Blender.Draw.PushButton("Fix Colors", evcode["FIXCOL"],x,y,width,20,"Fix baked FLT colors of selected meshes") - draw_postcommon(origx, origy,y) - -def gui(): - #draw the propsheet/toolbox. - psheety = 300 - #psheetx = psheety + 10 - draw_propsheet(0,psheety) -Draw.Register(gui,event,but_event) -
\ No newline at end of file diff --git a/release/scripts/help_bpy_api.py b/release/scripts/help_bpy_api.py deleted file mode 100644 index e8d77ed8452..00000000000 --- a/release/scripts/help_bpy_api.py +++ /dev/null @@ -1,47 +0,0 @@ -#!BPY -""" -Name: 'Blender/Python Scripting API' -Blender: 248 -Group: 'Help' -Tooltip: 'The Blender Python API reference manual' -""" - -__author__ = "Matt Ebb" -__url__ = ("blender", "blenderartist") -__version__ = "1.0.1" -__bpydoc__ = """\ -This script opens the user's default web browser at http://www.blender.org's -"Blender Python API Reference" page. -""" - -# -------------------------------------------------------------------------- -# Blender/Python Scripting Reference Help Menu Item -# -------------------------------------------------------------------------- -# ***** 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 ***** -# -------------------------------------------------------------------------- - -import Blender -try: import webbrowser -except: webbrowser = None - -if webbrowser: - version = str(int(Blender.Get('version'))) - webbrowser.open('http://www.blender.org/documentation/'+ version +'PythonDoc/') -else: - Blender.Draw.PupMenu("Error%t|This script requires a full python installation") diff --git a/release/scripts/help_browser.py b/release/scripts/help_browser.py deleted file mode 100644 index c207a12068f..00000000000 --- a/release/scripts/help_browser.py +++ /dev/null @@ -1,814 +0,0 @@ -#!BPY - -""" -Name: 'Scripts Help Browser' -Blender: 234 -Group: 'Help' -Tooltip: 'Show help information about a chosen installed script.' -""" - -__author__ = "Willian P. Germano" -__version__ = "0.3 01/21/09" -__email__ = ('scripts', 'Author, wgermano:ig*com*br') -__url__ = ('blender', 'blenderartists.org') - -__bpydoc__ ="""\ -This script shows help information for scripts registered in the menus. - -Usage: - -- Start Screen: - -To read any script's "user manual" select a script from one of the -available category menus. If the script has help information in the format -expected by this Help Browser, it will be displayed in the Script Help -Screen. Otherwise you'll be offered the possibility of loading the chosen -script's source file in Blender's Text Editor. The programmer(s) may have -written useful comments there for users. - -Hotkeys:<br> - ESC or Q: [Q]uit - -- Script Help Screen: - -This screen shows the user manual page for the chosen script. If the text -doesn't fit completely on the screen, you can scroll it up or down with -arrow keys or a mouse wheel. There may be link and email buttons that if -clicked should open your default web browser and email client programs for -further information or support. - -Hotkeys:<br> - ESC: back to Start Screen<br> - Q: [Q]uit<br> - S: view script's [S]ource code in Text Editor<br> - UP, DOWN Arrows and mouse wheel: scroll text up / down -""" - -# $Id$ -# -# -------------------------------------------------------------------------- -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Copyright (C) 2004: Willian P. Germano, wgermano _at_ ig.com.br -# -# 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 ***** -# -------------------------------------------------------------------------- -# Thanks: Brendon Murphy (suggestion) and Kevin Morgan (implementation) -# for the "run" button; Jean-Michel Soler for pointing a parsing error -# with multilines using triple single quotes. - -import Blender -from Blender import sys as bsys, Draw, Window, Registry - -WEBBROWSER = True -try: - import webbrowser -except: - WEBBROWSER = False - -DEFAULT_EMAILS = { - 'scripts': ['Bf-scripts-dev', 'bf-scripts-dev@blender.org'] -} - -DEFAULT_LINKS = { - 'blender': ["blender.org\'s Python forum", "http://www.blender.org/modules.php?op=modload&name=phpBB2&file=viewforum&f=9"] -} - -PADDING = 15 -COLUMNS = 1 -TEXT_WRAP = 100 -WIN_W = WIN_H = 200 -SCROLL_DOWN = 0 - -def screen_was_resized(): - global WIN_W, WIN_H - - w, h = Window.GetAreaSize() - if WIN_W != w or WIN_H != h: - WIN_W = w - WIN_H = h - return True - return False - -def fit_on_screen(): - global TEXT_WRAP, PADDING, WIN_W, WIN_H, COLUMNS - - COLUMNS = 1 - WIN_W, WIN_H = Window.GetAreaSize() - TEXT_WRAP = int((WIN_W - PADDING) / 6) - if TEXT_WRAP < 40: - TEXT_WRAP = 40 - elif TEXT_WRAP > 100: - if TEXT_WRAP > 110: - COLUMNS = 2 - TEXT_WRAP /= 2 - else: TEXT_WRAP = 100 - -def cut_point(text, length): - "Returns position of the last space found before 'length' chars" - l = length - c = text[l] - while c != ' ': - l -= 1 - if l == 0: return length # no space found - c = text[l] - return l - -def text_wrap(text, length = None): - global TEXT_WRAP - - wrapped = [] - lines = text.split('<br>') - llen = len(lines) - if llen > 1: - if lines[-1] == '': llen -= 1 - for i in range(llen - 1): - lines[i] = lines[i].rstrip() + '<br>' - lines[llen-1] = lines[llen-1].rstrip() - - if not length: length = TEXT_WRAP - - for l in lines: - while len(l) > length: - cpt = cut_point(l, length) - line, l = l[:cpt], l[cpt + 1:] - wrapped.append(line) - wrapped.append(l) - return wrapped - -def load_script_text(script): - global PATHS, SCRIPT_INFO - - if script.userdir: - path = PATHS['uscripts'] - else: - path = PATHS['scripts'] - - fname = bsys.join(path, script.fname) - - source = Blender.Text.Load(fname) - if source: - Draw.PupMenu("File loaded%%t|Please check the file \"%s\" in the Text Editor window" % source.name) - - -# for theme colors: -def float_colors(cols): - return map(lambda x: x / 255.0, cols) - -# globals - -SCRIPT_INFO = None - -PATHS = { - 'home': Blender.Get('homedir'), - 'scripts': Blender.Get('scriptsdir'), - 'uscripts': Blender.Get('uscriptsdir') -} - -if not PATHS['home']: - errmsg = """ -Can't find Blender's home dir and so can't find the -Bpymenus file automatically stored inside it, which -is needed by this script. Please run the -Help -> System -> System Information script to get -information about how to fix this. -""" - raise SystemError, errmsg - -BPYMENUS_FILE = bsys.join(PATHS['home'], 'Bpymenus') - -f = file(BPYMENUS_FILE, 'r') -lines = f.readlines() -f.close() - -AllGroups = [] - -class Script: - - def __init__(self, data): - self.name = data[0] - self.version = data[1] - self.fname = data[2] - self.userdir = data[3] - self.tip = data[4] - -# End of class Script - - -class Group: - - def __init__(self, name): - self.name = name - self.scripts = [] - - def add_script(self, script): - self.scripts.append(script) - - def get_name(self): - return self.name - - def get_scripts(self): - return self.scripts - -# End of class Group - - -class BPy_Info: - - def __init__(self, script, dict): - - self.script = script - - self.d = dict - - self.header = [] - self.len_header = 0 - self.content = [] - self.len_content = 0 - self.spaces = 0 - self.fix_urls() - self.make_header() - self.wrap_lines() - - def make_header(self): - - sc = self.script - d = self.d - - header = self.header - - title = "Script: %s" % sc.name - version = "Version: %s for Blender %1.2f or newer" % (d['__version__'], - sc.version / 100.0) - - if len(d['__author__']) == 1: - asuffix = ':' - else: asuffix = 's:' - - authors = "%s%s %s" % ("Author", asuffix, ", ".join(d['__author__'])) - - header.append(title) - header.append(version) - header.append(authors) - self.len_header = len(header) - - - def fix_urls(self): - - emails = self.d['__email__'] - fixed = [] - for a in emails: - if a in DEFAULT_EMAILS.keys(): - fixed.append(DEFAULT_EMAILS[a]) - else: - a = a.replace('*','.').replace(':','@') - ltmp = a.split(',') - if len(ltmp) != 2: - ltmp = [ltmp[0], ltmp[0]] - fixed.append(ltmp) - - self.d['__email__'] = fixed - - links = self.d['__url__'] - fixed = [] - for a in links: - if a in DEFAULT_LINKS.keys(): - fixed.append(DEFAULT_LINKS[a]) - else: - ltmp = a.split(',') - if len(ltmp) != 2: - ltmp = [ltmp[0], ltmp[0]] - fixed.append([ltmp[0].strip(), ltmp[1].strip()]) - - self.d['__url__'] = fixed - - - def wrap_lines(self, reset = 0): - - lines = self.d['__bpydoc__'].split('\n') - self.content = [] - newlines = [] - newline = [] - - if reset: - self.len_content = 0 - self.spaces = 0 - - for l in lines: - if l == '' and newline: - newlines.append(newline) - newline = [] - newlines.append('') - else: newline.append(l) - if newline: newlines.append(newline) - - for lst in newlines: - wrapped = text_wrap(" ".join(lst)) - for l in wrapped: - self.content.append(l) - if l: self.len_content += 1 - else: self.spaces += 1 - - if not self.content[-1]: - self.len_content -= 1 - - -# End of class BPy_Info - -def parse_pyobj_close(closetag, lines, i): - i += 1 - l = lines[i] - while l.find(closetag) < 0: - i += 1 - l = "%s%s" % (l, lines[i]) - return [l, i] - -def parse_pyobj(var, lines, i): - "Bad code, was in a hurry for release" - - l = lines[i].replace(var, '').replace('=','',1).strip() - - i0 = i - 1 - - if l[0] == '"': - if l[1:3] == '""': # """ - if l.find('"""', 3) < 0: # multiline - l2, i = parse_pyobj_close('"""', lines, i) - if l[-1] == '\\': l = l[:-1] - l = "%s%s" % (l, l2) - elif l[-1] == '"' and l[-2] != '\\': # single line: "..." - pass - else: - l = "ERROR" - - elif l[0] == "'": - if l[1:3] == "''": # ''' - if l.find("'''", 3) < 0: # multiline - l2, i = parse_pyobj_close("'''", lines, i) - if l[-1] == '\\': l = l[:-1] - l = "%s%s" % (l, l2) - elif l[-1] == '\\': - l2, i = parse_pyobj_close("'", lines, i) - l = "%s%s" % (l, l2) - elif l[-1] == "'" and l[-2] != '\\': # single line: '...' - pass - else: - l = "ERROR" - - elif l[0] == '(': - if l[-1] != ')': - l2, i = parse_pyobj_close(')', lines, i) - l = "%s%s" % (l, l2) - - elif l[0] == '[': - if l[-1] != ']': - l2, i = parse_pyobj_close(']', lines, i) - l = "%s%s" % (l, l2) - - return [l, i - i0] - -# helper functions: - -def parse_help_info(script): - - global PATHS, SCRIPT_INFO - - if script.userdir: - path = PATHS['uscripts'] - else: - path = PATHS['scripts'] - - fname = bsys.join(path, script.fname) - - if not bsys.exists(fname): - Draw.PupMenu('IO Error: couldn\'t find script %s' % fname) - return None - - f = file(fname, 'r') - lines = f.readlines() - f.close() - - # fix line endings: - if lines[0].find('\r'): - unixlines = [] - for l in lines: - unixlines.append(l.replace('\r','')) - lines = unixlines - - llen = len(lines) - has_doc = 0 - - doc_data = { - '__author__': '', - '__version__': '', - '__url__': '', - '__email__': '', - '__bpydoc__': '', - '__doc__': '' - } - - i = 0 - while i < llen: - l = lines[i] - incr = 1 - for k in doc_data.keys(): - if l.find(k, 0, 20) == 0: - value, incr = parse_pyobj(k, lines, i) - exec("doc_data['%s'] = %s" % (k, value)) - has_doc = 1 - break - i += incr - - # fix these to seqs, simplifies coding elsewhere - for w in ['__author__', '__url__', '__email__']: - val = doc_data[w] - if val and type(val) == str: - doc_data[w] = [doc_data[w]] - - if not doc_data['__bpydoc__']: - if doc_data['__doc__']: - doc_data['__bpydoc__'] = doc_data['__doc__'] - - if has_doc: # any data, maybe should confirm at least doc/bpydoc - info = BPy_Info(script, doc_data) - SCRIPT_INFO = info - return True - - else: - return False - - -def parse_script_line(l): - - tip = 'No tooltip' - try: - pieces = l.split("'") - name = pieces[1].replace('...','') - data = pieces[2].strip().split() - version = data[0] - userdir = data[-1] - fname = data[1] - i = 1 - while not fname.endswith('.py'): - i += 1 - fname = '%s %s' % (fname, data[i]) - if len(pieces) > 3: tip = pieces[3] - except: - return None - - return [name, int(version), fname, int(userdir), tip] - - -def parse_bpymenus(lines): - - global AllGroups - - llen = len(lines) - - for i in range(llen): - l = lines[i].strip() - if not l: continue - if l[-1] == '{': - group = Group(l[:-2]) - AllGroups.append(group) - i += 1 - l = lines[i].strip() - while l != '}': - if l[0] != '|': - data = parse_script_line(l) - if data: - script = Script(data) - group.add_script(script) - i += 1 - l = lines[i].strip() - -# AllGroups.reverse() - - -def create_group_menus(): - - global AllGroups - menus = [] - - for group in AllGroups: - - name = group.get_name() - menu = [] - scripts = group.get_scripts() - for s in scripts: menu.append(s.name) - menu = "|".join(menu) - menu = "%s%%t|%s" % (name, menu) - menus.append([name, menu]) - - return menus - - -# Collecting data: -fit_on_screen() -parse_bpymenus(lines) -GROUP_MENUS = create_group_menus() - - -# GUI: - -from Blender import BGL -from Blender.Window import Theme - -# globals: - -START_SCREEN = 0 -SCRIPT_SCREEN = 1 - -SCREEN = START_SCREEN - -# gui buttons: -len_gmenus = len(GROUP_MENUS) - -BUT_GMENU = range(len_gmenus) -for i in range(len_gmenus): - BUT_GMENU[i] = Draw.Create(0) - -# events: -BEVT_LINK = None # range(len(SCRIPT_INFO.links)) -BEVT_EMAIL = None # range(len(SCRIPT_INFO.emails)) -BEVT_GMENU = range(100, len_gmenus + 100) -BEVT_VIEWSOURCE = 1 -BEVT_EXIT = 2 -BEVT_BACK = 3 -BEVT_EXEC = 4 # Executes Script - -# gui callbacks: - -def gui(): # drawing the screen - - global SCREEN, START_SCREEN, SCRIPT_SCREEN - global SCRIPT_INFO, AllGroups, GROUP_MENUS - global BEVT_EMAIL, BEVT_LINK - global BEVT_VIEWSOURCE, BEVT_EXIT, BEVT_BACK, BEVT_GMENU, BUT_GMENU, BEVT_EXEC - global PADDING, WIN_W, WIN_H, SCROLL_DOWN, COLUMNS, FMODE - - theme = Theme.Get()[0] - tui = theme.get('ui') - ttxt = theme.get('text') - - COL_BG = float_colors(ttxt.back) - COL_TXT = ttxt.text - COL_TXTHI = ttxt.text_hi - - BGL.glClearColor(COL_BG[0],COL_BG[1],COL_BG[2],COL_BG[3]) - BGL.glClear(BGL.GL_COLOR_BUFFER_BIT) - BGL.glColor3ub(COL_TXT[0],COL_TXT[1], COL_TXT[2]) - - resize = screen_was_resized() - if resize: fit_on_screen() - - if SCREEN == START_SCREEN: - x = PADDING - bw = 85 - bh = 25 - hincr = 50 - - butcolumns = (WIN_W - 2*x)/ bw - if butcolumns < 2: butcolumns = 2 - elif butcolumns > 7: butcolumns = 7 - - len_gm = len(GROUP_MENUS) - butlines = len_gm / butcolumns - if len_gm % butcolumns: butlines += 1 - - h = hincr * butlines + 20 - y = h + bh - - BGL.glColor3ub(COL_TXTHI[0],COL_TXTHI[1], COL_TXTHI[2]) - BGL.glRasterPos2i(x, y) - Draw.Text('Scripts Help Browser') - - y -= bh - - BGL.glColor3ub(COL_TXT[0],COL_TXT[1], COL_TXT[2]) - - i = 0 - j = 0 - for group_menu in GROUP_MENUS: - BGL.glRasterPos2i(x, y) - Draw.Text(group_menu[0]+':') - BUT_GMENU[j] = Draw.Menu(group_menu[1], BEVT_GMENU[j], - x, y-bh-5, bw, bh, 0, - 'Choose a script to read its help information') - if i == butcolumns - 1: - x = PADDING - i = 0 - y -= hincr - else: - i += 1 - x += bw + 3 - j += 1 - - x = PADDING - y = 10 - BGL.glRasterPos2i(x, y) - Draw.Text('Select script for its help. Press Q or ESC to leave.') - - elif SCREEN == SCRIPT_SCREEN: - if SCRIPT_INFO: - - if resize: - SCRIPT_INFO.wrap_lines(1) - SCROLL_DOWN = 0 - - h = 18 * SCRIPT_INFO.len_content + 12 * SCRIPT_INFO.spaces - x = PADDING - y = WIN_H - bw = 38 - bh = 16 - - BGL.glColor3ub(COL_TXTHI[0],COL_TXTHI[1], COL_TXTHI[2]) - for line in SCRIPT_INFO.header: - y -= 18 - BGL.glRasterPos2i(x, y) - size = Draw.Text(line) - - for line in text_wrap('Tooltip: %s' % SCRIPT_INFO.script.tip): - y -= 18 - BGL.glRasterPos2i(x, y) - size = Draw.Text(line) - - i = 0 - y -= 28 - for data in SCRIPT_INFO.d['__url__']: - Draw.PushButton('link %d' % (i + 1), BEVT_LINK[i], - x + i*bw, y, bw, bh, data[0]) - i += 1 - y -= bh + 1 - - i = 0 - for data in SCRIPT_INFO.d['__email__']: - Draw.PushButton('email', BEVT_EMAIL[i], x + i*bw, y, bw, bh, data[0]) - i += 1 - y -= 18 - - y0 = y - BGL.glColor3ub(COL_TXT[0],COL_TXT[1], COL_TXT[2]) - for line in SCRIPT_INFO.content[SCROLL_DOWN:]: - if line: - line = line.replace('<br>', '') - BGL.glRasterPos2i(x, y) - Draw.Text(line) - y -= 18 - else: y -= 12 - if y < PADDING + 20: # reached end, either stop or go to 2nd column - if COLUMNS == 1: break - elif x == PADDING: # make sure we're still in column 1 - x = 6*TEXT_WRAP + PADDING / 2 - y = y0 - - x = PADDING - Draw.PushButton('source', BEVT_VIEWSOURCE, x, 17, 45, bh, - 'View this script\'s source code in the Text Editor (hotkey: S)') - Draw.PushButton('exit', BEVT_EXIT, x + 45, 17, 45, bh, - 'Exit from Scripts Help Browser (hotkey: Q)') - if not FMODE: - Draw.PushButton('back', BEVT_BACK, x + 2*45, 17, 45, bh, - 'Back to scripts selection screen (hotkey: ESC)') - Draw.PushButton('run script', BEVT_EXEC, x + 3*45, 17, 60, bh, 'Run this script') - - BGL.glColor3ub(COL_TXTHI[0],COL_TXTHI[1], COL_TXTHI[2]) - BGL.glRasterPos2i(x, 5) - Draw.Text('use the arrow keys or the mouse wheel to scroll text', 'small') - -def fit_scroll(): - global SCROLL_DOWN - if not SCRIPT_INFO: - SCROLL_DOWN = 0 - return - max = SCRIPT_INFO.len_content + SCRIPT_INFO.spaces - 1 - if SCROLL_DOWN > max: SCROLL_DOWN = max - if SCROLL_DOWN < 0: SCROLL_DOWN = 0 - - -def event(evt, val): # input events - - global SCREEN, START_SCREEN, SCRIPT_SCREEN - global SCROLL_DOWN, FMODE - - if not val: return - - if evt == Draw.ESCKEY: - if SCREEN == START_SCREEN or FMODE: Draw.Exit() - else: - SCREEN = START_SCREEN - SCROLL_DOWN = 0 - Draw.Redraw() - return - elif evt == Draw.QKEY: - Draw.Exit() - return - elif evt in [Draw.DOWNARROWKEY, Draw.WHEELDOWNMOUSE] and SCREEN == SCRIPT_SCREEN: - SCROLL_DOWN += 1 - fit_scroll() - Draw.Redraw() - return - elif evt in [Draw.UPARROWKEY, Draw.WHEELUPMOUSE] and SCREEN == SCRIPT_SCREEN: - SCROLL_DOWN -= 1 - fit_scroll() - Draw.Redraw() - return - elif evt == Draw.SKEY: - if SCREEN == SCRIPT_SCREEN and SCRIPT_INFO: - load_script_text(SCRIPT_INFO.script) - return - -def button_event(evt): # gui button events - - global SCREEN, START_SCREEN, SCRIPT_SCREEN - global BEVT_LINK, BEVT_EMAIL, BEVT_GMENU, BUT_GMENU, SCRIPT_INFO - global SCROLL_DOWN, FMODE - - if evt >= 100: # group menus - for i in range(len(BUT_GMENU)): - if evt == BEVT_GMENU[i]: - group = AllGroups[i] - index = BUT_GMENU[i].val - 1 - if index < 0: return # user didn't pick a menu entry - script = group.get_scripts()[BUT_GMENU[i].val - 1] - if parse_help_info(script): - SCREEN = SCRIPT_SCREEN - BEVT_LINK = range(20, len(SCRIPT_INFO.d['__url__']) + 20) - BEVT_EMAIL = range(50, len(SCRIPT_INFO.d['__email__']) + 50) - Draw.Redraw() - else: - res = Draw.PupMenu("No help available%t|View Source|Cancel") - if res == 1: - load_script_text(script) - elif evt >= 20: - if not WEBBROWSER: - Draw.PupMenu('Missing standard Python module%t|You need module "webbrowser" to access the web') - return - - if evt >= 50: # script screen email buttons - email = SCRIPT_INFO.d['__email__'][evt - 50][1] - webbrowser.open("mailto:%s" % email) - else: # >= 20: script screen link buttons - link = SCRIPT_INFO.d['__url__'][evt - 20][1] - webbrowser.open(link) - elif evt == BEVT_VIEWSOURCE: - if SCREEN == SCRIPT_SCREEN: load_script_text(SCRIPT_INFO.script) - elif evt == BEVT_EXIT: - Draw.Exit() - return - elif evt == BEVT_BACK: - if SCREEN == SCRIPT_SCREEN and not FMODE: - SCREEN = START_SCREEN - SCRIPT_INFO = None - SCROLL_DOWN = 0 - Draw.Redraw() - elif evt == BEVT_EXEC: # Execute script - exec_line = '' - if SCRIPT_INFO.script.userdir: - exec_line = bsys.join(Blender.Get('uscriptsdir'), SCRIPT_INFO.script.fname) - else: - exec_line = bsys.join(Blender.Get('scriptsdir'), SCRIPT_INFO.script.fname) - - Blender.Run(exec_line) - -keepon = True -FMODE = False # called by Blender.ShowHelp(name) API function ? - -KEYNAME = '__help_browser' -rd = Registry.GetKey(KEYNAME) -if rd: - rdscript = rd['script'] - keepon = False - Registry.RemoveKey(KEYNAME) - for group in AllGroups: - for script in group.get_scripts(): - if rdscript == script.fname: - parseit = parse_help_info(script) - if parseit == True: - keepon = True - SCREEN = SCRIPT_SCREEN - BEVT_LINK = range(20, len(SCRIPT_INFO.d['__url__']) + 20) - BEVT_EMAIL = range(50, len(SCRIPT_INFO.d['__email__']) + 50) - FMODE = True - elif parseit == False: - Draw.PupMenu("ERROR: script doesn't have proper help data") - break - -if not keepon: - Draw.PupMenu("ERROR: couldn't find script") -else: - Draw.Register(gui, event, button_event) diff --git a/release/scripts/hotkeys.py b/release/scripts/hotkeys.py deleted file mode 100644 index 187cba964bc..00000000000 --- a/release/scripts/hotkeys.py +++ /dev/null @@ -1,944 +0,0 @@ -#!BPY -# coding: utf-8 -""" Registration info for Blender menus: -Name: 'HotKey and MouseAction Reference' -Blender: 242 -Group: 'Help' -Tip: 'All the hotkeys/short keys' -""" - -__author__ = "Jean-Michel Soler (jms)" -__url__ = ("blender", "blenderartist", -"Script's homepage, http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_hotkeyscript.htm", -"Communicate problems and errors, http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender") -__version__ = "21/01/2007" - -__bpydoc__ = """\ -This script is a reference about all hotkeys and mouse actions in Blender. - -Usage: - -Open the script from the Help menu and select group of keys to browse. - -Notes:<br> - Additional entries in the database (c) 2004 by Bart. - Additional entries in the database for blender 2.37 --> 2.43 (c) 2003-2007/01 by jms. - -""" - -#------------------------ -# Hotkeys script -# (c) jm soler (2003-->01/2007) -# ----------------------- -# Page officielle : -# http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_hotkeyscript.htm -# Communiquer les problemes et les erreurs sur: -# http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender -#--------------------------------------------- -# ce script est proposé sous licence GPL pour etre associe -# a la distribution de Blender 2.33 et suivant -# -------------------------------------------------------------------------- -# this script is released under GPL licence -# for the Blender 2.33 scripts package -# -------------------------------------------------------------------------- -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Script copyright (C) 2003, 2004: Jean-Michel Soler -# Additionnal entries in the original data base (c) 2004 by Bart (bart@neeneenee.de) -# -# 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 ***** -# -------------------------------------------------------------------------- - -import Blender -from Blender.Draw import * -from Blender.BGL import * - -# INTERNATIONAL={0:'English','1':'French'} -# LANGUAGE=0 - -hotkeys={ -'Search ':[['', '']], -'Specials 1 ':[ -[',', 'Set Bounding Box rotation scaling pivot'], -['Ctrl-,', 'Set Median Point rotation scaling pivot'], -['.', 'Set 3D cursor as rotation scaling pivot'], -['.', 'Outliner : to get the current active data in center of view'], -['Ctrl-.', 'Set Individual Object Centers as rotation scaling pivot'], -['~', 'Display all layers (German keys: ö,french keyboard: ù)'], -['Shift-~', 'Display all/previous layers (German keys: Shift-ö, french keyboard: shift-ù)'], -['ENTER', 'Outliner : to open a subtree, works on entire item line. '], -['HOME', 'Outliner : to show the entire Object hierarchy. '], -['SHIFT+BACKSPACE',' Text edit mode: Clear text '], -['SPACE', 'Popup menu'], -['SPACE', '3D View: camera selected'], -['Ctrl-SPACE', 'Manipulator (transform widget) Menu'], -['TAB', 'Enter/exit Edit Mode'], -['TAB', 'Edit Mode and Numerical Edit (see N key) : move to next input value'], -['TAB', 'Sequencer: Edit meta strip'], -['TAB', 'IPO: Edit selected'], -['TAB', 'Text Editor : indent'], -['TAB', 'NODE window : Edit group'], #243 -['Shift-TAB', 'Text Editor : unindent'], -['Shift-TAB', 'Edit Mode: Toggle snaping'], -['Ctrl-TAB', 'ARMATURE : Enter/exit Pose Mode'], -['Ctrl-TAB','MESH : all views, enter exit weight paint mode.'], -['Shift-TAB', 'Edit Mode : Enter Object Mode'], -['Ctrl-Open menu /', ''], -['Ctrl-Load Image', 'Opens a thumbnail browser instead of file browser for images'], -['.', '...'] -], - -'Mouse ':[ -['Actions:', ''], -['LMB', '3D View: Set 3D Cursor'], -['LMB', '3D View: camera selected'], -['LMB drag', 'Border select circle: add to selection'], -['LMB hold down', 'Popup menu'], -['LMB hold down drag', 'Gesture'], -['Ctrl-LMB', 'IPO: Add key'], -['Ctrl-LMB', '3D View: OBJECT or EDIT mode, select with the Lasso tool'], -['Ctrl-LMB', '3D View: ARMATURE EDIT mode, add a new bone to the selected end '], -['Shift-LMB','MANIPULATOR (transform widget): select the axe to remove in the current'], -['Shift-LMB','MANIPULATOR transformation ( if there is a problem with small step adjustment'], -['Shift-LMB','MANIPULATOR first select the axe or axes with LBM alone)'], -['Shift-LMB', 'Outliner : Hold Shift while clicking on a triangle arrow to open/close the subtree below'], -['MMB', 'Rotate'], -['Ctrl-MMB', 'Zoom view'], -['Ctrl-LMB', 'Outliner : Hold CTRL while clicking on a name allows you to edit a name.'], -['Ctrl-LMB', 'Outliner : This works for all visualized data, including bones or vertex groups,'], -['Ctrl-LMB', 'Outliner : but not for \'nameless\' items that draw the links to Hooks, Deform '], -['Ctrl-LMB', 'Outliner : Groups or Constraints.'], -['Shift-MMB', 'Move view'], -['RMB', 'Select'], -['RMB drag', 'Border select circle: subtract from selection'], -['RMB hold down', 'Popup menu'], -['Alt-RMB', 'Object Mode :Select but in a displayed list of objects located under the mouse cursor'], -['Alt-RMB', 'Edit Mode: Select EDGES LOOP '], -['Alt-Ctrl-RMB', 'Edit Mode: Select FACES LOOP'], -['Alt-Ctrl-RMB', 'UV Image Editor: Select face'], -['Shift-RMB', 'Add/subtract to/from selection'], -['Wheel', 'Zoom view'], -['Transformations:', ''], -['Drag+Ctrl', 'Step adjustment'], -['Drag+Ctrl-Shift', 'Small step adjustment (Transform Widget : first select the axe or axes with LBM alone)'], -['Drag+Shift', 'Fine adjustment (Transform Widget : first select the axe or axes with LBM alone)'], -['LMB', 'Confirm transformation'], -['MMB', 'Toggle optional transform feature'], -['RMB', 'Abort transformation'], -['LMB', 'Grease Pencil: when "Draw Mode On", draw new stroke'], -['RMB', 'Grease Pencil: when "Draw Mode On", eraser tool for stroke segments'], -['Shift-LMB', 'Grease Pencil: draw new stroke'], -['Alt-RMB', 'Grease Pencil: eraser tool for stroke segments'], -['.', '...'] -], - -'F-Keys ':[ -['F1', 'Open File'], -['Shift-F1', 'Library Data Select'], -['F2', 'Save File'], -['Shift-F2', 'Export DXF'], -['Ctrl-F2', 'Save/export in vrml 1.0 format' ], -['F3', 'Save image'], -['Ctrl-F3', 'Save image : dump 3d view'], -['Ctrl-Shift-F3', 'Save image : dump screen'], -['F4', 'Logic Window (may change)'], -['Shift-F4', 'Object manager Data Select '], -['F5', 'Material Window'], -['Shift-F5', '3D Window'], -['F6', 'Texture Window'], -['Shift-F6', 'IPO Window'], -['F7', 'Object Window'], -['Shift-F7', 'Buttons Window'], -['F8', 'World Window'], -['Shift-F8', 'Video Sequencer Window'], -['F9', 'Edit Mode Window'], -['Shift-F9', 'OOP Window'], -['Alt-Shift-F9', 'OutLiner Window'], -['F10', 'Render Window'], -['Shift-F10', 'UV Image Editor'], -['F11', 'Recall the last rendered image'], -['Shift-F11', 'Text Editor'], -['ctrl-F11', 'replay the last rendered animation'], -['F12', 'Render current Scene'], -['Ctrl-F12', 'Render animation'], -['Ctrl-Shift-F12', 'NLA Editor'], -['Shift-F12', 'Action Editor'], -['Shift-F12', 'Action Editor'], -['.', '...'] -], - -'Numbers ':[ -['1..2..0-=', 'Show layer 1..2..12'], -['1..2..0-=', 'Edit Mode with Size, Grab, rotate tools : enter value'], -['Alt-1..2..0', 'Show layer 11..12..20'], -['Shift-1..2..0', 'Toggle layer 1..2..12'], -['Ctrl-1..4', 'Object/Edit Mode : change subsurf level to the selected value'], -['Shift-ALT-...', 'Toggle layer 11..12..20'], -['Crtl-Shift-ALT-3', 'Edit Mode & Face Mode : Triangle faces'], -['Crtl-Shift-ALT-4', 'Edit Mode & Face Mode : Quad faces'], -['Crtl-Shift-ALT-5', 'Edit Mode & Face Mode : Non quad or triangle faces'], -['.', '...'] -], - -'Numpad ':[ -['Numpad DEL', 'Zoom on object'], -['Numpad /', 'Local view on object (hide others)'], -['Numpad *', 'Rotate view to objects local axes'], -['Numpad +', 'Zoom in (works everywhere)'], -['Numpad -', 'OutLiner window, Collapse one level of the hierarchy'], -['Alt-Numpad +', 'Proportional vertex Edit Mode: Increase range of influence'], -['Ctrl-Numpad +', 'Edit Mode: Select More vertices'], -['Numpad -', 'Zoom out (works everywhere)'], -['Numpad +', 'OutLiner window, Expand one level of the hierarchy'], -['Alt-Numpad -', 'Proportional vertex Edit Mode: Decrease range of influence'], -['Ctrl-Numpad +', 'Edit Mode: Select Less vertices'], -['Numpad 0', 'Set Camera view'], -['Ctrl-Numpad 0', 'Set active object as camera'], -['Alt-Numbad 0', 'Restore old camera'], -['Ctrl-Alt-Numpad 0', 'Align active camera to view'], -['Numpad 1', 'Front view'], -['Ctrl-Numpad 1', 'Back view'], -['Numpad 3', 'Right view'], -['Ctrl-Numpad 3', 'Left view'], -['Numpad 7', 'Top view'], -['Ctrl-Numpad 7', 'Bottom view '], -['Numpad 5', 'Toggle orthogonal/perspective view'], -['Numpad 9', 'Redraw view'], -['Numpad 4', 'Rotate view left'], -['ctrl-Shift-Numpad 4', 'Previous Screen'], -['Numpad 6', 'Rotate view right'], -['ctrl-Shift-Numpad 6', 'Next Screen'], -['Numpad 8', 'Rotate view up'], -['Numpad 2', 'Rotate view down'], -['.', '...'] -], - -'Arrows ':[ -['Home/Pos1', 'View all',''], -['Home', 'OutLiner Windows, Show hierarchy'], -['PgUp', 'Edit Mode and Proportionnal Editing Tools, increase influence'], -['PgUp', 'Strip Editor, Move Down'], -['PgUp', 'TimeLine: Jump to next marker'], -['PgUp', 'IPO: Select next keyframe'], -['Ctrl-PgUp', 'IPO: Select and jump to next keyframe'], -['Ctrl-PgUn', 'TimeLine: Jump to next key'], -['PgDn', 'Edit Mode and Proportionnal Editing Tools, decrease influence'], -['PgDn', 'Strip Editor, Move Up'], -['PgDn', 'TimeLine: Jump to prev marker'], -['PgDn', 'IPO: Select previous keyframe'], -['Ctrl-PgDn', 'IPO: Select and jump to previous keyframe'], -['Ctrl-PgDn', 'TimeLine: Jump to prev key'], -['Left', 'One frame backwards'], -['Right', 'One frame forwards'], -['Down', '10 frames backwards'], -['Up', '10 frames forwards'], -['Alt-Down', 'Blender in Window mode'], -['Alt-Up', 'Blender in Fullscreen mode'], -['Ctrl-Left', 'Previous screen'], -['Ctrl-Right', 'Next screen'], -['Ctrl-Down', 'Maximize window toggle'], -['Ctrl-Up', 'Maximize window toggle'], -['Shift-Arrow', 'Toggle first frame/ last frame'], -['.', '...'] -], - -'Letters ':[ -{ -"A":[ -['A', 'Select all/Deselect all'], -['A', 'Outliner : Select all/Deselect all'], -['A', 'Ipo Editor : Object mode, Select all/Deselect all displayed Curves'], #243 -['A', 'Ipo Editor : Edit mode, Select all/Deselect all vertices'], #243 -['A', 'Render window (F12) : Display alpha plane'], -['Alt-A', 'Play animation in current window'], -['Ctrl-A', 'Apply objects size/rotation to object data'], -['Ctrl-A', 'Text Editor: Select all'], -['Ctrl-ALT-A', '3D-View: Armature Edit mode, align selected bones to active bone'], -['Shift-A', 'Sequencer: Add menu'], -['Shift-A', '3D-View: Add menu'], -['Shift-A', 'Sculpt Mode: Keep the brush center anchored to the initial location'], -['Shift-ALT-A', 'Play animation in all windows'], -['Shift-CTRL-A', 'Apply lattice / Make dupliverts real'], -['Shift-CTRL-A', 'Apply Deform '], -['.', '...'] -], - -"B":[ -['B', 'Border select'], -['BB', 'Circle select'], -['Alt-B', 'Object Mode: Select visible view section in 3D space'], -['Shift-B', 'Set render border (in active camera view)'], -['Ctrl-Alt-B', 'Object Mode: in 3D view, Bake (on an image in the uv editor window) the selected Meshes'], #243 -['Ctrl-Alt-B', 'Object Mode: in 3D view, Bake Full render of selected Meshes'], #243 -['Ctrl-Alt-B', 'Object Mode: in 3D view, Bake Ambient Occlusion of selected Meshes'], #243 -['Ctrl-Alt-B', 'Object Mode: in 3D view, Bake Normals of the selected Meshes'], #243 -['Ctrl-Alt-B', 'Object Mode: in 3D view, Bake Texture Only of selected Meshes'], #243 -['.', '...'] -], - -"C":[ -['C', 'Center view on cursor'], -['C', 'UV Image Editor: Active Face Select toggle'], -['C', 'Sequencer: Change content of the strip '], #243 -['C', 'IPO: Snap current frame to selected key'], -['C', 'TimeLine: Center View'], -['C', 'File Selector : Copy file'], -['C', 'NODE window : Show cyclic referencies'], #243 -['Alt-C', 'Object Mode: Convert menu'], -['Alt-C', 'Text Editor: Copy '], -['Ctrl-Alt-C', 'Object Mode : Add Constraint'], -['Ctrl-Shift-C', 'Text Editor: Copy selection to clipboard'], -['Ctrl-C', 'Copy menu (Copy properties of active to selected objects)'], -['Ctrl-C', 'UV Image Editor: Stick UVs to mesh vertex'], -['Ctrl-C','ARMATURE : posemode, Copy pose attributes'], -['Ctrl-Alt-C',' ARMATURE : posemode, add constraint to new empty object.'], -['Shift-C', 'Center and zoom view on selected objects'], -['Shift-C', 'UV Image Editor: Stick local UVs to mesh vertex'], -['.', '...'] -], - -"D":[ -['D', 'Set 3d draw mode'], -['Alt-D', 'Object Mode: Create new instance of object'], -['Ctrl-D', 'Display alpha of image texture as wire'], -['Ctrl-D', 'Text Editor : uncomment'], -['Shift-D', 'Create full copy of object'], -['Shift-D', 'NODE window : duplicate'], #243 -['CTRL-SHIFT-D', 'NLA editor : Duplicate markers'], -['CTRL-SHIFT-D', 'Action editor : Duplicate markers'], -['CTRL-SHIFT-D', 'IPO editor : Duplicate markers'], -['.', '...'] -], - -"E":[ -['E', 'Edit Mode: Extrude'], -['E', 'UV Image Editor: LSCM Unwrap'], -['E', 'TimeLine: Set current frame as End '], -['E', 'NODE window : Execute composite'], #243 -['ER', 'Edit Mode: Extrude Rotate'], -['ES', 'Edit Mode: Extrude Scale'], -['ESX', 'Edit Mode: Extrude Scale X axis'], -['ESY', 'Edit Mode: Extrude Scale Y axis'], -['ESZ', 'Edit Mode: Extrude Scale Z axis'], -['EX', 'Edit Mode: Extrude along X axis'], -['EY', 'Edit Mode: Extrude along Y axis'], -['EZ', 'Edit Mode: Extrude along Z axis'], -['Alt-E', 'Edit Mode: exit Edit Mode'], -['Ctrl-E', 'Edit Mode: Edge Specials menu'], -['Ctrl-E', 'Edit Mode: Edge Specials menu, Mark seams'], -['Ctrl-E', 'Edit Mode: Edge Specials menu, Clear seams'], -['Ctrl-E', 'Edit Mode: Edge Specials menu, Rotate Edge CW'], -['Ctrl-E', 'Edit Mode: Edge Specials menu, Rotate Edge CCW'], -['Ctrl-E', 'Edit Mode: Edge Specials menu, Loop Cut'], -['Ctrl-E', 'Edit Mode: Edge Specials menu, Edge Slide'], -['Shift-E', 'Edit Mode: SubSurf Edge Sharpness'], -['.', '...'] -], - -"F":[ -['F', 'Edit mode: Make edge/face'], -['F', 'Sequencer: Set Filter Y'], -['F', 'Object Mode: UV/Face Select mode'], -['Alt-F', 'Edit Mode: Beautify fill'], -['Alt-F,','Text editor : find again '], -['Alt-Ctrl-F,','Text editor : find '], -['Ctrl-F', 'Object Mode: Sort faces in Z direction'], -['Ctrl-F', 'Edit Mode: Flip triangle edges'], -['Shift-F', 'Edit Mode: Fill with triangles'], -['Shift-F', 'Object Mode: fly mode (see header for fly mode keys)'], -['.', '...'] -], - -"G":[ -['G', 'Grab (move)'], -['G', 'Timeline : Grab (move) Marker'], -['Alt-G', 'Clear location (this does only make sense in Object mode)'], -['Alt-G', 'NODE window : ungroup'], #243 -['Shift-ALT-G', 'Object mode: Remove selected objects from group'], -['Ctrl-G', 'NODE window : group'], #243 -['Ctrl-G', 'Add selected objects to group'], -['Ctrl-G', 'IPO editor, Grab/move marker'], -['Ctrl-Alt-G', 'MANIPULATOR (transform widget): set in Grab Mode'], -['Shift-G', 'Object mode: Selected Group menu'], -['Shift-G', 'Object mode: Selected Group menu 1, Children'], -['Shift-G', 'Object mode: Selected Group menu 2, Immediate Children'], -['Shift-G', 'Object mode: Selected Group menu 3, Parent'], -['Shift-G', 'Object mode: Selected Group menu 4, Sibling'], -['Shift-G', 'Object mode: Selected Group menu 5, Object of same type'], -['Shift-G', 'Object mode: Selected Group menu 6, Object in same shared layers'], -['Shift-G', 'Object mode: Selected Group menu 7, Objects in same group'], -['.', '...'] -], - -"H":[ -['H', 'Hide selected vertices/faces'], -['H', 'Curves: Set handle type'], -['H', 'Action editor: Handle type aligned'], -['H', 'Action editor: Handle type free'], -['H', 'NODE window : hide/unhide'], #243 -['Alt-H', 'Edit Mode : Show Hidden vertices/faces'], -['Shift-H', 'Curves: Automatic handle calculation'], -['Shift-H', 'Action editor: Handle type auto'], -['Shift-H', 'Edit Mode : Hide deselected vertices/faces'], -['Ctrl-H', 'Edit Mode : Add a hook on selected points or show the hook menu .'], -['.', '...'] -], - -"I":[ -['I', 'Insert Keyframe menu'], -['Alt-I','Delete Keyframe menu'], -['Ctrl-I','Select Inverse'], -['Shift-I','ARMATURE : add IK constraint'], -['Ctrl-Alt-I','ARMATURE : posemode, remove IK constraints.'], -['.', '...'] -], - -"J":[ -['J', 'IPO: Join menu'], -['J', 'Mesh: Join all adjacent triangles to quads'], -['J', 'Render Window: Swap render buffer'], -['Alt-J,','Text editor : Jump '], -['Ctrl-J', 'Join selected objects'], -['Ctrl-J', 'Nurbs: Add segment'], -['Ctrl-J', 'IPO: Join keyframes menu'], -['.', '...'] -], - -"K":[ -['K', '3d Window: Show keyframe positions'], -['K', 'Edit Mode: Loop/Cut menu'], -['K', 'IPO: Show keyframe positions'], -['K', 'Nurbs: Print knots'], -['K', 'VIDEO editor : cut at current frame'], #243 -['Ctrl-K', 'Make skeleton from armature'], -['Shift-K', 'Show and select all keyframes for object'], -['Shift-K', 'Edit Mode: Knife Mode select'], -['Shift-K', 'UV Face Select: Clear vertex colours'], -['Shift-K', 'Vertex Paint: All vertex colours are erased; they are changed to the current drawing colour.'], -['.', '...'] -], - -"L":[ -['L', 'Make local menu'], -['L', 'Edit Mode: Select linked vertices (near mouse pointer)'], -['L', 'NODE window: Select linked from '], #243 -['L', 'OOPS window: Select linked objects'], -['L', 'UV Face Select: Select linked faces'], -['Ctrl-L', 'Make links menu (for instance : to scene...)'], -['Shift-L', 'Select links menu'], -['Shift-L', 'NODE window: Select linked to '], #243 -['Ctrl-L', 'POSELIB: browse poses'], -['Shift-L', 'POSELIB: add/replace pose'], -['Ctrl-Shift-L', 'POSELIB: rename pose'], -['Alt-L', 'POSELIB: remove pose'], -['.', '...'] -], - -"M":[ -['M', 'Object mode : Move object to different layer'], -['M', 'Sequencer: Make meta strip (group) from selected strips'], -['M', 'Edit Mode: Mirros Axis menu'], -['M', 'File Selector: rename file'], -['M', 'Video Sequence Editor : Make Meta strip...'], -['M', 'NLA editor: Add marker'], -['M', 'Action editor: Add marker'], -['M', 'IPO editor: Add marker'], -['M', 'TimeLine: Add marker'], -['Alt-M', 'Edit Mode: Merge vertices menu'], -['Alt-M', 'Video Sequence Editor : Separate Meta strip...'], -['Ctrl-M', 'Object Mode: Mirros Axis menu'], -['Shift-M', 'TimeLine: Name marker'], -['Shift-M', 'IPO editor : Name marker'], -['Shift-M', 'NLA editor : Name marker'], -['Shift-M', 'Actions editor : Name marker'], -['.', '...'] -], - -"N":[ -['N', 'Transform Properties panel'] , -['N', 'OOPS window: Rename object'], -['N', 'VIDEO SEQUENCE editor : display strip properties '], #243 -['Alt-N', 'Text Editor : New text '], -['Ctrl-N', 'Armature: Recalculate bone roll angles'] , -['Ctrl-N', 'Edit Mode: Recalculate normals to outside'] , -['Ctrl-Shift-N', 'Edit Mode: Recalculate normals to inside'], -['.', '...'] -], - -"O":[ -['O', 'Edit Mode/UV Image Editor: Toggle proportional vertex editing'], -['O', 'IPO editor: Clean ipo curves (beware to the thresold needed value)'], #243 -['Alt-O', 'Clear object origin'], -['Alt-O', 'Edit mode, 3dview with prop-edit-mode, enables/disables connected'], -['Alt-O', 'Text Editor : Open file '], -['Ctrl-O', 'Open a panel with the ten most recent projets files'], #243 -['Shift-O', 'Proportional vertex Edit Mode: Toggle smooth/steep falloff'], -['Shift-O', 'Object Mode: Add a subsurf modifier to the selected mesh'], -['Shift-O', 'IPO editor: Smooth ipo curves'], #243 -['.', '...'] -], - -"P":[ -['P', 'Object Mode: Start realtime engine'], -['P', 'Edit mode: Seperate vertices to new object'], -['Shift-P', 'Edit mode: Push-Pull'], -['Shift-P', 'Object mode: Add a preview window in the D window'], -['P', 'UV Image Editor: Pin selected vertices. Pinned vertices will stay in place on the UV editor when executing an LSCM unwrap.'], -['Alt-P', 'Clear parent relationship'], -['Alt-P', 'UV Image Editor: Unpin UVs'], -['Alt-P', 'Text Editor : Run current script '], -['Ctrl-P', 'Make active object parent of selected object'], -['Ctrl-Shift-P', 'Make active object parent of selected object without inverse'], -['Ctrl-P', 'Edit mode: Make active vertex parent of selected object'], -['Ctrl-P', 'ARMATURE : editmode, make bone parent.'], -['Ctrl-Alt-P', 'ARMATURE: edimode, separate bones to new object'], -['.', '...'] -], - -"Q":[['Ctrl-Q', 'Quit'], - ['.', '...'] - ], - -"R":[ -['R', 'FileSelector : remove file'], -['R', 'Rotate'], -['R', 'IPO: Record mouse movement as IPO curve'], -['R', 'UV Face Select: Rotate menu uv coords or vertex colour'], -['R', 'NODE window : read saved render result'], #243 -['R', 'SEQUENCER window : re-assign entries to another strip '], #243 -['RX', 'Rotate around X axis'], -['RXX', "Rotate around object's local X axis"], -['RY', 'Rotate around Y axis'], -['RYY', "Rotate around object's local Y axis"], -['RZ', 'Rotate around Z axis'], -['RZZ', "Rotate around object's local Z axis"], -['Alt-R', 'Clear object rotation'], -['Alt-R', 'Text editor : reopen text.'], -['Ctrl-R', 'Edit Mode: Knife, cut selected edges, accept left mouse/ cancel right mouse'], -['Ctrl-Alt-R', 'MANIPULATOR (transform widget): set in Rotate Mode'], -['Shift-R', 'Edit Mode: select Face Loop'], -['Shift-R', 'Nurbs: Select row'], -['.', '...'] -], - -"S":[ -['S', 'Scale'] , -['S', 'TimeLine: Set Start'], -['SX', 'Flip around X axis'] , -['SY', 'Flip around Y axis'] , -['SZ', 'Flip around Z axis'] , -['SXX', 'Flip around X axis and show axis'] , -['SYY', 'Flip around Y axis and show axis'] , -['SZZ', 'Flip around Z axis and show axis'] , -['Alt-S', 'Edit mode: Shrink/fatten (Scale along vertex normals)'] , -['Alt-S', 'Text Editor : Save the current text to file '], -['Alt-S',' ARMATURE : posemode editmode: Scale envalope.'], -['Ctrl-Shift-S', 'Edit mode: To Sphere'] , -['Ctrl-Alt-Shift-S', 'Edit mode: Shear'] , -['Alt-S', 'Clear object size'] , -['Ctrl-S', 'Edit mode: Shear'] , -['Alt-Shift-S,','Text editor : Select the line '], -['Ctrl-Alt-G', 'MANIPULATOR (transform widget): set in Size Mode'], -['Shift-S', 'Cursor/Grid snap menu'], -['Shift-S', 'Sculpt Mode: Smooth Stroke.'], -['Shift-S+1', 'VIDEO SEQUENCE editor : jump to the current frame '], -['.', '...'] -], - -"T":[ -['T', 'Adjust texture space'], -['T', 'Edit mode: Flip 3d curve'], -['T', 'IPO: Menu Change IPO type, 1 Constant'], -['T', 'IPO: Menu Change IPO type, 2 Linear'], -['T', 'IPO: Menu Change IPO type, 3 Bezier'], -['T', 'TimeLine: Show second'], -['T', 'VIDEO SEQUENCE editor : toggle between show second andd show frame'], #243 -['Alt-T', 'Clear tracking of object'], -['Ctrl-T', 'Make selected object track active object'], -['Ctrl-T', 'Edit Mode: Convert to triangles'], -['Ctrl-Alt-T', 'Benchmark'], -['.', '...'] -], - -"U":[ -['U', 'Make single user menu (for import completly linked object to another scene for instance) '] , -['U', '3D View: Make Single user Menu'] , -['U', 'UV Face Select: Automatic UV calculation menu'] , -['U', 'Vertex-/Weightpaint mode: Undo'] , -['Ctrl-U', 'Save current state as user default'], -['Shift-U', 'Edit Mode: Redo Menu'], -['Alt-U', 'Edit Mode & Object Mode: Undo Menu'], -['.', '...'] -], - -"V":[ -['V', 'Curves/Nurbs: Vector handle'], -['V', 'Edit Mode : Rip selected vertices'], -['V', 'Vertexpaint mode'], -['V', 'UV Image Editor: Stitch UVs'], -['Ctrl-V',' UV Image Editor: maximize stretch.'], -['V', 'Action editor: Vector'], -['Alt-V', "Scale object to match image texture's aspect ratio"], -['Alt-V', 'Text Editor : Paste '], -['Alt-Shift-V', 'Text Editor : View menu'], -['Alt-Shift-V', 'Text Editor : View menu 1, Top of the file '], -['Alt-Shift-V', 'Text Editor : View menu 2, Bottom of the file '], -['Alt-Shift-V', 'Text Editor : View menu 3, PageUp'], -['Alt-Shift-V', 'Text Editor : View menu 4, PageDown'], -['Ctrl-Shift-V', 'Text Editor: Paste from clipboard'], -['Shift-V', 'Edit mode: Align view to selected vertices'], -['Shift-V', 'UV Image Editor: Limited Stitch UVs popup'], -['.', '...'] -], - -"W":[ -['W', 'Edit Mode: Specials menu'], -['W', 'Edit Mode: Specials menu, ARMATURE 1 Subdivide'], -['W', 'Edit Mode: Specials menu, ARMATURE 2 Subdivide Multi'], -['W', 'Edit Mode: Specials menu, ARMATURE 3 Switch Direction'], -['W', 'Edit Mode: Specials menu, ARMATURE 4 Flip Left-Right Name'], -['W', 'Edit Mode: Specials menu, ARMATURE 5 AutoName Left-Right'], -['W', 'Edit Mode: Specials menu, ARMATURE 6 AutoName Front-Back'], -['W', 'Edit Mode: Specials menu, ARMATURE 7 AutoName Top-Bottom'], -['W', 'Edit Mode: Specials menu, CURVE 1 Subdivide'], -['W', 'Edit Mode: Specials menu, CURVE 2 Swich Direction'], -['W', 'Edit Mode: Specials menu, CURVE 3 Set Goal Weight'], -['W', 'Edit Mode: Specials menu, CURVE 4 Set Radius'], -['W', 'Edit Mode: Specials menu, CURVE 5 Smooth'], -['W', 'Edit Mode: Specials menu, CURVE 6 Smooth Radius'], -['W', 'Edit Mode: Specials menu, MESH 1 Subdivide'], -['W', 'Edit Mode: Specials menu, MESH 2 Subdivide Multi'], -['W', 'Edit Mode: Specials menu, MESH 3 Subdivide Multi Fractal'], -['W', 'Edit Mode: Specials menu, MESH 4 Subdivide Smooth'], -['W', 'Edit Mode: Specials menu, MESH 5 Merge'], -['W', 'Edit Mode: Specials menu, MESH 6 Remove Double'], -['W', 'Edit Mode: Specials menu, MESH 7 Hide'], -['W', 'Edit Mode: Specials menu, MESH 8 Reveal'], -['W', 'Edit Mode: Specials menu, MESH 9 Select Swap'], -['W', 'Edit Mode: Specials menu, MESH 10 Flip Normal'], -['W', 'Edit Mode: Specials menu, MESH 11 Smooth'], -['W', 'Edit Mode: Specials menu, MESH 12 Bevel'], -['W', 'Edit Mode: Specials menu, MESH 13 Set Smooth'], -['W', 'Edit Mode : Specials menu, MESH 14 Set Solid'], -['W', 'Object Mode : on MESH objects, Boolean Tools menu'], -['W', 'Object Mode : on MESH objects, Boolean Tools 1 Intersect'], -['W', 'Object Mode : on MESH objects, Boolean Tools 2 union'], -['W', 'Object Mode : on MESH objects, Boolean Tools 3 difference'], -['W', 'Object Mode : on MESH objects, Boolean Tools 4 Add an intersect Modifier'], -['W', 'Object Mode : on MESH objects, Boolean Tools 5 Add an union Modifier'], -['W', 'Object Mode : on MESH objects, Boolean Tools 6 Add a difference Modifier'], -['W', 'Object mode : on TEXT object, Split characters, a new TEXT object by character in the selected string '], -['W', 'UV Image Editor: Weld/Align'], -['WX', 'UV Image Editor: Weld/Align X axis'], -['WY', 'UV Image Editor: Weld/Align Y axis'], -['Ctrl-W', 'Save current file'] , -['Shift-W', 'Warp/bend selected vertices around cursor'], -['.', '...'] - ], - -"X":[ -['X', 'Delete menu'] , -['X', 'TimeLine : Remove marker'], -['X', 'NLA : Remove marker'], -['X', 'IPO : Remove marker'], -['X', 'NODE window : delete'], #243 -['Alt-X', 'Text Editor : Cut '], -['Alt-X', 'Grease Pencil: Delete menu'], -['Ctrl-X', 'Restore default state (Erase all)'], -['.', '...'] - ], - -"Y":[ -['Y', 'Edit Mode & Mesh : Split selected vertices/faces from the rest'], -['Ctrl-Y', 'Object Mode : Redo'], -['.', '...'] -], - -"Z":[ -['Z', 'Render Window: 200% zoom from mouse position'], -['Z', 'Switch 3d draw type : solide/ wireframe (see also D)'], -['Alt-Z', 'Switch 3d draw type : solid / textured (see also D)'], -['Alt-Z,','Text editor : undo '], -['Ctrl-Z', 'Object Mode : Undo'], -['Ctrl-Z,','Text editor : undo '], -['Ctrl-Shift-Z,','Text editor : Redo '], -['Shift-Z', 'Switch 3d draw type : shaded / wireframe (see also D)'], -['.', '...'] -]}]} - -up=128 -down=129 -UP=0 -SEARCH=131 -OLDSEARCHLINE='' -SEARCHLINE=Create('') -LINE=130 -FINDED=[] -LEN=0 - -for k in hotkeys.keys(): - hotkeys[k].append(Create(0)) - -for k in hotkeys['Letters '][0]: - hotkeys['Letters '][0][k].append(Create(0)) - -hotL=hotkeys['Letters '][0].keys() -hotL.sort() - -hot=hotkeys.keys() -hot.sort() - -def searchfor(SEARCHLINE): - global hotkeys, hot - FINDLIST=[] - for k in hot: - if k not in ['Letters ', 'Search '] : - for l in hotkeys[k][:-1]: - #print 'k, l : ', k, l, l[1] - if l[1].upper().find(SEARCHLINE.upper())!=-1: - FINDLIST.append(l) - - elif k == 'Letters ': - for l in hotL : - for l0 in hotkeys['Letters '][0][l][:-1]: - #print 'k, l : ',l, k, l0 - if l0[1].upper().find(SEARCHLINE.upper())!=-1: - FINDLIST.append(l0) - #print 'FINDLIST',FINDLIST - FINDLIST.append(['Find list','Entry']) - return FINDLIST - - -glCr=glRasterPos2d -glCl3=glColor3f -glCl4=glColor4f -glRct=glRectf - -cf=[0.95,0.95,0.9,0.0] -c1=[0.95,0.95,0.9,0.0] -c=cf -r=[0,0,0,0] - -def trace_rectangle4(r,c): - glCl4(c[0],c[1],c[2],c[3]) - glRct(r[0],r[1],r[2],r[3]) - -def trace_rectangle3(r,c,c1): - glCl3(c[0],c[1],c[2]) - glRct(r[0],r[1],r[2],r[3]) - glCl3(c1[0],c1[1],c1[2]) - -def draw(): - global r,c,c1,hotkeys, hot, hotL, up, down, UP, SEARCH, SEARCHLINE,LINE - global OLDSEARCHLINE, FINDED, SCROLL, LEN - size=Buffer(GL_FLOAT, 4) - glGetFloatv(GL_SCISSOR_BOX, size) - size= size.list - - for s in [0,1,2,3]: size[s]=int(size[s]) - - c=[0.75,0.75,0.75,0] - c1=[0.6,0.6,0.6,0] - - r=[0,size[3],size[2],0] - trace_rectangle4(r,c) - - c=[0.64,0.64,0.64,0] - c1=[0.95,0.95,0.9,0.0] - - r=[0,size[3],size[2],size[3]-40] - trace_rectangle4(r,c) - - c1=[0.7,0.7,0.9,0.0] - c=[0.2,0.2,0.4,0.0] - c2=[0.71,0.71,0.71,0.0] - - glColor3f(1, 1, 1) - glRasterPos2f(42, size[3]-25) - - Text("HotKey and MouseAction Reference") - - l=0 - listed=0 - Llisted=0 - size[3]=size[3]-18 - - BeginAlign() - for i, k in enumerate(hot): - hotkeys[k][-1]=Toggle(k, i+10, 78*i, size[3]-(47), 78, 24, hotkeys[k][-1].val ) - l+=len(k) - if hotkeys[k][-1].val==1.0: - listed= i - EndAlign() - l=0 - size[3]=size[3]-4 - - if hot[listed]!='Letters ' and hot[listed]!='Search ' : - size[3]=size[3]-8 - SCROLL=size[3]/21 - END=-1 - if SCROLL < len(hotkeys[hot[listed]][:-1]): - BeginAlign() - Button('/\\',up,4,size[3]+8,20,14,'Scroll up') - Button('\\/',down,4,size[3]-8,20,14,'Scroll down') - EndAlign() - if (SCROLL+UP)<len(hotkeys[hot[listed]][:-1]): - END=(UP+SCROLL) - else: - END=-1 - UP=len(hotkeys[hot[listed]][:-1])-SCROLL - else : - UP=0 - for n in hotkeys[hot[listed]][:-1][UP:END]: - if l%2==0: - r=[0,size[3]-(21*l+66), - size[2], size[3]-(21*l+43)] - trace_rectangle4(r,c2) - glColor3f(0,0,0) - glRasterPos2f(4+8, size[3]-(58+21*l)) - Text(n[0]) - glRasterPos2f(4+8*15, size[3]-(58+21*l)) - Text(' : '+n[1]) - l+=1 - - elif hot[listed]=='Search ' : - r=[0,size[3]-70, - size[2], size[3]-44] - trace_rectangle4(r,c2) - SEARCHLINE=String(' ', LINE, 42, size[3]-68,200,18,SEARCHLINE.val, 256,'') - if len(FINDED)>0: - LEN=len(FINDED) - size[3]=size[3]-8 - SCROLL=size[3]/21 - END=-1 - - if SCROLL < len(FINDED): - BeginAlign() - Button('/\\',up,4,size[3]+8,20,14,'Scroll up') - Button('\\/',down,4,size[3]-8,20,14,'Scroll down') - EndAlign() - if (SCROLL+UP)<len(FINDED): - END=(UP+SCROLL-1) - else: - END=-1 - #UP=len(FINDED)-SCROLL - else: - UP=0 - for n in FINDED[UP:END]: - if l%2==0: - r=[0,size[3]-(21*l+66+24), - size[2], size[3]-(21*l+43+24)] - trace_rectangle4(r,c2) - glColor3f(0,0,0) - glRasterPos2f(4+8, size[3]-(58+24+21*l)) - Text(n[0]) - glRasterPos2f(4+8*15, size[3]-(58+24+21*l)) - Text(' : '+n[1]) - l+=1 - else: - BeginAlign() - for pos, k in enumerate(hotL): - hotkeys['Letters '][0][k][-1]=Toggle(k,pos+20,pos*21, size[3]-(52+18), 21, 18, hotkeys['Letters '][0][k][-1].val ) - if hotkeys['Letters '][0][k][-1].val==1.0: - Llisted=pos - EndAlign() - size[3]=size[3]-8 - SCROLL=(size[3]-88)/21 - END=-1 - if SCROLL < len(hotkeys['Letters '][0][hotL[Llisted]]): - LEN=len(hotkeys['Letters '][0][hotL[Llisted]]) - BeginAlign() - Button('/\\',up,4,size[3]+8,20,14,'Scroll up, you can use arrow or page keys too ') - Button('\\/',down,4,size[3]-8,20,14,'Scroll down, you can use arrow or page keys too ') - EndAlign() - if (UP+SCROLL)<len(hotkeys['Letters '][0][hotL[Llisted]]): - END=(UP+SCROLL) - else: - END=-1 - UP=len(hotkeys['Letters '][0][hotL[Llisted]])-SCROLL - else : - UP=0 - - for n in hotkeys['Letters '][0][hotL[Llisted]][UP:END]: - if l%2==0: - r=[4,size[3]-(21*l+92), - size[2], size[3]-(69+21*l+1)] - trace_rectangle4(r,c2) - - glColor3f(0.1, 0.1, 0.15) - glRasterPos2f(4+8, (size[3]-(88+21*l))+3) - Text(n[0]) - glRasterPos2f(4+8*15, (size[3]-(88+21*l))+3) - Text(' : '+n[1]) - l+=1 - -def event(evt, val): - global hotkeys, UP, SCROLL , LEN - if (evt== QKEY or evt== ESCKEY): - Exit() - elif val: - if (evt== PAGEUPKEY): - if (UP+SCROLL)<LEN-5: - UP+=5 - elif (evt== PAGEDOWNKEY): - if UP>4: - UP-=5 - elif (evt== UPARROWKEY): - if (UP+SCROLL)<LEN-1: - UP+=1 - elif (evt== DOWNARROWKEY): - if UP>0: - UP-=1 - Redraw() - -def bevent(evt): - global hotkeysmhot, hotL, up,down,UP, FINDED - global SEARCH, SEARCHLINE,LINE, OLDSEARCHLINE - - if (evt== 1): - Exit() - - elif 9 < evt < 20: - for i, k in enumerate(hot): - if i+10!=evt: - hotkeys[k][-1].val=0 - UP=0 - Blender.Window.Redraw() - - elif 19 < evt < 46: - for i, k in enumerate(hotL): - if i+20!=evt: - hotkeys['Letters '][0][k][-1].val=0 - UP=0 - Blender.Window.Redraw() - - elif (evt==up): - UP+=1 - Blender.Window.Redraw() - - elif (evt==down): - if UP>0: UP-=1 - Blender.Window.Redraw() - - elif (evt==LINE): - if SEARCHLINE.val!='' and SEARCHLINE.val!=OLDSEARCHLINE: - OLDSEARCHLINE=SEARCHLINE.val - FINDED=searchfor(OLDSEARCHLINE) - Blender.Window.Redraw() - -if __name__ == '__main__': - Register(draw, event, bevent) diff --git a/release/scripts/image_2d_cutout.py b/release/scripts/image_2d_cutout.py deleted file mode 100644 index 16d0805256b..00000000000 --- a/release/scripts/image_2d_cutout.py +++ /dev/null @@ -1,559 +0,0 @@ -#!BPY - -""" -Name: '2D Cutout Image Importer' -Blender: 249 -Group: 'Image' -Tooltip: 'Batch UV Map images to Planes' -""" - -__author__ = "Kevin Morgan (forTe)" -__url__ = ("Home page, http://gamulabs.freepgs.com") -__version__ = "1.2.1" -__bpydoc__ = """\ -This Script will take an image and -UV map it to a plane sharing the same width to height ratio as the image. -Import options allow for the image to be a still or sequence type image -<br><br> -Imports can be single images or whole directories of images depending on the chosen -option. -""" - -#################################################### -#Copyright (C) 2008: Kevin Morgan -#################################################### -#-------------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 3 of the License, or -#(at your option) any later version. -# -#This program is distributed in the hopes 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, see <http://www.gnu.org/licenses>. -#################################################### -#################################################### -#V1.0 -#Basic Functionality -#Published June 28, 2007 -#################################################### -#V1.1 -#Added Support for enabling viewport transparency -#Added more options to the UI for materials -#Added Proportionality code (Pixels per unit) -#Added GPL License Block -#Published June 29, 2007 -#################################################### -#V1.2 -#Added Support for Copying Existing Materials -#Import Images as Sequences -#Refreshed GUI - now with more clutter :( -#Miscellaneous and Housekeeping -#Published June 16, 2008 -#################################################### -#V1.2.1 -#Added Extend Texture Mode option at request of a user -#Published September 24, 2008 -#################################################### - -import Blender -from Blender import BGL, Draw, Image, Mesh, Material, Texture, Window -from Blender.Mathutils import * -import bpy - -# Global Constants -DIR = 0 -SINGLE = 1 -CUROFFS = 0 - -# GUI CONSTANTS -NO_EVT = 0 -SINGLE_IMG = 1 -DIRECTORY_IMG = 2 -CLR_PATH = 3 -CHG_EXT = 4 -EXIT = 5 -DO_SCRIPT = 6 - -VERSIONSTRING = '1.2.1' - -# Note the two parameter dicts could be combined, I just, liked them seperate... -# GUI Buttons Dict -GUIPARAMS = { - 'Path': Draw.Create(''), - 'ImageExt': Draw.Create(''), - 'Seq': Draw.Create(0), - 'PackImage': Draw.Create(0), - 'PPU': Draw.Create(50), - 'VPTransp': Draw.Create(1), - 'XOff': Draw.Create(0.0), - 'YOff': Draw.Create(0.0), - 'ZOff': Draw.Create(0.0), - 'CopyMat': Draw.Create(0), - 'MatId': Draw.Create(0), - 'MatCol': Draw.Create(1.0, 0.0, 0.0), - 'Ref': Draw.Create(0.8), - 'Spec': Draw.Create(0.5), - 'Hard': Draw.Create(50), - 'Alpha': Draw.Create(1.0), - 'ZTransp': Draw.Create(1), - 'Shadeless': Draw.Create(0), - 'TexChan': Draw.Create(1), - 'MPTCol': Draw.Create(1), - 'MPTAlpha': Draw.Create(1), - 'UseAlpha': Draw.Create(1), - 'CalcAlpha': Draw.Create(0), - 'ExtendMode': Draw.Create(0), - 'AutoRefresh': Draw.Create(0), - 'Cyclic': Draw.Create(0), - 'Frames': Draw.Create(100), - 'Offs': Draw.Create(0), - 'StartFr': Draw.Create(1), - 'RedrawImp': Draw.Create(0) -} - -# Script Execution Paramaters -PARAMS = { - 'ImagePaths': [], # Path to images to import - 'ImportType': SINGLE, # Import a Directory or a Single Image? - 'ImageProp': Image.Sources.STILL, # What sources for the image, still or sequence - 'PackImage': 0, # Pack the Image(s)? - 'PPU': 20, # Pixels Per Blender Unit - 'MakeTransp': 1, # Make face transparent in viewport - - 'NewMat': 1, # If true make a new material, otherwise duplicate an existing one, replacing appropriate attributes - 'MaterialId': 0, # ID to take from the Materials list upon copy - 'Materials': None, # Materials in Scene - 'MatProps': {'Col': [1.0, 0.0, 0.0], 'Shadeless': 1, 'Ref': 0.5, 'Spec': 0.5, 'Hard': 200, 'Alpha': 1.0, 'ZTransp': 1}, - - 'TexProps': {'UseAlpha': 1, 'CalcAlpha': 0, 'ExtendMode': 0}, # Texture Properties - 'TexChannel': 0, # Texture Channel - 'TexMapTo': {'Col': 1, 'Alpha': 1}, # Map to Col and/or Alpha - 'SeqProps': {'AutoRefresh': 0, 'Cyclic': 0, 'Frames': 100, 'Offs': 0, 'StartFr': 1}, - 'ObOffset': Vector(1, 0, 0) # Offset by this vector upon creation for multifile import -} - -# Get the Active Scene, of course -scn = bpy.data.scenes.active - -########################################## -# MAIN SCRIPT FUNCTIONS -########################################## - -def imgImport(imgPath): - global CUROFFS, PARAMS - ###################################### - # Load the image - ###################################### - try: - img = Image.Load(imgPath) - imgDimensions = img.getSize() # do this to ensure the data is available - except: - Blender.Draw.PupMenu('Error%t|Unsupported image format for "'+ imgPath.split('\\')[-1].split('/')[-1] +'"') - return - - if PARAMS['PackImage']: - img.pack() - name = Blender.sys.makename(imgPath, strip = 1) - - ###################################### - # Construct the mesh - ###################################### - - me = Mesh.New(name) - - # Calculate Dimensions from Image Size - dim = [float(i)/PARAMS['PPU'] for i in imgDimensions] - v = [[dim[0], dim[1], 0], [-dim[0], dim[1], 0], [-dim[0], -dim[1], 0], [dim[0], -dim[1], 0]] - me.verts.extend(v) - me.faces.extend([0, 1, 2, 3]) - - me.faces[0].image = img - me.faces[0].uv = [Vector(1.0, 1.0), Vector(0.0, 1.0), Vector(0.0, 0.0), Vector(1.0, 0.0)] - - if PARAMS['MakeTransp']: - me.faces[0].transp = Mesh.FaceTranspModes.ALPHA - - ###################################### - # Modify the Material - ###################################### - - mat = None - if not PARAMS['NewMat']: - mat = PARAMS['Materials'][PARAMS['MaterialId']].__copy__() - mat.setName(name) - else: - mat = Material.New(name) - properties = PARAMS['MatProps'] - mat.setRGBCol(properties['Col']) - mat.setRef(properties['Ref']) - mat.setSpec(properties['Spec']) - mat.setHardness(properties['Hard']) - mat.setAlpha(properties['Alpha']) - - if properties['Shadeless']: - mat.mode |= Material.Modes.SHADELESS - if properties['ZTransp']: - mat.mode |= Material.Modes.ZTRANSP - - properties = PARAMS['TexProps'] - - tex = Texture.New(name) - tex.setType('Image') - tex.setImage(img) - if properties['UseAlpha']: - tex.useAlpha = Texture.ImageFlags.USEALPHA - - if properties['CalcAlpha']: - tex.calcAlpha = Texture.ImageFlags.CALCALPHA - - if properties['ExtendMode']: - tex.setExtend('Extend') - - if PARAMS['ImageProp'] == Image.Sources.SEQUENCE: - properties = PARAMS['SeqProps'] - - img.source = PARAMS['ImageProp'] # Needs to be done here, otherwise an error with earlier getSize() - - tex.animStart = properties['StartFr'] - tex.animOffset = properties['Offs'] - tex.animFrames = properties['Frames'] - tex.autoRefresh = properties['AutoRefresh'] - tex.cyclic = properties['Cyclic'] - - texMapSetters = Texture.TexCo.UV - - # PARAMS['TexMapTo']['Col'] (and alpha) will either be 0 or 1 because its from a toggle, otherwise this line doesn't work - texChanSetters = Texture.MapTo.COL * PARAMS['TexMapTo']['Col'] | Texture.MapTo.ALPHA * PARAMS['TexMapTo']['Alpha'] - - mat.setTexture(PARAMS['TexChannel'], tex, texMapSetters, texChanSetters) - me.materials += [mat] - - ###################################### - # Object Construction - ###################################### - - ob = scn.objects.new(me, name) - p = Vector(ob.getLocation()) # Should be the origin, but just to be safe, get it - ob.setLocation((CUROFFS * PARAMS['ObOffset']) + p) - - return - -def translateParams(): - # Translates (or assigns for the most part) GUI values to those that can be read by the - # Import Function - - global GUIPARAMS, PARAMS - - if GUIPARAMS['Seq'].val and PARAMS['ImportType'] != DIR: - PARAMS['ImageProp'] = Image.Sources.SEQUENCE - - PARAMS['PackImage'] = GUIPARAMS['PackImage'].val - PARAMS['PPU'] = GUIPARAMS['PPU'].val - PARAMS['MakeTransp'] = GUIPARAMS['VPTransp'].val - PARAMS['ObOffset'] = Vector(GUIPARAMS['XOff'].val, GUIPARAMS['YOff'].val, GUIPARAMS['ZOff'].val) - - PARAMS['NewMat'] = not GUIPARAMS['CopyMat'].val - PARAMS['MaterialId'] = GUIPARAMS['MatId'].val - PARAMS['MatProps']['Col'] = list(GUIPARAMS['MatCol'].val) - PARAMS['MatProps']['Ref'] = GUIPARAMS['Ref'].val - PARAMS['MatProps']['Spec'] = GUIPARAMS['Spec'].val - PARAMS['MatProps']['Hard'] = GUIPARAMS['Hard'].val - PARAMS['MatProps']['Alpha'] = GUIPARAMS['Alpha'].val - PARAMS['MatProps']['ZTransp'] = GUIPARAMS['ZTransp'].val - PARAMS['MatProps']['Shadeless'] = GUIPARAMS['Shadeless'].val - - PARAMS['TexChannel'] = GUIPARAMS['TexChan'].val - 1 #Channels are 0-9, but GUI shows 1-10 - PARAMS['TexProps']['UseAlpha'] = GUIPARAMS['UseAlpha'].val - PARAMS['TexProps']['CalcAlpha'] = GUIPARAMS['CalcAlpha'].val - PARAMS['TexProps']['ExtendMode'] = GUIPARAMS['ExtendMode'].val - PARAMS['TexMapTo']['Col'] = GUIPARAMS['MPTCol'].val - PARAMS['TexMapTo']['Alpha'] = GUIPARAMS['MPTAlpha'].val - - PARAMS['SeqProps']['AutoRefresh'] = GUIPARAMS['AutoRefresh'].val - PARAMS['SeqProps']['Cyclic'] = GUIPARAMS['Cyclic'].val - PARAMS['SeqProps']['Frames'] = GUIPARAMS['Frames'].val - PARAMS['SeqProps']['Offs'] = GUIPARAMS['Offs'].val - PARAMS['SeqProps']['StartFr'] = GUIPARAMS['StartFr'].val - return - -def doScript(): - # Main script Function - # Consists of choosing between 2 loops, one with a redraw, one without, see comments for why - - global CUROFFS - - translateParams() - - total = len(PARAMS['ImagePaths']) - broken = 0 - - if GUIPARAMS['RedrawImp'].val: # Reduces the need to compare on every go through the loop - for i, path in enumerate(PARAMS['ImagePaths']): - CUROFFS = i # Could be passed to the import Function, but I chose a global instead - Window.DrawProgressBar(float(i)/total, "Importing %i of %i Images..." %(i+1, total)) - imgImport(path) - Blender.Redraw() - if Blender.Get('version') >= 246: - if Window.TestBreak(): - broken = 1 - break - else: - for i, path in enumerate(PARAMS['ImagePaths']): - CUROFFS = i - Window.DrawProgressBar(float(i)/total, "Importing %i of %i Images..." %(i+1, total)) - imgImport(path) - if Blender.Get('version') >= 246: - if Window.TestBreak(): - broken = 1 - break - - if broken: - Window.DrawProgressBar(1.0, "Script Execution Aborted") - else: - Window.DrawProgressBar(1.0, "Finished Importing") - - Blender.Redraw() # Force a refresh, since the user may have chosen to not refresh as they go along - - return - -########################################## -# PATH SETTERS AND CHANGERS -########################################## - -def setSinglePath(filename): - global GUIPARAMS, PARAMS - GUIPARAMS['Path'].val = filename - PARAMS['ImagePaths'] = [filename] - return - -def setDirPath(filename): - global GUIPARAMS, PARAMS - - try: - import os - except: - Draw.PupMenu('Full install of python required to be able to set Directory Paths') - Draw.Exit() - return - - path = os.path.dirname(filename) # Blender.sys.dirname fails on '/' - GUIPARAMS['Path'].val = path - - ext_lower = GUIPARAMS['ImageExt'].val.lower() - for f in os.listdir(path): - if f.lower().endswith(ext_lower): - PARAMS['ImagePaths'].append(os.path.join(path, f)) - - return - -def changeExtension(): - global GUIPARAMS, PARAMS - - if PARAMS['ImportType'] == SINGLE: - return - - try: - import os - except: - Draw.PupMenu('Full install of python required to be able to set Directory Paths') - Draw.Exit() - return - - PARAMS['ImagePaths'] = [] - - ext_lower = GUIPARAMS['ImageExt'].val.lower() - for f in os.listdir(GUIPARAMS['Path'].val): - if f.lower().endswith(ext_lower): - PARAMS['ImagePaths'].append(os.path.join(GUIPARAMS['Path'].val, f)) - - return - -########################################## -# INTERFACE FUNCTIONS -########################################## -def compileMaterialList(): - # Pretty straight forward, just grabs the materials in the blend file and constructs - # an appropriate string for use as a menu - - mats = [mat for mat in bpy.data.materials] - PARAMS['Materials'] = mats - title = 'Materials%t|' - menStrs = [mat.name + '%x' + str(i) + '|' for i, mat in enumerate(mats)] - return title + ''.join(menStrs) - -def event(evt, val): - # Disabled, since Esc is often used from the file browser - #if evt == Draw.ESCKEY: - # Draw.Exit() - - return - -def bevent(evt): - global GUIPARAMS, PARAMS - - if evt == NO_EVT: - Draw.Redraw() - - elif evt == SINGLE_IMG: - Window.FileSelector(setSinglePath, 'Image', Blender.sys.expandpath('//')) - Draw.Redraw() - PARAMS['ImportType'] = SINGLE - - elif evt == DIRECTORY_IMG: - Window.FileSelector(setDirPath, 'Directory', Blender.sys.expandpath('//')) - Draw.Redraw() - PARAMS['ImportType'] = DIR - - elif evt == CLR_PATH: - GUIPARAMS['Path'].val = '' - PARAMS['ImagePaths'] = [] - GUIPARAMS['ImageExt'].val = '' - Draw.Redraw() - - elif evt == CHG_EXT: - changeExtension() - Draw.Redraw() - - elif evt == EXIT: - Draw.Exit() - - elif evt == DO_SCRIPT: - doScript() - - else: - print "ERROR: UNEXPECTED BUTTON EVENT" - - return - -# GUI Colors ###### -ScreenColor = [0.7, 0.7, 0.7] -BackgroundColor = [0.8, 0.8, 0.8] -TitleBG = [0.6, 0.6, 0.6] -TitleCol = [1.0, 1.0, 1.0] -ErrCol = [1.0, 0.0, 0.0] -TextCol = [0.4, 0.4, 0.5] -################### - -def GUI(): - global GUIPARAMS, PARAMS - - BGL.glClearColor(*(ScreenColor + [1.0])) - BGL.glClear(BGL.GL_COLOR_BUFFER_BIT) - - minx = 5 - maxx = 500 - miny = 5 - maxy = 450 - - lineheight = 24 - buPad = 5 # Generic Button Padding, most buttons should have 24-19 (or 5) px space around them - - lP = 5 # Left Padding - rP = 5 # Right Padding - - # Draw Background Box - BGL.glColor3f(*BackgroundColor) - BGL.glRecti(minx, miny, maxx, maxy) - - # Draw Title - BGL.glColor3f(*TitleBG) - BGL.glRecti(minx, maxy - (lineheight), maxx, maxy) - BGL.glColor3f(*TitleCol) - - title = "2D Cutout Image Importer v" + VERSIONSTRING - BGL.glRasterPos2i(minx + lP, maxy - 15) - Draw.Text(title, 'large') - - Draw.PushButton('Exit', EXIT, maxx-50-rP, maxy - lineheight + 2, 50, 19, "Exit Script") - - # Path Buttons - if GUIPARAMS['Path'].val == '': - Draw.PushButton('Single Image', SINGLE_IMG, minx + lP, maxy - (2*lineheight), 150, 19, "Select a Single Image to Import") - Draw.PushButton('Directory', DIRECTORY_IMG, minx + lP + 150, maxy - (2*lineheight), 150, 19, "Select a Directory of Images to Import") - - else: - Draw.PushButton('Clear', CLR_PATH, minx+lP, maxy - (2*lineheight), 50, 19, "Clear Path and Change Import Options") - - GUIPARAMS['Path'] = Draw.String('Path: ', NO_EVT, minx + lP, maxy - (3*lineheight), (maxx-minx-lP-rP), 19, GUIPARAMS['Path'].val, 399, 'Path to Import From') - if PARAMS['ImportType'] == DIR: - GUIPARAMS['ImageExt'] = Draw.String('Image Ext: ', CHG_EXT, minx + lP, maxy - (4*lineheight), 110, 19, GUIPARAMS['ImageExt'].val, 6, 'Image extension for batch directory importing (case insensitive)') - GUIPARAMS['PackImage'] = Draw.Toggle('Pack', NO_EVT, maxx - rP - 50, maxy - (4*lineheight), 50, 19, GUIPARAMS['PackImage'].val, 'Pack Image(s) into .Blend File') - - # Geometry and Viewport Options - BGL.glColor3f(*TextCol) - BGL.glRecti(minx+lP, maxy - (5*lineheight), maxx-rP, maxy - (5*lineheight) + 1) - BGL.glRasterPos2i(minx + lP, maxy-(5*lineheight) + 3) - Draw.Text('Geometry and Display Options', 'small') - - GUIPARAMS['PPU'] = Draw.Slider('Pixels Per Unit: ', NO_EVT, minx + lP, maxy - (6*lineheight), (maxx-minx)/2 - lP, 19, GUIPARAMS['PPU'].val, 1, 5000, 0, 'Set the Number of Pixels Per Blender Unit to preserve Image Size Relations') - GUIPARAMS['VPTransp'] = Draw.Toggle('Viewport Transparency', NO_EVT, minx + lP, maxy - (8*lineheight), (maxx-minx)/2 - lP, 2*lineheight - buPad, GUIPARAMS['VPTransp'].val, 'Display Alpha Transparency in the Viewport') - - GUIPARAMS['XOff'] = Draw.Slider('Offs X: ', NO_EVT, minx + lP + (maxx-minx)/2, maxy - (6*lineheight), (maxx-minx)/2 - lP - rP, 19, GUIPARAMS['XOff'].val, 0, 5.0, 0, 'Amount to Offset Each Imported in the X-Direction if Importing Multiple Images') - GUIPARAMS['YOff'] = Draw.Slider('Offs Y: ', NO_EVT, minx + lP + (maxx-minx)/2, maxy - (7*lineheight), (maxx-minx)/2 - lP - rP, 19, GUIPARAMS['YOff'].val, 0, 5.0, 0, 'Amount to Offset Each Imported in the Y-Direction if Importing Multiple Images') - GUIPARAMS['ZOff'] = Draw.Slider('Offs Z: ', NO_EVT, minx + lP + (maxx-minx)/2, maxy - (8*lineheight), (maxx-minx)/2 - lP - rP, 19, GUIPARAMS['ZOff'].val, 0, 5.0, 0, 'Amount to Offset Each Imported in the Z-Direction if Importing Multiple Images') - - # Material and Texture Options - BGL.glColor3f(*TextCol) - BGL.glRecti(minx+lP, maxy - (9*lineheight), maxx-rP, maxy - (9*lineheight) + 1) - BGL.glRasterPos2i(minx + lP, maxy-(9*lineheight) + 3) - Draw.Text('Material and Texture Options', 'small') - - half = (maxx-minx-lP-rP)/2 - GUIPARAMS['CopyMat'] = Draw.Toggle('Copy Existing Material', NO_EVT, minx + lP, maxy-(10*lineheight), half, 19, GUIPARAMS['CopyMat'].val, 'Copy an Existing Material') - if GUIPARAMS['CopyMat'].val: - menStr = compileMaterialList() - GUIPARAMS['MatId'] = Draw.Menu(menStr, NO_EVT, minx + lP, maxy - (11*lineheight), half, 19, GUIPARAMS['MatId'].val, 'Material to Copy Settings From') - else: - GUIPARAMS['MatCol'] = Draw.ColorPicker(NO_EVT, minx+lP, maxy - (13*lineheight), 40, (3*lineheight) - buPad, GUIPARAMS['MatCol'].val, 'Color of Newly Created Material') - GUIPARAMS['Ref'] = Draw.Slider('Ref: ', NO_EVT, minx +lP+45, maxy - (11*lineheight), half-45, 19, GUIPARAMS['Ref'].val, 0.0, 1.0, 0, 'Set the Ref Value for Created Materials') - GUIPARAMS['Spec'] = Draw.Slider('Spec: ', NO_EVT, minx +lP+45, maxy - (12*lineheight), half-45, 19, GUIPARAMS['Spec'].val, 0.0, 2.0, 0, 'Set the Spec Value for Created Materials') - GUIPARAMS['Hard'] = Draw.Slider('Hard: ', NO_EVT, minx +lP+45, maxy - (13*lineheight), half-45, 19, GUIPARAMS['Hard'].val, 1, 500, 0, 'Set the Hardness Value for Created Materials') - GUIPARAMS['Alpha'] = Draw.Slider('A: ', NO_EVT, minx +lP, maxy - (14*lineheight), half, 19, GUIPARAMS['Alpha'].val, 0.0, 1.0, 0, 'Set the Alpha Value for Created Materials') - - GUIPARAMS['ZTransp'] = Draw.Toggle('ZTransparency', NO_EVT, minx + lP, maxy - (15*lineheight), half, 19, GUIPARAMS['ZTransp'].val, 'Enable ZTransparency') - GUIPARAMS['Shadeless'] = Draw.Toggle('Shadeless', NO_EVT, minx + lP, maxy - (16*lineheight), half, 19, GUIPARAMS['Shadeless'].val, 'Enable Shadeless') - - GUIPARAMS['TexChan'] = Draw.Number('Texture Channel: ', NO_EVT, minx + lP+ half + buPad, maxy - (10*lineheight), half-rP, 19, GUIPARAMS['TexChan'].val, 1, 10, 'Texture Channel for Image Texture') - - GUIPARAMS['MPTCol'] = Draw.Toggle('Color', NO_EVT, minx + lP + half + buPad, maxy - (11*lineheight), half/2, 19, GUIPARAMS['MPTCol'].val, 'Map To Color Channel') - GUIPARAMS['MPTAlpha'] = Draw.Toggle('Alpha', NO_EVT, minx + lP + int((1.5)*half) + buPad, maxy - (11*lineheight), half/2 - rP, 19, GUIPARAMS['MPTAlpha'].val, 'Map To Alpha Channel') - - third = int((maxx-minx-lP-rP)/6) - GUIPARAMS['UseAlpha'] = Draw.Toggle('Use Alpha', NO_EVT, minx + lP + half + buPad, maxy - (12*lineheight), third, 19, GUIPARAMS['UseAlpha'].val, "Use the Images' Alpha Values") - GUIPARAMS['CalcAlpha'] = Draw.Toggle('Calc Alpha', NO_EVT, minx + lP + half + third + buPad, maxy - (12*lineheight), third, 19, GUIPARAMS['CalcAlpha'].val, "Calculate Images' Alpha Values") - GUIPARAMS['ExtendMode'] = Draw.Toggle('Extend', NO_EVT, minx+lP+half+third+third+buPad, maxy - (12*lineheight), third-3, 19, GUIPARAMS['ExtendMode'].val, "Use Extend texture mode. If deselected, Repeat is used") - GUIPARAMS['Seq'] = Draw.Toggle('Sequence', NO_EVT, minx + lP + half + buPad, maxy - (13*lineheight), half-rP, 19, GUIPARAMS['Seq'].val, 'Set the Image(s) to use a Sequence instead of a Still') - - if GUIPARAMS['Seq'].val and not PARAMS['ImportType'] == DIR: - GUIPARAMS['AutoRefresh'] = Draw.Toggle('Auto Refresh', NO_EVT, minx + lP + half + buPad, maxy - (14*lineheight), half/2, 19, GUIPARAMS['AutoRefresh'].val, 'Use Auto Refresh') - GUIPARAMS['Cyclic'] = Draw.Toggle('Cyclic', NO_EVT, minx + lP + half + buPad + half/2, maxy - (14*lineheight), half/2 - rP, 19, GUIPARAMS['Cyclic'].val, 'Repeat Frames Cyclically`') - - GUIPARAMS['Frames'] = Draw.Number('Frames: ', NO_EVT, minx +lP + half + buPad, maxy - (15*lineheight), half - rP, 19, GUIPARAMS['Frames'].val, 1, 30000, 'Sets the Number of Images of a Movie to Use') - GUIPARAMS['Offs'] = Draw.Number('Offs: ', NO_EVT, minx +lP + half + buPad, maxy - (16*lineheight), half/2, 19, GUIPARAMS['Offs'].val, -30000, 30000, 'Offsets the Number of the Frame to use in the Animation') - GUIPARAMS['StartFr'] = Draw.Number('StartFr: ', NO_EVT, minx +lP + half + buPad + half/2, maxy - (16*lineheight), half/2 - rP, 19, GUIPARAMS['StartFr'].val, 1, 30000, 'Sets the Global Starting Frame of the Movie') - elif GUIPARAMS['Seq'].val and PARAMS['ImportType'] == DIR: - BGL.glColor3f(*ErrCol) - BGL.glRasterPos2i(minx + lP + half + buPad + 7, maxy-(14 * lineheight) + 5) - Draw.Text('Sequence only available for Single Image Import', 'small') - - # Import Options - BGL.glColor3f(*TextCol) - BGL.glRecti(minx+lP, maxy - (17*lineheight), maxx-rP, maxy - (17*lineheight) + 1) - BGL.glRasterPos2i(minx + lP, maxy-(17*lineheight) + 3) - Draw.Text('Import', 'small') - - if GUIPARAMS['Path'].val and GUIPARAMS['ImageExt'].val or GUIPARAMS['Path'].val and PARAMS['ImportType'] == SINGLE: - Draw.PushButton('Import', DO_SCRIPT, minx + lP, maxy - (18*lineheight), 75, 19, "Import Image(s)") - else: - BGL.glColor3f(*ErrCol) - BGL.glRasterPos2i(minx+lP, maxy - (18*lineheight) + 5) - Draw.Text('A path and image type must be specified to import images') - - GUIPARAMS['RedrawImp'] = Draw.Toggle('Redraw During Import', NO_EVT, maxx - rP - 150, maxy - (18*lineheight), 150, 19, GUIPARAMS['RedrawImp'].val, 'Redraw the View as Images Import') - -Draw.Register(GUI, event, bevent)
\ No newline at end of file diff --git a/release/scripts/image_auto_layout.py b/release/scripts/image_auto_layout.py deleted file mode 100644 index d19ba1da662..00000000000 --- a/release/scripts/image_auto_layout.py +++ /dev/null @@ -1,455 +0,0 @@ -#!BPY - -""" -Name: 'Consolidate into one image' -Blender: 243 -Group: 'Image' -Tooltip: 'Pack all texture images into 1 image and remap faces.' -""" - -__author__ = "Campbell Barton" -__url__ = ("blender", "blenderartists.org") -__version__ = "1.1a 2009/04/01" - -__bpydoc__ = """\ -This script makes a new image from the used areas of all the images mapped to the selected mesh objects. -Image are packed into 1 new image that is assigned to the original faces. -This is usefull for game models where 1 image is faster then many, and saves the labour of manual texture layout in an image editor. - -""" -# -------------------------------------------------------------------------- -# Auto Texture Layout v1.0 by Campbell Barton (AKA Ideasman) -# -------------------------------------------------------------------------- -# ***** 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 ***** -# -------------------------------------------------------------------------- - - -# Function to find all the images we use -import Blender as B -from Blender.Mathutils import Vector, RotationMatrix -from Blender.Scene import Render -import BPyMathutils -BIGNUM= 1<<30 -TEXMODE= B.Mesh.FaceModes.TEX - -def pointBounds(points): - ''' - Takes a list of points and returns the - area, center, bounds - ''' - ymax= xmax= -BIGNUM - ymin= xmin= BIGNUM - - for p in points: - x= p.x - y= p.y - - if x>xmax: xmax=x - if y>ymax: ymax=y - - if x<xmin: xmin=x - if y<ymin: ymin=y - - # area and center - return\ - (xmax-xmin) * (ymax-ymin),\ - Vector((xmin+xmax)/2, (ymin+ymax)/2),\ - (xmin, ymin, xmax, ymax) - - -def bestBoundsRotation(current_points): - ''' - Takes a list of points and returns the best rotation for those points - so they fit into the samllest bounding box - ''' - - current_area, cent, bounds= pointBounds(current_points) - - total_rot_angle= 0.0 - rot_angle= 45 - while rot_angle > 0.1: - mat_pos= RotationMatrix( rot_angle, 2) - mat_neg= RotationMatrix( -rot_angle, 2) - - new_points_pos= [v*mat_pos for v in current_points] - area_pos, cent_pos, bounds_pos= pointBounds(new_points_pos) - - # 45d rotations only need to be tested in 1 direction. - if rot_angle == 45: - area_neg= area_pos - else: - new_points_neg= [v*mat_neg for v in current_points] - area_neg, cent_neg, bounds_neg= pointBounds(new_points_neg) - - - # Works! - #print 'Testing angle', rot_angle, current_area, area_pos, area_neg - - best_area= min(area_pos, area_neg, current_area) - if area_pos == best_area: - current_area= area_pos - cent= cent_pos - bounds= bounds_pos - current_points= new_points_pos - total_rot_angle+= rot_angle - elif rot_angle != 45 and area_neg == best_area: - current_area= area_neg - cent= cent_neg - bounds= bounds_neg - current_points= new_points_neg - total_rot_angle-= rot_angle - - rot_angle *= 0.5 - - # Return the optimal rotation. - return total_rot_angle - - -class faceGroup(object): - ''' - A Group of faces that all use the same image, each group has its UVs packed into a square. - ''' - __slots__= 'xmax', 'ymax', 'xmin', 'ymin',\ - 'image', 'faces', 'box_pack', 'size', 'ang', 'rot_mat', 'cent'\ - - def __init__(self, mesh_list, image, size, PREF_IMAGE_MARGIN): - self.image= image - self.size= size - self.faces= [f for me in mesh_list for f in me.faces if f.mode & TEXMODE and f.image == image] - - # Find the best rotation. - all_points= [uv for f in self.faces for uv in f.uv] - bountry_indicies= BPyMathutils.convexHull(all_points) - bountry_points= [all_points[i] for i in bountry_indicies] - - # Pre Rotation bounds - self.cent= pointBounds(bountry_points)[1] - - # Get the optimal rotation angle - self.ang= bestBoundsRotation(bountry_points) - self.rot_mat= RotationMatrix(self.ang, 2), RotationMatrix(-self.ang, 2) - - # Post rotation bounds - bounds= pointBounds([\ - ((uv-self.cent) * self.rot_mat[0]) + self.cent\ - for uv in bountry_points])[2] - - # Break the bounds into useable values. - xmin, ymin, xmax, ymax= bounds - - # Store the bounds, include the margin. - # The bounds rect will need to be rotated to the rotation angle. - self.xmax= xmax + (PREF_IMAGE_MARGIN/size[0]) - self.xmin= xmin - (PREF_IMAGE_MARGIN/size[0]) - self.ymax= ymax + (PREF_IMAGE_MARGIN/size[1]) - self.ymin= ymin - (PREF_IMAGE_MARGIN/size[1]) - - self.box_pack=[\ - 0.0, 0.0,\ - size[0]*(self.xmax - self.xmin),\ - size[1]*(self.ymax - self.ymin),\ - image.name] - - ''' - # default. - self.scale= 1.0 - - def set_worldspace_scale(self): - scale_uv= 0.0 - scale_3d= 0.0 - for f in self.faces: - for i in xrange(len(f.v)): - scale_uv+= (f.uv[i]-f.uv[i-1]).length * 0.1 - scale_3d+= (f.v[i].co-f.v[i-1].co).length * 0.1 - self.scale= scale_3d/scale_uv - ''' - - - - def move2packed(self, width, height): - ''' - Moves the UV coords to their packed location - using self.box_pack as the offset, scaler. - box_pack must be set to its packed location. - width and weight are the w/h of the overall packed area's bounds. - ''' - # packedLs is a list of [(anyUniqueID, left, bottom, width, height)...] - # Width and height in float pixel space. - - # X Is flipped :/ - #offset_x= (1-(self.box_pack[1]/d)) - (((self.xmax-self.xmin) * self.image.size[0])/d) - offset_x= self.box_pack[0]/width - offset_y= self.box_pack[1]/height - - for f in self.faces: - for uv in f.uv: - uv_rot= ((uv-self.cent) * self.rot_mat[0]) + self.cent - uv.x= offset_x+ (((uv_rot.x-self.xmin) * self.size[0])/width) - uv.y= offset_y+ (((uv_rot.y-self.ymin) * self.size[1])/height) - -def consolidate_mesh_images(mesh_list, scn, PREF_IMAGE_PATH, PREF_IMAGE_SIZE, PREF_KEEP_ASPECT, PREF_IMAGE_MARGIN): #, PREF_SIZE_FROM_UV=True): - ''' - Main packing function - - All meshes from mesh_list must have faceUV else this function will fail. - ''' - face_groups= {} - - for me in mesh_list: - for f in me.faces: - if f.mode & TEXMODE: - image= f.image - if image: - try: - face_groups[image.name] # will fail if teh groups not added. - except: - try: - size= image.size - except: - B.Draw.PupMenu('Aborting: Image cold not be loaded|' + image.name) - return - - face_groups[image.name]= faceGroup(mesh_list, image, size, PREF_IMAGE_MARGIN) - - if not face_groups: - B.Draw.PupMenu('No Images found in mesh(es). Aborting!') - return - - if len(face_groups)<2: - B.Draw.PupMenu('Only 1 image found|Select a mesh(es) using 2 or more images.') - return - - ''' - if PREF_SIZE_FROM_UV: - for fg in face_groups.itervalues(): - fg.set_worldspace_scale() - ''' - - # RENDER THE FACES. - render_scn= B.Scene.New() - render_scn.makeCurrent() - render_context= render_scn.getRenderingContext() - render_context.setRenderPath('') # so we can ignore any existing path and save to the abs path. - - PREF_IMAGE_PATH_EXPAND= B.sys.expandpath(PREF_IMAGE_PATH) + '.png' - - # TEST THE FILE WRITING. - try: - # Can we write to this file??? - f= open(PREF_IMAGE_PATH_EXPAND, 'w') - f.close() - except: - B.Draw.PupMenu('Error%t|Could not write to path|' + PREF_IMAGE_PATH_EXPAND) - return - - render_context.imageSizeX(PREF_IMAGE_SIZE) - render_context.imageSizeY(PREF_IMAGE_SIZE) - render_context.enableOversampling(True) - render_context.setOversamplingLevel(16) - render_context.setRenderWinSize(100) - render_context.setImageType(Render.PNG) - render_context.enableExtensions(True) - render_context.enablePremultiply() # No alpha needed. - render_context.enableRGBAColor() - render_context.threads = 2 - - #Render.EnableDispView() # Broken?? - - # New Mesh and Object - render_mat= B.Material.New() - render_mat.mode |= \ - B.Material.Modes.SHADELESS | \ - B.Material.Modes.TEXFACE | \ - B.Material.Modes.TEXFACE_ALPHA | \ - B.Material.Modes.ZTRANSP - - render_mat.setAlpha(0.0) - - render_me= B.Mesh.New() - render_me.verts.extend([Vector(0,0,0)]) # Stupid, dummy vert, preverts errors. when assigning UV's/ - render_ob= B.Object.New('Mesh') - render_ob.link(render_me) - render_scn.link(render_ob) - render_me.materials= [render_mat] - - - # New camera and object - render_cam_data= B.Camera.New('ortho') - render_cam_ob= B.Object.New('Camera') - render_cam_ob.link(render_cam_data) - render_scn.link(render_cam_ob) - render_scn.objects.camera = render_cam_ob - - render_cam_data.type= 'ortho' - render_cam_data.scale= 1.0 - - - # Position the camera - render_cam_ob.LocZ= 1.0 - render_cam_ob.LocX= 0.5 - render_cam_ob.LocY= 0.5 - - # List to send to to boxpack function. - boxes2Pack= [ fg.box_pack for fg in face_groups.itervalues()] - packWidth, packHeight = B.Geometry.BoxPack2D(boxes2Pack) - - if PREF_KEEP_ASPECT: - packWidth= packHeight= max(packWidth, packHeight) - - - # packedLs is a list of [(anyUniqueID, left, bottom, width, height)...] - # Re assign the face groups boxes to the face_group. - for box in boxes2Pack: - face_groups[ box[4] ].box_pack= box # box[4] is the ID (image name) - - - # Add geometry to the mesh - for fg in face_groups.itervalues(): - # Add verts clockwise from the bottom left. - _x= fg.box_pack[0] / packWidth - _y= fg.box_pack[1] / packHeight - _w= fg.box_pack[2] / packWidth - _h= fg.box_pack[3] / packHeight - - render_me.verts.extend([\ - Vector(_x, _y, 0),\ - Vector(_x, _y +_h, 0),\ - Vector(_x + _w, _y +_h, 0),\ - Vector(_x + _w, _y, 0),\ - ]) - - render_me.faces.extend([\ - render_me.verts[-1],\ - render_me.verts[-2],\ - render_me.verts[-3],\ - render_me.verts[-4],\ - ]) - - target_face= render_me.faces[-1] - target_face.image= fg.image - target_face.mode |= TEXMODE - - # Set the UV's, we need to flip them HOZ? - target_face.uv[0].x= target_face.uv[1].x= fg.xmax - target_face.uv[2].x= target_face.uv[3].x= fg.xmin - - target_face.uv[0].y= target_face.uv[3].y= fg.ymin - target_face.uv[1].y= target_face.uv[2].y= fg.ymax - - for uv in target_face.uv: - uv_rot= ((uv-fg.cent) * fg.rot_mat[1]) + fg.cent - uv.x= uv_rot.x - uv.y= uv_rot.y - - render_context.render() - Render.CloseRenderWindow() - render_context.saveRenderedImage(PREF_IMAGE_PATH_EXPAND) - - #if not B.sys.exists(PREF_IMAGE_PATH_EXPAND): - # raise 'Error!!!' - - - # NOW APPLY THE SAVED IMAGE TO THE FACES! - #print PREF_IMAGE_PATH_EXPAND - try: - target_image= B.Image.Load(PREF_IMAGE_PATH_EXPAND) - except: - B.Draw.PupMenu('Error: Could not render or load the image at path|' + PREF_IMAGE_PATH_EXPAND) - return - - # Set to the 1 image. - for me in mesh_list: - for f in me.faces: - if f.mode & TEXMODE and f.image: - f.image= target_image - - for fg in face_groups.itervalues(): - fg.move2packed(packWidth, packHeight) - - scn.makeCurrent() - render_me.verts= None # free a tiny amount of memory. - B.Scene.Unlink(render_scn) - target_image.makeCurrent() - - -def main(): - scn= B.Scene.GetCurrent() - scn_objects = scn.objects - ob= scn_objects.active - - if not ob or ob.type != 'Mesh': - B.Draw.PupMenu('Error, no active mesh object, aborting.') - return - - # Create the variables. - # Filename without path or extension. - newpath= B.Get('filename').split('/')[-1].split('\\')[-1].replace('.blend', '') - - PREF_IMAGE_PATH = B.Draw.Create('//%s_grp' % newpath) - PREF_IMAGE_SIZE = B.Draw.Create(1024) - PREF_IMAGE_MARGIN = B.Draw.Create(6) - PREF_KEEP_ASPECT = B.Draw.Create(0) - PREF_ALL_SEL_OBS = B.Draw.Create(0) - - pup_block = [\ - 'Image Path: (no ext)',\ - ('', PREF_IMAGE_PATH, 3, 100, 'Path to new Image. "//" for curent blend dir.'),\ - 'Image Options', - ('Pixel Size:', PREF_IMAGE_SIZE, 64, 4096, 'Image Width and Height.'),\ - ('Pixel Margin:', PREF_IMAGE_MARGIN, 0, 64, 'Use a margin to stop mipmapping artifacts.'),\ - ('Keep Aspect', PREF_KEEP_ASPECT, 'If disabled, will stretch the images to the bounds of the texture'),\ - 'Texture Source',\ - ('All Sel Objects', PREF_ALL_SEL_OBS, 'Combine all selected objects into 1 texture, otherwise active object only.'),\ - ] - - if not B.Draw.PupBlock('Consolidate images...', pup_block): - return - - PREF_IMAGE_PATH= PREF_IMAGE_PATH.val - PREF_IMAGE_SIZE= PREF_IMAGE_SIZE.val - PREF_IMAGE_MARGIN= float(PREF_IMAGE_MARGIN.val) # important this is a float otherwise division wont work properly - PREF_KEEP_ASPECT= PREF_KEEP_ASPECT.val - PREF_ALL_SEL_OBS= PREF_ALL_SEL_OBS.val - - if PREF_ALL_SEL_OBS: - mesh_list= [ob.getData(mesh=1) for ob in scn_objects.context if ob.type=='Mesh'] - # Make sure we have no doubles- dict by name, then get the values back. - - for me in mesh_list: me.tag = False - - mesh_list_new = [] - for me in mesh_list: - if me.faceUV and me.tag==False: - me.tag = True - mesh_list_new.append(me) - - # replace list with possible doubles - mesh_list = mesh_list_new - - else: - mesh_list= [ob.getData(mesh=1)] - if not mesh_list[0].faceUV: - B.Draw.PupMenu('Error, active mesh has no images, Aborting!') - return - - consolidate_mesh_images(mesh_list, scn, PREF_IMAGE_PATH, PREF_IMAGE_SIZE, PREF_KEEP_ASPECT, PREF_IMAGE_MARGIN) - B.Window.RedrawAll() - -if __name__=='__main__': - main() diff --git a/release/scripts/image_billboard.py b/release/scripts/image_billboard.py deleted file mode 100644 index 54f0f7c5c55..00000000000 --- a/release/scripts/image_billboard.py +++ /dev/null @@ -1,269 +0,0 @@ -#!BPY -""" -Name: 'Billboard Render on Active' -Blender: 242 -Group: 'Image' -Tooltip: 'Selected objects and lamps to rendered faces on the act mesh' -""" -__author__= "Campbell Barton" -__url__= ["blender", "blenderartist"] -__version__= "1.0" - -__bpydoc__= """\ -Render Billboard Script -This can texture a simple billboard mesh from any number of selected objects. - -Renders objects in the selection to quad faces on the active mesh. - -Usage -* Light your model or enable the shadless flag so it is visible -* Make a low poly mesh out of quads with 90d corners. (this will be you billboard mesh) -* Select the model and any lamps that light it -* Select the billboard mesh so that it is active -* Run this script, Adjust settings such as image size or oversampling. -* Select a place to save the PNG image. -* Once the script has finished running return to the 3d view by pressing Shift+F5 -* To see the newly applied textures change the drawtype to 'Textured Solid' -""" -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Script copyright (C) Campbell J Barton 2006 -# -# 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 ***** -# -------------------------------------------------------------------------- - -import Blender -from Blender import Mesh, Material, Draw -import BPyMathutils -import bpy -import BPyRender -from Blender.Scene import Render - -# reload(BPyRender) -# reload(BPyMathutils) - -import os -Vector= Blender.Mathutils.Vector - -def alpha_mat(image): - # returns a material useable for - mtl= bpy.data.materials.new() - mtl.mode |= (Material.Modes.SHADELESS | Material.Modes.ZTRANSP | Material.Modes.FULLOSA | Material.Modes.TEXFACE | Material.Modes.TEXFACE_ALPHA ) - return mtl - -# PupBlock Settings -GLOBALS= {} -PREF_RES= Draw.Create(512) -PREF_TILE_RES= Draw.Create(256) -PREF_AA = Draw.Create(1) -PREF_ALPHA= Draw.Create(1) -PREF_Z_OFFSET = Draw.Create(10.0) -PREF_IMG_PACK= Draw.Create(1) - - -def save_billboard(PREF_IMAGE_PATH): - Blender.Window.WaitCursor(1) - # remove png, add it later - PREF_IMAGE_PATH= PREF_IMAGE_PATH.replace('.png', '') - - ob_sel= GLOBALS['ob_sel'] - me_ob = GLOBALS['me_ob'] - me_data = GLOBALS['me_data'] - - time= Blender.sys.time() - - me_mat= me_ob.matrixWorld - - # Render images for all faces - face_data= [] # Store faces, images etc - boxes2Pack= [] - me_data.faceUV= True - - for i, f in enumerate(me_data.faces): - no= f.no - - # Offset the plane by the zoffset on the faces normal - plane= [v.co * me_mat for v in f] - - # Horizontal stacking, make sure 0,1 and 2,3 are the longest - if\ - (plane[0]-plane[1]).length + (plane[2]-plane[3]).length < \ - (plane[1]-plane[2]).length + (plane[3]-plane[0]).length: - plane.append(plane.pop(0)) - rot90= True - else: - rot90= False - - no= Blender.Mathutils.QuadNormal(*plane) - plane= [v + no*PREF_Z_OFFSET.val for v in plane] - - cent= (plane[0]+plane[1]+plane[2]+plane[3] ) /4.0 - camera_matrix= BPyMathutils.plane2mat(plane) - tmp_path= '%s_%d' % (PREF_IMAGE_PATH, i) - img= BPyRender.imageFromObjectsOrtho(ob_sel, tmp_path, PREF_TILE_RES.val, PREF_TILE_RES.val, PREF_AA.val, PREF_ALPHA.val, camera_matrix) - img.reload() - #img.pack() # se we can keep overwriting the path - #img.filename= "" - - if rot90: - f.uv=Vector(1,1), Vector(0,1), Vector(0,0), Vector(1,0) - else: - f.uv= Vector(0,1), Vector(0,0), Vector(1,0), Vector(1,1) - - if not PREF_IMG_PACK.val: - f.mode |= Mesh.FaceModes.TEX - f.image = img - - if PREF_ALPHA.val: - f.transp |= Mesh.FaceTranspModes.ALPHA - else: - w= ((plane[0]-plane[1]).length + (plane[2]-plane[3]).length)/2 - h= ((plane[1]-plane[2]).length + (plane[3]-plane[0]).length)/2 - - face_data.append( (f, img) ) - boxes2Pack.append( [0.0,0.0,h, w, i] ) - - if PREF_IMG_PACK.val: - # pack the quads into a square - packWidth, packHeight = Blender.Geometry.BoxPack2D(boxes2Pack) - - render_obs= [] - - render_mat= alpha_mat(img) - - # Add geometry to the mesh - for box in boxes2Pack: - i= box[4] - - orig_f, img= face_data[i] - - # New Mesh and Object - - render_me= bpy.data.meshes.new() - - render_ob= Blender.Object.New('Mesh') - render_me.materials= [render_mat] - render_ob.link(render_me) - - render_obs.append(render_ob) - - # Add verts clockwise from the bottom left. - _x= box[0] / packWidth - _y= box[1] / packHeight - _w= box[2] / packWidth - _h= box[3] / packHeight - - - render_me.verts.extend([\ - Vector(_x, _y, 0),\ - Vector(_x, _y +_h, 0),\ - Vector(_x + _w, _y +_h, 0),\ - Vector(_x + _w, _y, 0),\ - ]) - - render_me.faces.extend(list(render_me.verts)) - render_me.faceUV= True - - render_me.faces[0].uv = [Vector(0,0), Vector(0,1), Vector(1,1), Vector(1,0)] - render_me.faces[0].image = img - - # Set the UV's, we need to flip them HOZ? - for uv in orig_f.uv: - uv.x = _x + (uv.x * _w) - uv.y = _y + (uv.y * _h) - - target_image= BPyRender.imageFromObjectsOrtho(render_obs, PREF_IMAGE_PATH, PREF_RES.val, PREF_RES.val, PREF_AA.val, PREF_ALPHA.val, None) - target_image.reload() # incase your overwriting an existing image. - - # Set to the 1 image. - for f in me_data.faces: - f.image= target_image - if PREF_ALPHA.val: - f.transp |= Mesh.FaceTranspModes.ALPHA - - # Free the images data and remove - for data in face_data: - img= data[1] - os.remove(img.filename) - img.reload() - - # Finish pack - - me_data.update() - me_ob.makeDisplayList() - Blender.Window.WaitCursor(0) - print '%.2f secs taken' % (Blender.sys.time()-time) - - -def main(): - scn= bpy.data.scenes.active - ob_sel= list(scn.objects.context) - - PREF_KEEP_ASPECT= False - - # Error Checking - if len(ob_sel) < 2: - Draw.PupMenu("Error%t|Select 2 mesh objects") - return - - me_ob= scn.objects.active - - if not me_ob: - Draw.PupMenu("Error%t|No active mesh selected.") - - try: - ob_sel.remove(me_ob) - except: - pass - - if me_ob.type != 'Mesh': - Draw.PupMenu("Error%t|Active Object must be a mesh to write billboard images too") - return - - me_data= me_ob.getData(mesh=1) - - for f in me_data.faces: - if len(f) != 4: - Draw.PupMenu("Error%t|Active mesh must have only quads") - return - - - # Get user input - block = [\ - 'Image Pixel Size',\ - ("Packed Size: ", PREF_RES, 128, 2048, "Pixel width and height to render the billboard to"),\ - ("Tile Size: ", PREF_TILE_RES, 64, 1024, "Pixel width and height for each tile to render to"),\ - 'Render Settings',\ - ("Pack Final", PREF_IMG_PACK , "Pack the image for each face into images into a single image"),\ - ("Oversampling", PREF_AA , "Higher quality woth extra sampling"),\ - ("Alpha Clipping", PREF_ALPHA , "Render empty areas as transparent"),\ - ("Cam ZOffset: ", PREF_Z_OFFSET, 0.1, 100, "Distance to place the camera away from the quad when rendering")\ - ] - - if not Draw.PupBlock("Billboard Render", block): - return - - # Set globals - GLOBALS['ob_sel'] = ob_sel - GLOBALS['me_ob'] = me_ob - GLOBALS['me_data'] = me_data - - Blender.Window.FileSelector(save_billboard, 'SAVE BILLBOARD', Blender.sys.makename(ext='.png')) - # save_billboard('/tmp/test.png') - -if __name__=='__main__': - main() diff --git a/release/scripts/image_edit.py b/release/scripts/image_edit.py deleted file mode 100644 index cae40b74097..00000000000 --- a/release/scripts/image_edit.py +++ /dev/null @@ -1,158 +0,0 @@ -#!BPY -""" -Name: 'Edit Externally' -Blender: 242a -Group: 'Image' -Tooltip: 'Open in an application for editing. (hold Shift to configure)' -""" - -__author__ = "Campbell Barton" -__url__ = ["blender", "blenderartists.org"] -__version__ = "1.0" -__bpydoc__ = """\ -This script opens the current image in an external application for editing. - -Usage: -Choose an image for editing in the UV/Image view. - -To configure the application to open the image with, hold Shift as you -click on this menu item. - -For first time users try running the default application for your -operating system. If the application does not open you can type in -the full path. You can choose that the last entered application will -be saved as a default. - -* Note, default commants for opening an image are "start" for win32 -and "open" for macos. This will use the system default associated -application. -""" - -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Script copyright (C) Campbell J Barton 2006 -# -# 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 ***** -# -------------------------------------------------------------------------- - -import Blender -from Blender import Image, sys, Draw, Registry - -try: - import subprocess - import sys as py_sys - platform = py_sys.platform -except: - Draw.PupMenu('Error: Recent version of Python not installed.') - subprocess=None - -def os_run(appstring, filename): - ''' - Run the app, take into account different python versions etc - looks like python 2.6 wants a list for - ''' - - # evil trick, temp replace spaces so we can allow spaces in filenames - # also allows multiple instances of %f - appstring = appstring.replace(' ', '\t') - appstring = appstring.replace('%f', filename) - appstring = appstring.split('\t') - - print ' '.join(appstring) - - try: # only python 2.6 wants a list? - p = subprocess.Popen(appstring) - except: - p = subprocess.Popen(' '.join(appstring)) - - -def edit_extern(image=None): - - if not image: - image = Image.GetCurrent() - - if not image: # Image is None - Draw.PupMenu('ERROR: Please select active Image.') - return - if image.packed: - Draw.PupMenu('ERROR: Image is packed, unpack before editing.') - return - - imageFileName = sys.expandpath( image.filename ) - - if not sys.exists(imageFileName): - Draw.PupMenu('ERROR: Image path does not exist.') - return - - pupblock = [imageFileName.split('/')[-1].split('\\')[-1]] - - new_text= False - try: - appstring = Registry.GetKey('ExternalImageEditor', True) - appstring = appstring['path'] - - # for ZanQdo if he removed the path from the textbox totaly. ;) - Cam - if not appstring or appstring.find('%f')==-1: - new_text= True - except: - new_text= True - - if new_text: - pupblock.append('first time, set path.') - if platform == 'win32': - # Example of path to popular image editor... ;-) - # appstring = '"C:\\Program Files\\Adobe\\Photoshop CS\\photoshop.exe" "%f"' - # Have to add "cmd /c" to make sure we're using Windows shell. - appstring = 'cmd /c start "" /B "%f"' - elif platform == 'darwin': - appstring = 'open "%f"' - else: - appstring = 'gimp %f' - - appstring_but = Draw.Create(appstring) - save_default_but = Draw.Create(0) - - pupblock.append(('editor: ', appstring_but, 0, 99, 'Path to application, %f will be replaced with the image path.')) - pupblock.append(('Set Default', save_default_but, 'Store this path in the blender registry.')) - - # Only configure if Shift is held, - if Blender.Window.GetKeyQualifiers() & Blender.Window.Qual.SHIFT: - if not Draw.PupBlock('External Image Editor...', pupblock): - return - - appstring = appstring_but.val - save_default= save_default_but.val - - if save_default: - Registry.SetKey('ExternalImageEditor', {'path':appstring}, True) - - if appstring.find('%f') == -1: - Draw.PupMenu('ERROR: No filename specified! ("%f")') - return - - # ------------------------------- - - os_run(appstring, imageFileName) - - - -def main(): - edit_extern() - - -if __name__ == '__main__' and subprocess: - main() diff --git a/release/scripts/import_dxf.py b/release/scripts/import_dxf.py deleted file mode 100644 index b3bee11c464..00000000000 --- a/release/scripts/import_dxf.py +++ /dev/null @@ -1,6225 +0,0 @@ -#!BPY - -""" -Name: 'Autodesk DXF (.dxf .dwg)' -Blender: 249 -Group: 'Import' -Tooltip: 'Import for DWG/DXF geometry data.' -""" -__author__ = 'Kitsu(Ed Blake) & migius(Remigiusz Fiedler)' -__version__ = '1.12 - 2009.06.16 by migius' -__url__ = ["http://blenderartists.org/forum/showthread.php?t=84319", - "http://wiki.blender.org/index.php/Scripts/Manual/Import/DXF-3D"] -__email__ = ["migius(at)4d-vectors.de","Kitsune_e(at)yahoo.com"] -__bpydoc__ = """\ -This script imports objects from DWG/DXF (2d/3d) into Blender. - -This script imports 2d and 3d geometery from DXF files. -It supports DWG format too, with help of an external converter. -Supported DXF format versions: from (r2.5) r12 up to r2008. -Enhanced features are: -- configurable object filtering and geometry manipulation, -- configurable material pre-processing, -- DXF-code analyze and reporting. - -Supported DXF r12 objects: -LINE, -POINT, -SOLID, -TRACE, -TEXT, -INSERT (=block), -MINSERT (=array of blocks), -CIRCLE, -ARC, -3DFACE, -2d-POLYLINE (=in plane, incl. arc, variable-width, curve, spline), -3d-POLYLINE (=non-plane), -3d-POLYMESH, -3d-POLYFACE, -VIEW, VPORT -XREF (External Reference). - -Supported DXF>r12 objects: -ELLIPSE, -LWPOLYLINE (LightWeight Polyline), -SPLINE, -(todo v1.13) MLINE, -(todo v1.13) MTEXT - -Unsupported objects: -DXF r12: DIMENSION. -DXF>r12: GROUP, RAY/XLINE, LEADER, 3DSOLID, BODY, REGION, dynamic BLOCK - -Supported geometry: 2d and 3d DXF-objects. -Curves imported as Blender curves or meshes optionally. - -Supported layout modes: -"model space" is default, -"paper space" as option (= "layout views") - -Supported scene definition objects produced with AVE_RENDER: -scene: selection of lights assigned to the camera, -lights: DIRECT, OVERHEAD, SH_SPOT, -(wip v1.13 import of AVE_RENDER material definitions) - -Hierarchy: -Entire DXF BLOCK hierarchy is preserved after import into Blender -(BLOCKs as groups on layer19, INSERTs as dupliGroups on target layer). - -Supported properties: -visibility status, -frozen status, -thickness, -width, -color, -layer, -(todo v1.13: XDATA, grouped status) -It is recommended to use DXF-object properties for assign Blender materials. - -Notes: -- Recommend that you run 'RemoveDoubles' on each imported mesh after using this script -- Blocks are created on layer 19 then referenced at each insert point. -- support for DXF-files up to 160MB on systems with 1GB RAM -- DXF-files with over 1500 objects decrease import performance. -The problem is not the inefficiency of python-scripting but Blenders performance -in creating new objects in scene database - probably a database management problem. - -""" - -""" -History: - v1.0 - 2007/2008/2009 by migius - planned tasks: - -- (to see more, search for "--todo--" in script code) - -- command-line-mode/batch-mode - -- in-place-editing for dupliGroups - -- support for MLINE (is exported to r12 as BLOCK*Unnamed with LINEs) - -- support for MTEXT (is exported to r12 as TEXT???) - -- blender_object.properties['dxf_layer_name'] - -- better support for long dxf-layer-names - -- add configuration file.ini handles multiple material setups - -- added f_layerFilter - -- to-check: obj/mat/group/_mapping-idea from ideasman42 - -- curves: added "fill/non-fill" option for closed curves: CIRCLEs,ELLIPSEs,POLYLINEs - -- "normalize Z" option to correct non-planar figures - -- LINEs need "width" in 3d-space incl vGroups - -- support width_force for LINEs/ELLIPSEs = "solidify" - -- add better support for color_index BYLAYER=256, BYBLOCK=0 - -- bug: "oneMesh" produces irregularly errors - -- bug: Registry recall from hd_cache ?? only win32 bug?? - -- support DXF-definitions of autoshade: scene, lights and cameras - -- support ortho mode for VIEWs and VPORTs as cameras - - v1.12 - 2009.06.16 by migius - d7 fix for ignored BLOCKs (e.g. *X) which are members of other BLOCKs - v1.12 - 2009.05.27 by migius - d6 bugfix negative scaled INSERTs - isLeftHand(Matrix) check - v1.12 - 2009.05.26 by migius - d5 changed to the new 2.49 method Vector.cross() - d5 bugfix WORLDY(1,1,0) to (0,1,0) - v1.12 - 2009.04.11 by migius - d4 added DWG support, Stani Michiels idea for binding an extern DXF-DWG-converter - v1.12 - 2009.03.14 by migius - d3 removed all set()functions (problem with osx/python<2.4 reported by Blinkozo) - d3 code-cleaning - v1.12 - 2009.01.14 by migius - d2 temp patch for noname BLOCKS (*X,*U,*D) - v1.12 - 2008.11.16 by migius - d1 remove try_finally: cause not supported in python <2.5 - d1 add Bezier curves bevel radius support (default 1.0) - v1.12 - 2008.08.03 by migius - c2 warningfix: relocating of globals: layersmap, oblist - c2 modif UI: buttons newScene+targetLayer moved to start panel - v1.12 - 2008.07.04 by migius - c1 added control Curve's OrderU parameter - c1 modif UI: preset buttons X-2D-3D moved to start panel - b6 added handling exception of not registered LAYERs (Hammer-HL-editor DXF output) - b5 rebuild UI: global preset 2D for Curve-Import - b5 added UI-options: PL-MESH N+N plmesh_flip and normals_out - b5 added support for SPLINEs, added control OrderU parameter - b5 rewrote draw module for NURBS_curve and Bezier_curve - v1.12 - 2008.06.22 by migius - b4 change versioning system 1.0.12 -> 1.12 - b4 print at start version-info to console - b3 bugfix: ob.name conflict with existing meshes (different ob.name/mesh.name) - v1.0.12: 2008.05.24 by migius - b2 added support for LWPOLYLINEs - b2 added support for ProE in readerDXF.py - v1.0.12: 2008.02.08 by migius - b1 update: object = Object.Get(obname) -> f_getSceChild().getChildren() - a9 bugfix by non-existing tables views, vports, layers (Kai reported) - v1.0.12: 2008.01.17 by migius - a8 lately used INI-dir/filename persistently stored in Registry - a8 lately used DXF-dir/filename persistently stored in Registry - a7 fix missing layersmap{} for dxf-files without "section:layer" - a6 added support for XREF external referenced BLOCKs - a6 check for bug in AutoCAD2002:DXFr12export: ELLIPSE->POLYLINE_ARC fault angles - a6 support VIEWs and VPORTs as cameras: ortho and perspective mode - a6 save resources through ignoring unused BLOCKs (not-inserted or on frozen/blocked layers) - a6 added try_finally: f.close() for all IO-files - a6 added handling for TypeError raise - a5 bugfix f_getOCS for (0,0,z!=1.0) (ellipse in Kai's dxf) - a4 added to analyzeTool: report about VIEWs, VPORTs, unused/xref BLOCKs - a4 bugfix: individual support for 2D/3DPOLYLINE/POLYMESH - a4 added to UI: (*wip)BLOCK-(F): name filtering for BLOCKs - a4 added to UI: BLOCK-(n): filter noname/hatch BLOCKs *X... - a2 g_scale_as is no more GUI_A-variable - a2 bugfix "material": negative sign color_index - a2 added support for BLOCKs defined with origin !=(0,0,0) - a1 added 'global.reLocation-vector' option - - v1.0.11: 2007.11.24 by migius - c8 added 'curve_resolution_U' option - c8 added context_sensitivity for some UI-buttons - c8 bugfix ELLIPSE rotation, added closed_variant and caps - c7 rebuild UI: new layout, grouping and meta-buttons - c6 rewritten support for ELLIPSE mesh & curve representation - c6 restore selector-buttons for DXF-drawTypes: LINE & Co - c6 change header of INI/INF-files: # at begin - c6 apply scale(1,1,1) after glob.Scale for all mesh objects, not for curve objects. - c5 fixing 'material_on' option - c4 added "analyze DXF-file" UI-option: print LAYER/BLOCK-dependences into a textfile - c3 human-formating of data in INI-Files - c2 added "caps" for closed Bezier-curves - c2 added "set elevation" UI-option - c1 rewrite POLYLINE2d-arc-segments Bezier-interpreter - b9 many bugs fixed - b9 rewrite POLYLINE2d-arc-segments trimming (clean-trim) - b8 added "import from frozen layers" UI-option - b8 added "import from paper space" UI-option - b8 support Bezier curves for LINEs incl.thickness(0.0-10.0) - b8 added meshSmooth_on for circle/arc/polyline - b8 added vertexGroups for circle/arc - b7 added width_force for ARCs/CIRCLEs = "thin_box" option - b3 cleanup code, rename f_drawArc/Bulg->f_calcArc/Bulg - b2 fixing material assignment by LAYER+COLOR - b1 fixing Bezier curves representation of POLYLINEs-arc-segments - b0 added global_scale_presets: "yard/feet/inch to meter" - - v1.0.10: 2007.10.18 by migius - a6 bugfix CircleDrawCaps for OSX - a5 added two "curve_res" UI-buttons for Bezier curves representation - a5 improved Bezier curves representation of circles/arcs: correct handlers - a4 try to fix malformed endpoints of Blender curves of ARC/POLYLINE-arc segments. - a3 bugfix: open-POLYLINEs with end_point.loc==start_point.loc - a2 bugfix: f_transform for OCS=(0,0,-1) oriented objects - a1 added "fill_on=caps" option to draw top and bottom sides of CIRCLEs and ELLIPSEs - a1 rewrite f_CIRCLE.Draw: from Mesh.Primitive to Mesh - a1 bugfix "newScene"-mode: all Cylinders/Arcs were drawn at <0,0,0>location - - v1.0.beta09: 2007.09.02 by migius - g5 redesign UI: grouping of buttons - g3 update multi-import-mode: <*.*> button - g- added multi-import-mode: (path/*) for importing many dxf-files at once - g- added import into newScene - g- redesign UI: user presets, into newScene-import - f- cleanup code - f- bugfix: thickness for Bezier/Bsplines into Blender-curves - f- BlenderWiki documentation, on-line Manual - f- added import POLYLINE-Bsplines into Blender-NURBSCurves - f- added import POLYLINE-arc-segments into Blender-BezierCurves - f- added import POLYLINE-Bezier-curves into Blender-Curves - d5 rewrite: Optimization Levels, added 'directDrawing' - d4 added: f_set_thick(controlled by ini-parameters) - d4 bugfix: face-normals in objects with minus thickness - d4 added: placeholder'Empty'-size in f_Insert.draw - d3 rewrite f_Text.Draw: added support for all Text's parameters - d2 redesign: progressbar - e- tuning by ideasman42: better use of the Py API. - c- tuning by ideasman42 - b- rewrite f_Text.Draw rotation/transform - b- bugfix: POLYLINE-segment-intersection more reliable now - b- bugfix: circle:_thic, 'Empties':no material_assignment - b- added material assignment (from layer and/or color) - a- added empty, cylinder and UVsphere for POINTs - a- added support for 2d-POLYLINE: splines, fitted curves, fitted surfaces - a- redesign f_Drawer for block_definitions - a- rewrite import into Blender-Curve-Object - - v1.0.beta08 - 2007.07.27 by migius: "full 3d"-release - l- bugfix: solid_vgroups, clean:scene.objects.new() - l- redesign UI to standard Draw.Register+FileSelector, advanced_config_option - k- bugfix UI:fileSelect() for MacOSX os.listdir() - k- added reset/save/load for config-data - k- redesign keywords/drawTypes/Draw.Create_Buttons - j- new UI using UIBlock() with own FileSelector, cause problem Window.FileSelector() - i- rewritten Class:Settings for better config-parameter management - h- bugfix: face-normals in objects with minus thickness - h- added Vertex-Groups in POLYLINE and SOLID meshes, for easy material assignment - h- beautify code, whitespace->tabs - h- added settings.thic_force switch for forcing thickness - h- added "one Mesh" option for all entities from the same Layer, sorted in<br> - Vertex-Groups(color_name) (fewer objects = better import performance) - g- rewrote: insert-point-handle-object is a small tetrahedron - e- bugfix: closed-polymesh3d - - rewrote: UI, type_map.keys, f_drawer, all class_f_draw(added "settings" as attribut) - - added 2d/3d-support for Polyline_Width incl. angle intersection - beta07: 2007.06.19 by migius - - added 3d-support for LWPolylines - - added 2d/3d-support for Points - beta06: 2007.06.15 by migius - - cleanup code - - added 2d/3d-support for MINSERT=BlockArray in f_drawer, added f_rotXY_Vec - beta05: 2007.06.14 by migius - - added 2d/3d-support for 3d-PolyLine, PolyMesh and PolyFace - - added Global-Scale for size control of imported scenes - beta04: 2007.06.12 by migius - - rewrote the f_drawBulge for correct import the arc-segments of Polylines - beta03: 2007.06.10 by migius - - rewrote interface - beta02: 2007.06.09 by migius - - added 3d-support for Arcs and Circles - - added support for Object_Thickness(=height) - beta01: 2007.06.08 by migius - - added 3d-support for Blocks/Inserts within nested-structures - - rewrote f_transform for correct 3d-location/3d-rotation - - added 3d-support Lines, 3dFaces - - added 2d+3d-support for Solids and Traces - - v0.9 - 2007.01 by kitsu: (for 2.43) - - first draft of true POLYLINE import - - - - v0.8 - 2006.12 by kitsu: - - first draft of object space coordinates OCS import - - - - v0.5b - 2006.10 by kitsu: (for 2.42a) - - dxfReader.py - - color_map.py - -""" - -# -------------------------------------------------------------------------- -# DXF Import v1.0 by Ed Blake (AKA kitsu) and Remigiusz Fiedler (AKA migius) -# -------------------------------------------------------------------------- -# ***** 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 ***** -# -------------------------------------------------------------------------- - -import Blender -from Blender import Mathutils, BezTriple, Draw, Registry, sys,\ -Text3d, Window, Mesh, Material, Group, Curve -#from Blender.Mathutils import Vector, Matrix -#import bpy #not used yet -#import BPyMessages - -from dxfReader import readDXF -#from dxfReader import get_name, get_layer -from dxfReader import Object as dxfObject -from dxfColorMap import color_map -from math import log10, sqrt, radians, degrees, atan, cos, sin - -# osx-patch by Blinkozo -#todo: avoid additional modules, prefer Blender-build-in test routines -#import platform -#if platform.python_version() < '2.4': -# from sets import Set as set -#from sys import version_info -#ver = '%s.%s' % version_info[0:2] -# end osx-patch - -import subprocess -import os -if os.name != 'mac': - try: - import psyco - psyco.log(Blender.Get('tempdir')+"/blender.log-psyco") - #psyco.log() - psyco.full(memory=100) - psyco.profile(0.05, memory=100) - psyco.profile(0.2) - #print 'psyco imported' - except ImportError: - print 'psyco not imported' - -print '\n\n\n' -print 'DXF/DWG-Importer v%s *** start ***' %(__version__) #--------------------- - -SCENE = None -WORLDX = Mathutils.Vector((1,0,0)) -WORLDY = Mathutils.Vector((0,1,0)) -WORLDZ = Mathutils.Vector((0,0,1)) - -G_SCALE = 1.0 #(0.0001-1000) global scaling factor for all dxf data -G_ORIGIN_X = 0.0 #global translation-vector (x,y,z) in DXF units -G_ORIGIN_Y = 0.0 -G_ORIGIN_Z = 0.0 -MIN_DIST = 0.001 #cut-off value for sort out short-distance polyline-"duoble_vertex" -ARC_RESOLUTION = 64 #(4-500) arc/circle resolution - number of segments -ARC_RADIUS = 1.0 #(0.01-100) arc/circle radius for number of segments algorithm -CURV_RESOLUTION = 12 #(1-128) Bezier curves U-resolution -CURVARC_RESOLUTION = 4 #(3-32) resolution of circle represented as Bezier curve -THIN_RESOLUTION = 8 #(4-64) thin_cylinder arc_resolution - number of segments -MIN_THICK = MIN_DIST * 10.0 #minimal thickness by forced thickness -MIN_WIDTH = MIN_DIST * 10.0 #minimal width by forced width -TRIM_LIMIT = 3.0 #limit for triming of polylines-wide-segments (values:0.0 - 5.0) -ELEVATION = 0.0 #standard elevation = coordinate Z value - -BYBLOCK = 0 -BYLAYER = 256 -TARGET_LAYER = 3 #target blender_layer -GROUP_BYLAYER = 0 #(0/1) all entities from same layer import into one blender-group -LAYER_DEF_NAME = 'AAAA' #default layer name -LAYER_DEF_COLOR = 4 #default layer color -E_M = 0 -LAB = ". wip .. todo" #"*) parts under construction" -M_OBJ = 0 - -FILENAME_MAX = 180 #max length of path+file_name string (FILE_MAXDIR + FILE_MAXFILE) -MAX_NAMELENGTH = 17 #max_effective_obnamelength in blender =21=17+(.001) -INIFILE_DEFAULT_NAME = 'importDXF' -INIFILE_EXTENSION = '.ini' -INIFILE_HEADER = '#ImportDXF.py ver.1.0 config data' -INFFILE_HEADER = '#ImportDXF.py ver.1.0 analyze of DXF-data' - -AUTO = BezTriple.HandleTypes.AUTO -FREE = BezTriple.HandleTypes.FREE -VECT = BezTriple.HandleTypes.VECT -ALIGN = BezTriple.HandleTypes.ALIGN - -UI_MODE = True #activates UI-popup-print, if not multiple files imported - -#---- migration to 2.49------------------------------------------------- -if 'cross' in dir(Mathutils.Vector()): - #Draw.PupMenu('DXF exporter: Abort%t|This script version works for Blender up 2.49 only!') - def M_CrossVecs(v1,v2): - return v1.cross(v2) #for up2.49 - def M_DotVecs(v1,v2): - return v1.dot(v2) #for up2.49 -else: - def M_CrossVecs(v1,v2): - return Mathutils.CrossVecs(v1,v2) #for pre2.49 - def M_DotVecs(v1,v2): - return Mathutils.DotVecs(v1,v2) #for pre2.49 - - -#-------- DWG support ------------------------------------------ -extCONV_OK = True -extCONV = 'DConvertCon.exe' -extCONV_PATH = os.path.join(Blender.Get('scriptsdir'),extCONV) -if not os.path.isfile(extCONV_PATH): - extCONV_OK = False - extCONV_TEXT = 'DWG-Importer cant find external DWG-converter (%s) in Blender script directory.|\ -More details in online Help.' %extCONV -else: - if not os.sys.platform.startswith('win'): - # check if Wine installed: - if subprocess.Popen(('which', 'winepath'), stdout=subprocess.PIPE).stdout.read().strip(): - extCONV_PATH = 'wine %s'%extCONV_PATH - else: - extCONV_OK = False - extCONV_TEXT = 'The external DWG-converter (%s) needs Wine installed on your system.|\ -More details in online Help.' %extCONV -#print 'extCONV_PATH = ', extCONV_PATH - - - -class View: #----------------------------------------------------------------- - """Class for objects representing dxf VIEWs. - """ - def __init__(self, obj, active=None): - """Expects an object of type VIEW as input. - """ - if not obj.type == 'view': - raise TypeError, "Wrong type %s for VIEW object!" %obj.type - - self.type = obj.type - self.name = obj.get_type(2)[0] -# self.data = obj.data[:] - - - self.centerX = getit(obj, 10, 0.0) #view center pointX (in DCS) - self.centerY = getit(obj, 20, 0.0) #view center pointY (in DCS) - self.height = obj.get_type(40)[0] #view height (in DCS) - self.width = obj.get_type(41)[0] #view width (in DCS) - - self.dir = [0,0,0] - self.dir[0] = getit(obj, 11, 0.0) #view directionX from target (in WCS) - self.dir[1] = getit(obj, 21, 0.0) # - self.dir[2] = getit(obj, 31, 0.0) # - - self.target = [0,0,0] - self.target[0] = getit(obj, 12, 0.0) #target pointX(in WCS) - self.target[1] = getit(obj, 22, 0.0) # - self.target[2] = getit(obj, 32, 0.0) # - - self.length = obj.get_type(42)[0] #Lens length - self.clip_front = getit(obj, 43) #Front clipping plane (offset from target point) - self.clip_back = getit(obj, 44) #Back clipping plane (offset from target point) - self.twist = obj.get_type(50)[0] #view twist angle in degrees - - self.flags = getit(obj, 70, 0) - self.paperspace = self.flags & 1 # - - self.mode = obj.get_type(71)[0] #view mode (VIEWMODE system variable) - - def __repr__(self): - return "%s: name - %s, focus length - %s" %(self.__class__.__name__, self.name, self.length) - - - def draw(self, settings): - """for VIEW: generate Blender_camera. - """ - obname = 'vw_%s' %self.name # create camera object name - #obname = 'ca_%s' %self.name # create camera object name - obname = obname[:MAX_NAMELENGTH] - - if self.target == [0,0,0] and Mathutils.Vector(self.dir).length == 1.0: - cam= Camera.New('ortho', obname) - ob= SCENE.objects.new(cam) - cam.type = 'ortho' - cam.scale = 1.0 # for ortho cameras - else: - cam= Camera.New('persp', obname) - ob= SCENE.objects.new(cam) - cam.type = 'persp' - cam.angle = 60.0 # for persp cameras - if self.length: - #cam.angle = 2 * atan(17.5/self.length) * 180/pi - cam.lens = self.length #for persp cameras - # hack to update Camera>Lens setting (inaccurate as a focal length) - #curLens = cam.lens; cam.lens = curLens - # AutoCAD gets clip distance from target: - dist = Mathutils.Vector(self.dir).length - cam.clipEnd = dist - self.clip_back - cam.clipStart = dist - self.clip_front - - cam.drawLimits = 1 - cam.drawSize = 10 - - v = Mathutils.Vector(self.dir) -# print 'deb:view cam:', cam #------------ -# print 'deb:view self.target:', self.target #------------ -# print 'deb:view self.dir:', self.dir #------------ -# print 'deb:view self.twist:', self.twist #------------ -# print 'deb:view self.clip_front=%s, self.clip_back=%s, dist=%s' %(self.clip_front, self.clip_back, dist) #------------ - transform(v.normalize(), -self.twist, ob) - ob.loc = Mathutils.Vector(self.target) + Mathutils.Vector(self.dir) - return ob - - -class Vport: #----------------------------------------------------------------- - """Class for objects representing dxf VPORTs. - """ - def __init__(self, obj, active=None): - """Expects an object of type VPORT as input. - """ - if not obj.type == 'vport': - raise TypeError, "Wrong type %s for VPORT object!" %obj.type - - self.type = obj.type - self.name = obj.get_type(2)[0] -# self.data = obj.data[:] - #print 'deb:vport name, data:', self.name #------- - #print 'deb:vport data:', self.data #------- - - self.height = obj.get_type(40)[0] #vport height (in DCS) - self.centerX = getit(obj, 12, 0.0) #vport center pointX (in DCS) - self.centerY = getit(obj, 22, 0.0) #vport center pointY (in DCS) - self.width = self.height * obj.get_type(41)[0] #vport aspect ratio - width (in DCS) - - self.dir = [0,0,0] - self.dir[0] = getit(obj, 16, 0.0) #vport directionX from target (in WCS) - self.dir[1] = getit(obj, 26, 0.0) # - self.dir[2] = getit(obj, 36, 0.0) # - - self.target = [0,0,0] - self.target[0] = getit(obj, 17, 0.0) #target pointX(in WCS) - self.target[1] = getit(obj, 27, 0.0) # - self.target[2] = getit(obj, 37, 0.0) # - - self.length = obj.get_type(42)[0] #Lens length - self.clip_front = getit(obj, 43) #Front clipping plane (offset from target point) - self.clip_back = getit(obj, 44) #Back clipping plane (offset from target point) - self.twist = obj.get_type(51)[0] #view twist angle - - self.flags = getit(obj, 70, 0) - self.paperspace = self.flags & 1 # - - self.mode = obj.get_type(71)[0] #view mode (VIEWMODE system variable) - - def __repr__(self): - return "%s: name - %s, focus length - %s" %(self.__class__.__name__, self.name, self.length) - - def draw(self, settings): - """for VPORT: generate Blender_camera. - """ - obname = 'vp_%s' %self.name # create camera object name - #obname = 'ca_%s' %self.name # create camera object name - obname = obname[:MAX_NAMELENGTH] - - if self.target == [0,0,0] and Mathutils.Vector(self.dir).length == 1.0: - cam= Camera.New('ortho', obname) - ob= SCENE.objects.new(cam) - cam.type = 'ortho' - cam.scale = 1.0 # for ortho cameras - else: - cam= Camera.New('persp', obname) - ob= SCENE.objects.new(cam) - cam.type = 'persp' - cam.angle = 60.0 # for persp cameras - if self.length: - #cam.angle = 2 * atan(17.5/self.length) * 180/pi - cam.lens = self.length #for persp cameras - # hack to update Camera>Lens setting (inaccurate as a focal length) - #curLens = cam.lens; cam.lens = curLens - # AutoCAD gets clip distance from target: - dist = Mathutils.Vector(self.dir).length - cam.clipEnd = dist - self.clip_back - cam.clipStart = dist - self.clip_front - - cam.drawLimits = 1 - cam.drawSize = 10 - - v = Mathutils.Vector(self.dir) -# print 'deb:view cam:', cam #------------ -# print 'deb:view self.target:', self.target #------------ -# print 'deb:view self.dir:', self.dir #------------ -# print 'deb:view self.twist:', self.twist #------------ -# print 'deb:view self.clip_front=%s, self.clip_back=%s, dist=%s' %(self.clip_front, self.clip_back, dist) #------------ - transform(v.normalize(), -self.twist, ob) - ob.loc = Mathutils.Vector(self.target) + Mathutils.Vector(self.dir) - return ob - - - -class Layer: #----------------------------------------------------------------- - """Class for objects representing dxf LAYERs. - """ - def __init__(self, obj, name=None, color=None, frozen=None): - """Expects an dxfobject of type layer as input. - if no dxfobject - creates surogate layer with default parameters - """ - - if obj==None: - self.type = 'layer' - if name: self.name = name - else: self.name = LAYER_DEF_NAME - - if color: self.color = color - else: self.color = LAYER_DEF_COLOR - - if frozen!=None: self.frozen = frozen - else: self.frozen = 0 - else: - if obj.type=='layer': - self.type = obj.type - #self.data = obj.data[:] - if name: self.name = name - #self.bfname = name #--todo---see layernamesmap in f_getLayersmap --- - else: self.name = obj.get_type(2)[0] #layer name of object - - if color: self.color = color - else: self.color = obj.get_type(62)[0] #color of object - - if frozen!=None: self.frozen = frozen - else: - self.flags = obj.get_type(70)[0] - self.frozen = self.flags & 1 - - def __repr__(self): - return "%s: name - %s, color - %s" %(self.__class__.__name__, self.name, self.color) - - - -def getit(obj, typ, default=None): #------------------------------------------ - """Universal procedure for geting data from list/objects. - """ - it = default - if type(obj) == list: #if obj is a list, then searching in a list - for item in obj: - #print 'deb:getit item, type(item)', item, type(item) - try: - if item[0] == typ: - it = item[1] - break #as soon as the first found - except: - # --todo-- I found one case where item was a text instance - # that failed with no __getitem__ - pass - else: #else searching in Object with get_type-Methode - item = obj.get_type(typ) - if item: - it = item[0] - #print 'deb:getit:typ, it', typ, it #---------- - return it - - - -def get_extrusion(data): #------------------------------------------------- - """Find the axis of extrusion. - - Used to get from object_data the objects Object_Coordinate_System (ocs). - """ - #print 'deb:get_extrusion: data: \n', data #--------------- - vec = [0,0,1] - vec[0] = getit(data, 210, 0) # 210 = x - vec[1] = getit(data, 220, 0) # 220 = y - vec[2] = getit(data, 230, 1) # 230 = z - #print 'deb:get_extrusion: vec: ', vec #--------------- - return vec - - -#------------------------------------------ -def getSceneChild(name): - dudu = [i for i in SCENE.objects if i.name==name] -# dudu = [i for i in SCENE.getChildren() if i.name==name] - #print 'deb:getSceneChild %s -result: %s:' %(name,dudu) #----------------- - if dudu!=[]: return dudu[0] - return None - - -class Solid: #----------------------------------------------------------------- - """Class for objects representing dxf SOLID or TRACE. - """ - def __init__(self, obj): - """Expects an entity object of type solid or trace as input. - """ - if obj.type == 'trace': - obj.type = 'solid' - if not obj.type == 'solid': - raise TypeError, "Wrong type \'%s\' for solid/trace object!" %obj.type - - self.type = obj.type -# self.data = obj.data[:] - - self.space = getit(obj, 67, 0) - self.thic = getit(obj, 39, 0) - self.color_index = getit(obj, 62, BYLAYER) - - self.layer = getit(obj, 8, None) - self.extrusion = get_extrusion(obj) - self.points = self.get_points(obj) - - - - def get_points(self, data): - """Gets start and end points for a solid type object. - - Solids have 3 or 4 points and fixed codes for each value. - """ - - # start x, y, z and end x, y, z = 0 - a = [0, 0, 0] - b = [0, 0, 0] - c = [0, 0, 0] - d = [0, 0, 0] - a[0] = getit(data, 10, None) # 10 = x - a[1] = getit(data, 20, None) # 20 = y - a[2] = getit(data, 30, 0) # 30 = z - b[0] = getit(data, 11, None) - b[1] = getit(data, 21, None) - b[2] = getit(data, 31, 0) - c[0] = getit(data, 12, None) - c[1] = getit(data, 22, None) - c[2] = getit(data, 32, 0) - out = [a,b,c] - - d[0] = getit(data, 13, None) - if d[0] != None: - d[1] = getit(data, 23, None) - d[2] = getit(data, 33, 0) - out.append(d) - #print 'deb:solid.vertices:---------\n', out #----------------------- - return out - - - def __repr__(self): - return "%s: layer - %s, points - %s" %(self.__class__.__name__, self.layer, self.points) - - - def draw(self, settings): - """for SOLID: generate Blender_geometry. - """ - points = self.points - if not points: return - edges, faces = [], [] - l = len(self.points) - - obname = 'so_%s' %self.layer # create object name from layer name - obname = obname[:MAX_NAMELENGTH] - - vg_left, vg_right, vg_top, vg_bottom, vg_start, vg_end = [], [], [], [], [], [] - thic = set_thick(self.thic, settings) - if thic != 0: - thic_points = [[v[0], v[1], v[2] + thic] for v in points[:]] - if thic < 0.0: - thic_points.extend(points) - points = thic_points - else: - points.extend(thic_points) - - if l == 4: - faces = [[0,1,3,2], [4,6,7,5], [0,4,5,1], - [1,5,7,3], [3,7,6,2], [2,6,4,0]] - vg_left = [2,6,4,0] - vg_right = [1,5,7,3] - vg_top = [4,6,7,5] - vg_bottom = [0,1,3,2] - vg_start = [0,4,5,1] - vg_end = [3,7,6,2] - elif l == 3: - faces = [[0,1,2], [3,5,4], [0,3,4,1], [1,4,5,2], [2,5,3,0]] - vg_top = [3,4,5] - vg_bottom = [0,1,2] - vg_left = [2,5,3,0] - vg_right = [1,4,5,2] - vg_start = [0,3,4,1] - elif l == 2: faces = [[0,1,3,2]] - else: - if l == 4: faces = [[0,1,3,2]] - elif l == 3: faces = [[0,1,2]] - elif l == 2: edges = [[0,1]] - - if M_OBJ: obname, me, ob = makeNewObject() - else: - me = Mesh.New(obname) # create a new mesh - ob = SCENE.objects.new(me) # create a new mesh_object - me.verts.extend(points) # add vertices to mesh - if faces: me.faces.extend(faces) # add faces to the mesh - if edges: me.edges.extend(edges) # add faces to the mesh - - if settings.var['vGroup_on'] and not M_OBJ: - # each MeshSide becomes vertexGroup for easier material assignment --------------------- - replace = Mesh.AssignModes.ADD #or .AssignModes.ADD/REPLACE - if vg_left: me.addVertGroup('side.left') ; me.assignVertsToGroup('side.left', vg_left, 1.0, replace) - if vg_right:me.addVertGroup('side.right') ; me.assignVertsToGroup('side.right', vg_right, 1.0, replace) - if vg_top: me.addVertGroup('side.top') ; me.assignVertsToGroup('side.top', vg_top, 1.0, replace) - if vg_bottom:me.addVertGroup('side.bottom'); me.assignVertsToGroup('side.bottom',vg_bottom, 1.0, replace) - if vg_start:me.addVertGroup('side.start') ; me.assignVertsToGroup('side.start', vg_start, 1.0, replace) - if vg_end: me.addVertGroup('side.end') ; me.assignVertsToGroup('side.end', vg_end, 1.0, replace) - - transform(self.extrusion, 0, ob) - - return ob - -class Line: #----------------------------------------------------------------- - """Class for objects representing dxf LINEs. - """ - def __init__(self, obj): - """Expects an entity object of type line as input. - """ - if not obj.type == 'line': - raise TypeError, "Wrong type \'%s\' for line object!" %obj.type - self.type = obj.type -# self.data = obj.data[:] - - self.space = getit(obj, 67, 0) - self.thic = getit(obj, 39, 0) - #print 'deb:self.thic: ', self.thic #--------------------- - self.color_index = getit(obj, 62, BYLAYER) - - self.layer = getit(obj, 8, None) - self.extrusion = get_extrusion(obj) - self.points = self.get_points(obj) - - - def get_points(self, data): - """Gets start and end points for a line type object. - - Lines have a fixed number of points (two) and fixed codes for each value. - """ - # start x,y,z and end x,y,z = 0 - a = [0, 0, 0] - b = [0, 0, 0] - a[0] = getit(data, 10, None) # 10 = x - a[1] = getit(data, 20, None) # 20 = y - a[2] = getit(data, 30, 0) # 30 = z - b[0] = getit(data, 11, None) - b[1] = getit(data, 21, None) - b[2] = getit(data, 31, 0) - out = [a,b] - return out - - - def __repr__(self): - return "%s: layer - %s, points - %s" %(self.__class__.__name__, self.layer, self.points) - - - def draw(self, settings): - """for LINE: generate Blender_geometry. - """ - # Generate the geometery - #settings.var['curves_on']=False - - points = self.points - thic = set_thick(self.thic, settings) - width = 0.0 - if settings.var['lines_as'] == 4: # as thin_box - thic = settings.var['thick_min'] - width = settings.var['width_min'] - elif settings.var['lines_as'] == 3: # as thin cylinder - cyl_rad = 0.5 * settings.var['width_min'] - - elif settings.var['lines_as'] == 5: # LINE curve representation------------------------- - obname = 'li_%s' %self.layer # create object name from layer name - obname = obname[:MAX_NAMELENGTH] - - c = Curve.New(obname) # create new curve data - curve = c.appendNurb(BezTriple.New(points[0])) - curve.append(BezTriple.New(points[1])) - for point in curve: - point.handleTypes = [VECT, VECT] - point.radius = 1.0 - curve.flagU = 0 # 0 sets the curve not cyclic=open - c.setResolu(settings.var['curve_res']) - c.update() #important for handles calculation - - ob = SCENE.objects.new(c) # create a new curve_object - - #if False: # --todo-- better support for 210-group - if thic != 0.0: #hack: Blender2.45 curve-extrusion - t = thic * 0.5 - if abs(t) > 5.0: t = 5.0 * cmp(t,0) # Blender2.45 accepts only (0.0 - 5.0) - e = self.extrusion - c.setExt1(abs(t)) # curve-extrusion - ob.LocX += t * e[0] - ob.LocY += t * e[1] - ob.LocZ += t * e[2] - #c.setExt1(1.0) # curve-extrusion: Blender2.45 accepts only (0.0 - 5.0) - #ob.LocZ = t + self.loc[2] - #ob.SizeZ *= abs(t) - return ob - - else: # LINE mesh representation ------------------------------ - global activObjectLayer - global activObjectName - #print 'deb:draw:line.ob IN activObjectName: ', activObjectName #--------------------- - - if M_OBJ: obname, me, ob = makeNewObject() - else: - if activObjectLayer == self.layer and settings.var['one_mesh_on']: - obname = activObjectName - #print 'deb:line.draw obname from activObjectName: ', obname #--------------------- - ob = getSceneChild(obname) # open an existing mesh_object - #ob = SCENE.getChildren(obname) # open an existing mesh_object - #me = Mesh.Get(ob.name) # open objects mesh data - me = ob.getData(name_only=False, mesh=True) - else: - obname = 'li_%s' %self.layer # create object name from layer name - obname = obname[:MAX_NAMELENGTH] - me = Mesh.New(obname) # create a new mesh - ob = SCENE.objects.new(me) # create a new mesh_object - activObjectName = ob.name - activObjectLayer = self.layer - #print ('deb:line.draw new line.ob+mesh:"%s" created!' %ob.name) #--------------------- - - faces, edges = [], [] - n = len(me.verts) - - #if settings.var['width_force']: #--todo----------- - - if thic != 0: - t, e = thic, self.extrusion - #print 'deb:thic, extr: ', t, e #--------------------- - points.extend([[v[0]+t*e[0], v[1]+t*e[1], v[2]+t*e[2]] for v in points[:]]) - faces = [[0+n, 1+n, 3+n, 2+n]] - else: - edges = [[0+n, 1+n]] - - me.verts.extend(points) # adds vertices to global mesh - if faces: me.faces.extend(faces) # add faces to the mesh - if edges: me.edges.extend(edges) # add faces to the mesh - - if settings.var['vGroup_on'] and not M_OBJ: - # entities with the same color build one vertexGroup for easier material assignment ---- - ob.link(me) # link mesh to that object - vG_name = 'color_%s' %self.color_index - if edges: faces = edges - replace = Mesh.AssignModes.ADD #or .AssignModes.REPLACE or ADD - try: - me.assignVertsToGroup(vG_name, faces[0], 1.0, replace) - #print 'deb: existed vGroup:', vG_name #--------------------- - except: - me.addVertGroup(vG_name) - me.assignVertsToGroup(vG_name, faces[0], 1.0, replace) - #print 'deb: create new vGroup:', vG_name #--------------------- - - - #print 'deb:draw:line.ob OUT activObjectName: ', activObjectName #--------------------- - return ob - - - -class Point: #----------------------------------------------------------------- - """Class for objects representing dxf POINTs. - """ - def __init__(self, obj): - """Expects an entity object of type point as input. - """ - if not obj.type == 'point': - raise TypeError, "Wrong type %s for point object!" %obj.type - self.type = obj.type -# self.data = obj.data[:] - - self.space = getit(obj, 67, 0) - self.thic = getit(obj, 39, 0) - #print 'deb:self.thic: ', self.thic #--------------------- - self.color_index = getit(obj, 62, BYLAYER) - - self.layer = getit(obj, 8, None) - self.extrusion = get_extrusion(obj) - self.points = self.get_points(obj) - - - def get_points(self, data): - """Gets coordinates for a point type object. - - Points have fixed codes for each value. - """ - a = [0, 0, 0] - a[0] = getit(data, 10, None) # 10 = x - a[1] = getit(data, 20, None) # 20 = y - a[2] = getit(data, 30, 0) # 30 = z - out = [a] - return out - - - def __repr__(self): - return "%s: layer - %s, points - %s" %(self.__class__.__name__, self.layer, self.points) - - - def draw(self, settings): - """for POINT: generate Blender_geometry. - """ - points = self.points - obname = 'po_%s' %self.layer # create object name from layer name - obname = obname[:MAX_NAMELENGTH] - points_as = settings.var['points_as'] - thic = settings.var['thick_min'] - if thic < settings.var['dist_min']: thic = settings.var['dist_min'] - - if points_as in [1,3,4,5]: - if points_as in [1,5]: # as 'empty' - c = 'Empty' - elif points_as == 3: # as 'thin sphere' - res = settings.var['thin_res'] - c = Mesh.Primitives.UVsphere(res,res,thic) - elif points_as == 4: # as 'thin box' - c = Mesh.Primitives.Cube(thic) - ob = SCENE.objects.new(c, obname) # create a new object - transform(self.extrusion, 0, ob) - ob.loc = tuple(points[0]) - - elif points_as == 2: # as 'vertex' - global activObjectLayer - global activObjectName - #print 'deb:draw:point.ob IN activObjectName: ', activObjectName #--------------------- - if M_OBJ: obname, me, ob = makeNewObject() - else: - if activObjectLayer == self.layer and settings.var['one_mesh_on']: - obname = activObjectName - #print 'deb:draw:point.ob obname from activObjectName: ', obname #--------------------- - ob = getSceneChild(obname) # open an existing mesh_object - #ob = SCENE.getChildren(obname) # open an existing mesh_object - me = ob.getData(name_only=False, mesh=True) - #me = Mesh.Get(ob.name) # open objects mesh data - else: - me = Mesh.New(obname) # create a new mesh - ob = SCENE.objects.new(me) # create a new mesh_object - activObjectName = ob.name - activObjectLayer = self.layer - #print ('deb:draw:point new point.ob+mesh:"%s" created!' %ob.name) #--------------------- - me.verts.extend(points) # add vertices to mesh - - return ob - - - -class Polyline: #----------------------------------------------------------------- - """Class for objects representing dxf POLYLINEs. - """ - def __init__(self, obj): - """Expects an entity object of type polyline as input. - """ - #print 'deb:polyline.init.START:----------------' #------------------------ - if not obj.type == 'polyline': - raise TypeError, "Wrong type %s for polyline object!" %obj.type - self.type = obj.type -# self.data = obj.data[:] - - self.space = getit(obj, 67, 0) - self.elevation = getit(obj, 30, 0) - #print 'deb:elevation: ', self.elevation #--------------- - self.thic = getit(obj, 39, 0) - self.color_index = getit(obj, 62, BYLAYER) - - self.flags = getit(obj, 70, 0) - self.closed = self.flags & 1 # closed in the M direction - self.curved = self.flags & 2 # Bezier-curve-fit vertices have been added - self.spline = self.flags & 4 # NURBS-curve-fit vertices have been added - self.poly3d = self.flags & 8 # 3D-polyline - self.plmesh = self.flags & 16 # 3D-polygon mesh - self.closeN = self.flags & 32 # closed in the N direction - self.plface = self.flags & 64 # 3D-polyface mesh - self.contin = self.flags & 128 # the linetype pattern is generated continuously - - self.pltype='poly2d' # default is a 2D-polyline - if self.poly3d: self.pltype='poly3d' - elif self.plface: self.pltype='plface' - elif self.plmesh: self.pltype='plmesh' - - self.swidth = getit(obj, 40, 0) # default start width - self.ewidth = getit(obj, 41, 0) # default end width - #self.bulge = getit(obj, 42, None) # bulge of the segment - self.vectorsM = getit(obj, 71, None) # PolyMesh: expansion in M-direction / PolyFace: number of the vertices - self.vectorsN = getit(obj, 72, None) # PolyMesh: expansion in M-direction / PolyFace: number of faces - #self.resolM = getit(obj, 73, None) # resolution of surface in M direction - #self.resolN = getit(obj, 74, None) # resolution of surface in N direction - self.curvNoFitted = False - self.curvQuadrati = False - self.curvCubicBsp = False - self.curvBezier = False - curvetype = getit(obj, 75, 0) # type of curve/surface: 0=None/5=Quadric/6=Cubic/8=Bezier - if curvetype == 0: self.curvNoFitted = True - elif curvetype == 5: self.curvQuadrati = True - elif curvetype == 6: self.curvCubicBsp = True - elif curvetype == 8: self.curvBezier = True - - self.layer = getit(obj, 8, None) - self.extrusion = get_extrusion(obj) - - self.points = [] #list with vertices coordinats - self.faces = [] #list with vertices assigment to faces - #print 'deb:polyline.init.ENDinit:----------------' #------------ - - - - def __repr__(self): - return "%s: layer - %s, points - %s" %(self.__class__.__name__, self.layer, self.points) - - - - def doubles_out(self, settings, d_points): - """routine to sort out of double.vertices----------------------------- - """ - minimal_dist = settings.var['dist_min'] * 0.1 - dv_count = 0 - temp_points = [] - for i in xrange(len(d_points)-1): - point = d_points[i] - point2 = d_points[i+1] - #print 'deb:double.vertex p1,p2', point, point2 #------------------------ - delta = Mathutils.Vector(point2.loc) - Mathutils.Vector(point.loc) - if delta.length > minimal_dist: - temp_points.append(point) - else: - dv_count+=1 - #print 'deb:drawPoly2d double.vertex sort out! count=', dv_count #------------------------ - temp_points.append(d_points[-1]) #------ incl. last vertex ------------- - #if self.closed: temp_points.append(d_points[1]) #------ loop start vertex ------------- - d_points = temp_points #-----vertex.list without "double.vertices" - #print 'deb:drawPoly2d d_pointsList =after DV-outsorting=====:\n ', d_points #------------------------ - return d_points - - - def tribles_out(self, settings, d_points): - """routine to sort out of three_in_place.vertices----------------------------- - """ - minimal_dist = settings.var['dist_min'] * 0.1 - dv_count = 0 - temp_points = [] - for i in xrange(len(d_points)-2): - point1 = d_points[i] - point2 = d_points[i+1] - point3 = d_points[i+2] - #print 'deb:double.vertex p1,p2', point, point2 #------------------------ - delta12 = Mathutils.Vector(point2.loc) - Mathutils.Vector(point1.loc) - delta23 = Mathutils.Vector(point3.loc) - Mathutils.Vector(point2.loc) - if delta12.length < minimal_dist and delta23.length < minimal_dist: - dv_count+=1 - else: - temp_points.append(point1) - #print 'deb:drawPoly2d double.vertex sort out! count=', dv_count #------------------------ - point1 = d_points[-2] - point2 = d_points[-1] - delta12 = Mathutils.Vector(point2.loc) - Mathutils.Vector(point1.loc) - if delta12.length > minimal_dist: - temp_points.append(d_points[-2]) #------ incl. 2last vertex ------------- - temp_points.append(d_points[-1]) #------ incl. 1last vertex ------------- - #if self.closed: temp_points.append(d_points[1]) #------ loop start vertex ------------- - d_points = temp_points #-----vertex.list without "double.vertices" - #print 'deb:drawPoly2d d_pointsList =after DV-outsorting=====:\n ', d_points #------------------------ - return d_points - - - def draw(self, settings): #-------------%%%% DRAW POLYLINE %%%--------------- - """for POLYLINE: generate Blender_geometry. - """ - #print 'deb:drawPOLYLINE.START:----------------' #------------------------ - #print 'deb:POLYLINEdraw self.pltype:', self.pltype #------------------------ - #print 'deb:POLYLINEdraw self.points:\n', self.points #------------------------ - ob = [] - #---- 3dPolyFace - mesh with free topology - if self.pltype=='plface' and settings.drawTypes['plmesh']: - ob = self.drawPlFace(settings) - #---- 3dPolyMesh - mesh with ortogonal topology - elif self.pltype=='plmesh' and settings.drawTypes['plmesh']: - ob = self.drawPlMesh(settings) - - #---- 2dPolyline - plane polyline with arc/wide/thic segments - elif self.pltype=='poly2d' and settings.drawTypes['polyline']: - if settings.var['plines_as'] in [5,6]: # and self.spline: - ob = self.drawPolyCurve(settings) - else: - ob = self.drawPoly2d(settings) - - #---- 3dPolyline - non-plane polyline (thin segments = without arc/wide/thic) - elif self.pltype=='poly3d' and settings.drawTypes['pline3']: - if settings.var['plines3_as'] in [5,6]: # and self.spline: - ob = self.drawPolyCurve(settings) - else: - ob = self.drawPoly2d(settings) - - #---- Spline - curved polyline (thin segments = without arc/wide/thic) - elif self.pltype=='spline' and settings.drawTypes['spline']: - if settings.var['splines_as'] in [5,6]: - ob = self.drawPolyCurve(settings) - else: - ob = self.drawPoly2d(settings) - return ob - - - def drawPlFace(self, settings): #---- 3dPolyFace - mesh with free topology - """Generate the geometery of polyface. - """ - #print 'deb:drawPlFace.START:----------------' #------------------------ - points = [] - faces = [] - #print 'deb:len of pointsList ====== ', len(self.points) #------------------------ - for point in self.points: - if point.face: - faces.append(point.face) - else: - points.append(point.loc) - - if settings.var['plmesh_flip']: # ---------------------- - for face in faces: - face.reverse() - face = [face[-1]] + face[:-1] - - #print 'deb:drawPlFace: len of points_list:\n', len(points) #----------------------- - #print 'deb:drawPlFace: len of faces_list:\n', len(faces) #----------------------- - #print 'deb:drawPlFace: points_list:\n', points #----------------------- - #print 'deb:drawPlFace: faces_list:\n', faces #----------------------- - obname = 'pf_%s' %self.layer # create object name from layer name - obname = obname[:MAX_NAMELENGTH] - me = Mesh.New(obname) # create a new mesh - ob = SCENE.objects.new(me) # create a new mesh_object - me.verts.extend(points) # add vertices to mesh - me.faces.extend(faces) # add faces to the mesh - if settings.var['normals_out']: # ---------------------- - #me.flipNormals() - me.recalcNormals(0) - #me.update() - #print 'deb:drawPlFace: len of me.faces:\n', len(me.faces) #----------------------- - - if settings.var['meshSmooth_on']: # ---------------------- - for i in xrange(len(me.faces)): - me.faces[i].smooth = True - #me.Mode(AUTOSMOOTH) - transform(self.extrusion, 0, ob) - #print 'deb:drawPlFace.END:----------------' #------------------------ - return ob - - - - def drawPlMesh(self, settings): #---- 3dPolyMesh - mesh with orthogonal topology - """Generate the geometery of polymesh. - """ - #print 'deb:polymesh.draw.START:----------------' #------------------------ - #points = [] - #print 'deb:len of pointsList ====== ', len(self.points) #------------------------ - faces = [] - m = self.vectorsM - n = self.vectorsN - for j in xrange(m - 1): - for i in xrange(n - 1): - nn = j * n - faces.append([nn+i, nn+i+1, nn+n+i+1, nn+n+i]) - - if self.closed: #mesh closed in N-direction - nn = (m-1)*n - for i in xrange(n - 1): - faces.append([nn+i, nn+i+1, i+1, i]) - - if self.closeN: #mesh closed in M-direction - for j in xrange(m-1): - nn = j * n - faces.append([nn+n-1, nn, nn+n, nn+n-1+n]) - - if self.closed and self.closeN: #mesh closed in M/N-direction - faces.append([ (n*m)-1, (m-1)*n, 0, n-1]) - - #print 'deb:len of points_list:\n', len(points) #----------------------- - #print 'deb:faces_list:\n', faces #----------------------- - obname = 'pm_%s' %self.layer # create object name from layer name - obname = obname[:MAX_NAMELENGTH] - me = Mesh.New(obname) # create a new mesh - ob = SCENE.objects.new(me) # create a new mesh_object - me.verts.extend([point.loc for point in self.points]) # add vertices to mesh - me.faces.extend(faces) # add faces to the mesh - if settings.var['normals_out']: # ---------------------- - #me.flipNormals() - me.recalcNormals(0) - #me.update() - if settings.var['meshSmooth_on']: # ---------------------- - for i in xrange(len(faces)): - me.faces[i].smooth = True - #me.Mode(AUTOSMOOTH) - - transform(self.extrusion, 0, ob) - #print 'deb:polymesh.draw.END:----------------' #------------------------ - return ob - - - def drawPolyCurve(self, settings): #---- Polyline - draw as Blender-curve - """Generate the geometery of polyline as Blender-curve. - """ - #print 'deb:polyline2dCurve.draw.START:----------------' #--- - if len(self.points) < 2: - #print 'deb:drawPoly2d exit, cause POLYLINE has less than 2 vertices' #--------- - return - - if self.spline: pline_typ = 'ps' # Polyline-NURBSpline - elif self.curved: pline_typ = 'pc' # Polyline-BezierCurve - else: pline_typ = 'pl' # Polyline classic - obname = '%s_%s' %(pline_typ, self.layer) # create object_name from layer name - obname = obname[:MAX_NAMELENGTH] - d_points = [] - - if settings.var['Z_force_on']: - self.elevation = settings.var['Z_elev'] - for point in self.points: - point.loc[2] = self.elevation - d_points.append(point) - else: #for DXFr10-format: update all points[].loc[2] == None -> 0.0 - for point in self.points: - if point.loc[2] == None: - point.loc[2] = self.elevation - d_points.append(point) - - #d_points = self.tribles_out(settings, d_points) - #d_points = self.doubles_out(settings, d_points) - #print 'deb:drawPolyCurve d_pointsList =after DV-outsorting=====:\n ', d_points #------------------------ - - thic = set_thick(self.thic, settings) - if thic != 0.0: #hack: Blender<2.45 curve-extrusion - LocZ = d_points[0].loc[2] - temp_points = [] - for point in d_points: - point.loc[2] = 0.0 - temp_points.append(point) - d_points = temp_points - - #print 'deb:polyline2dCurve.draw d_points=', d_points #--------------- - pline = Curve.New(obname) # create new curve data - #pline.setResolu(24) #--todo----- - - if self.spline: # NURBSplines-----OK----- - #print 'deb:polyline2dCurve.draw self.spline!' #--------------- - nurbs_points = [] - for d in d_points: - pkt = d.loc - pkt.append(d.weight) - nurbs_points.append(pkt) - firstpoint = nurbs_points[0] - curve = pline.appendNurb(firstpoint) - curve.setType(4) # set curve_type NURBS - print 'deb: dir(curve):', dir(curve[-1]) #---------------- - for point in nurbs_points[1:]: - curve.append(point) - #TODO: what is the trick for bevel radius? curve[-1].radius = 1.0 - if self.closed: - curve.flagU = 1+0 # Set curve cyclic=close and uni - else: - curve.flagU = 0+2 # Set curve not cyclic=open - try: curve.orderU = 5 # works only with >2.46svn080625 - except AttributeError: pass - #print 'deb: dir(curve):', dir(curve) #---------------- - - elif self.curved: #--SPLINE as Bezier-curves---wip------ - #print 'deb:polyline2dCurve.draw self.curved!' #--------------- - begtangent, endtangent = None, None - if d_points[0].tangent: - begtangent = d_points[0] - d_points = d_points[1:] - if d_points[-1].tangent: - endtangent = d_points[-1] - d_points = d_points[:-1] - curve = pline.appendNurb(BezTriple.New(d_points[0])) - for p in d_points[1:]: - curve.append(BezTriple.New(p)) - for point in curve: - point.handleTypes = [AUTO, AUTO] - point.radius = 1.0 - #curve.setType(1) #Bezier curve - if self.closed: - curve.flagU = 5 #1 # Set curve cyclic=close - else: - curve.flagU = 4 #0 # Set curve not cyclic=open - if begtangent: - #print 'deb:polyline2dCurve.draw curve[0].vec:', curve[0].vec #----- - #print 'deb:polyline2dCurve.draw begtangent:', begtangent #----- - p0h1,p0,p0h2 = curve[0].vec - p0h1 = [p0h1[i]+begtangent[i] for i in range(3)] - curve.__setitem__(0,BezTriple.New(p0h1+p0+p0h2)) - curve[0].handleTypes = [FREE, ALIGN] #remi--todo----- - curve[0].radius = 1.0 - if endtangent: - #print 'deb:polyline2dCurve.draw curve[-1].vec:', curve[-1].vec #----- - #print 'deb:polyline2dCurve.draw endtangent:', endtangent #----- - p0h1,p0,p0h2 = curve[-1].vec - p0h2 = [p0h2[i]+endtangent[i] for i in range(3)] - #print 'deb:drawPlineCurve: p0h2:', p0h2 #---------- - curve.__setitem__(-1,BezTriple.New(p0h1+p0+p0h2)) - #print 'deb:polyline2dCurve.draw curve[-1].vec:', curve[-1].vec #----- - curve[-1].handleTypes = [ALIGN, FREE] #remi--todo----- - curve[-1].radius = 1.0 - - - - else: #-- only straight line- and arc-segments----OK------ - #print 'deb:polyline2dCurve.draw curve:', curve #----- - points = [] - arc_res = settings.var['curve_arc'] - prevHandleType = VECT - #d_points.append(d_points[0]) #------ first vertex added at the end of list -------- - #curve.setType(0) #polygon_type of Blender_curve - for i in xrange(len(d_points)): - point1 = d_points[i] - #point2 = d_points[i+1] - #----- optimised Bezier-Handles calculation -------------------------------- - #print 'deb:drawPlineCurve: i:', i #--------- - if point1.bulge and not (i == len(d_points)-1 and point1.bulge and not self.closed): - if i == len(d_points)-1: point2 = d_points[0] - else: point2 = d_points[i+1] - - - # calculate additional points for bulge - VectorTriples = calcBulge(point1, point2, arc_res, triples=True) - - if prevHandleType == FREE: - #print 'deb:drawPlineCurve: VectorTriples[0]:', VectorTriples[0] #--------- - VectorTriples[0][:3] = prevHandleVect - #print 'deb:drawPlineCurve: VectorTriples[0]:', VectorTriples[0] #--------- - - if i == 0: curve = pline.appendNurb(BezTriple.New(VectorTriples[0])) - else: curve.append(BezTriple.New(VectorTriples[0])) - curve[-1].handleTypes = [prevHandleType, FREE] - curve[-1].radius = 1.0 - - for p in VectorTriples[1:-1]: - curve.append(BezTriple.New(p)) - curve[-1].handleTypes = [FREE, FREE] - curve[-1].radius = 1.0 - - prevHandleVect = VectorTriples[-1][:3] - prevHandleType = FREE - #print 'deb:drawPlineCurve: prevHandleVect:', prevHandleVect #--------- - else: - #print 'deb:drawPlineCurve: else' #---------- - if prevHandleType == FREE: - VectorTriples = prevHandleVect + list(point1) + list(point1) - #print 'deb:drawPlineCurve: VectorTriples:', VectorTriples #--------- - curve.append(BezTriple.New(VectorTriples)) - curve[-1].handleTypes = [FREE, VECT] - prevHandleType = VECT - curve[-1].radius = 1.0 - else: - if i == 0: curve = pline.appendNurb(BezTriple.New(point1.loc)) - else: curve.append(BezTriple.New(point1.loc)) - curve[-1].handleTypes = [VECT, VECT] - curve[-1].radius = 1.0 - #print 'deb:drawPlineCurve: curve[-1].vec[0]', curve[-1].vec[0] #---------- - - if self.closed: - curve.flagU = 1 # Set curve cyclic=close - if prevHandleType == FREE: - #print 'deb:drawPlineCurve:closed curve[0].vec:', curve[0].vec #---------- - #print 'deb:drawPlineCurve:closed curve[0].handleTypes:', curve[0].handleTypes #---------- - prevHandleType2 = curve[0].handleTypes[1] - p0h1,p0,p0h2 = curve[0].vec - #print 'deb:drawPlineCurve:closed p0h1:', p0h1 #---------- - p0h1 = prevHandleVect - #p0h1 = [0,0,0] - #print 'deb:drawPlineCurve:closed p0h1:', p0h1 #---------- - #curve[0].vec = [p0h1,p0,p0h2] - curve.__setitem__(0,BezTriple.New(p0h1+p0+p0h2)) - - curve[0].handleTypes = [FREE,prevHandleType2] - curve[0].radius = 1.0 - #print 'deb:drawPlineCurve:closed curve[0].vec:', curve[0].vec #---------- - #print 'deb:drawPlineCurve:closed curve[0].handleTypes:', curve[0].handleTypes #---------- - else: - curve[0].handleTypes[0] = VECT - curve[0].radius = 1.0 - else: - curve.flagU = 0 # Set curve not cyclic=open - - if settings.var['fill_on']: - pline.setFlag(6) # 2+4 set top and button caps - else: - pline.setFlag(pline.getFlag() & ~6) # dont set top and button caps - - pline.setResolu(settings.var['curve_res']) - pline.update() - ob = SCENE.objects.new(pline) # create a new curve_object - - if thic != 0.0: #hack: Blender<2.45 curve-extrusion - thic = thic * 0.5 - pline.setExt1(1.0) # curve-extrusion accepts only (0.0 - 2.0) - ob.LocZ = thic + LocZ - - transform(self.extrusion, 0, ob) - if thic != 0.0: - ob.SizeZ *= abs(thic) - - #print 'deb:polyline2dCurve.draw.END:----------------' #----- - return ob - - - def drawPoly2d(self, settings): #---- 2dPolyline - plane lines/arcs with wide/thic - """Generate the geometery of regular polyline. - """ - #print 'deb:polyline2d.draw.START:----------------' #------------------------ - points = [] - d_points = [] - swidths = [] - ewidths = [] - swidth_default = self.swidth #default start width of POLYLINEs segments - ewidth_default = self.ewidth #default end width of POLYLINEs segments - #print 'deb:drawPoly2d self.swidth=', self.swidth #------------------------ - thic = set_thick(self.thic, settings) - if self.spline: pline_typ = 'ps' - elif self.curved: pline_typ = 'pc' - else: pline_typ = 'pl' - obname = '%s_%s' %(pline_typ, self.layer) # create object_name from layer name - obname = obname[:MAX_NAMELENGTH] - - if len(self.points) < 2: - #print 'deb:drawPoly2d exit, cause POLYLINE has less than 2 vertices' #--------- - return - - if settings.var['Z_force_on']: - self.elevation = settings.var['Z_elev'] - for point in self.points: - point.loc[2] = self.elevation - d_points.append(point) - else: #for DXFr10-format: update all non-existing LocZ points[].loc[2] == None -> 0.0 elevation - for point in self.points: - if point.loc[2] == None: - point.loc[2] = self.elevation - d_points.append(point) - #print 'deb:drawPoly2d len of d_pointsList ====== ', len(d_points) #------------------------ - #print 'deb:drawPoly2d d_pointsList ======:\n ', d_points #------------------------ - - - #if closed polyline, add duplic of the first vertex at the end of pointslist - if self.closed: #new_b8 - if d_points[-1].loc != d_points[0].loc: # if not equal, then set the first at the end of pointslist - d_points.append(d_points[0]) - else: - if d_points[-1].loc == d_points[0].loc: # if equal, then set to closed, and modify the last point - d_points[-1] = d_points[0] - self.closed = True - #print 'deb:drawPoly2d len of d_pointsList ====== ', len(d_points) #------------------------ - #print 'deb:drawPoly2d d_pointsList ======:\n ', d_points #------------------------ - - d_points = self.doubles_out(settings, d_points) - #print 'deb:drawPolyCurve d_pointsList =after DV-outsorting=====:\n ', d_points #------------------------ - - #print 'deb:drawPoly2d len of d_pointsList ====== ', len(d_points) #------------------------ - if len(d_points) < 2: #if too few vertex, then return - #print 'deb:drawPoly2d corrupted Vertices' #--------- - return - - # analyze of straight- and bulge-segments - # generation of additional points for bulge segments - arc_res = settings.var['arc_res']/sqrt(settings.var['arc_rad']) - wide_segment_exist = False - bulg_points = [] # for each point set None (or center for arc-subPoints) - for i in xrange(len(d_points)-1): - point1 = d_points[i] - point2 = d_points[i+1] - #print 'deb:drawPoly2d_bulg tocalc.point1:', point1 #------------------------ - #print 'deb:drawPoly2d_bulg tocalc.point2:', point2 #------------------------ - - swidth = point1.swidth - ewidth = point1.ewidth - #print 'deb:drawPoly2d point1.swidth=', swidth #------------------------ - if swidth == None: swidth = swidth_default - if ewidth == None: ewidth = ewidth_default - if swidth != 0.0 or ewidth != 0.0: wide_segment_exist = True - #print 'deb:drawPoly2d vertex_swidth=', swidth #------------------------ - - if settings.var['width_force']: # force minimal width for thin segments - width_min = settings.var['width_min'] - if swidth < width_min: swidth = width_min - if ewidth < width_min: ewidth = width_min - if not settings.var['width_on']: # then force minimal width for all segments - swidth = width_min - ewidth = width_min - - #if point1.bulge and (i < (len(d_points)-1) or self.closed): - if point1.bulge and i < (len(d_points)-1): #10_b8 - verts, center = calcBulge(point1, point2, arc_res) #calculate additional points for bulge - points.extend(verts) - delta_width = (ewidth - swidth) / len(verts) - width_list = [swidth + (delta_width * ii) for ii in xrange(len(verts)+1)] - swidths.extend(width_list[:-1]) - ewidths.extend(width_list[1:]) - bulg_list = [center for ii in xrange(len(verts))] - #the last point in bulge has index False for better indexing of bulg_end! - bulg_list[-1] = None - bulg_points.extend(bulg_list) - - else: - points.append(point1.loc) - swidths.append(swidth) - ewidths.append(ewidth) - bulg_points.append(None) - points.append(d_points[-1].loc) - - - #--calculate width_vectors: left-side- and right-side-points ---------------- - # 1.level:IF width --------------------------------------- - if (settings.var['width_on'] and wide_segment_exist) or settings.var['width_force']: - #new_b8 points.append(d_points[0].loc) #temporarly add first vertex at the end (for better loop) - dist_min05 = 0.5 * settings.var['dist_min'] #minimal width for zero_witdh - - pointsLs = [] # list of left-start-points - pointsLe = [] # list of left-end-points - pointsRs = [] # list of right-start-points - pointsRe = [] # list of right-end-points - pointsW = [] # list of all border-points - #rotMatr90 = Mathutils.Matrix(rotate 90 degree around Z-axis) = normalvectorXY - rotMatr90 = Mathutils.Matrix([0, -1, 0], [1, 0, 0], [0, 0, 1]) - bulg_in = False - last_bulg_point = False - for i in xrange(len(points)-1): - point1 = points[i] - point2 = points[i+1] - point1vec = Mathutils.Vector(point1) - point2vec = Mathutils.Vector(point2) - swidth05 = swidths[i] * 0.5 - ewidth05 = ewidths[i] * 0.5 - if swidth05 == 0: swidth05 = dist_min05 - if ewidth05 == 0: ewidth05 = dist_min05 - normal_vector = rotMatr90 * (point2vec-point1vec).normalize() - if last_bulg_point: - last_bulg_point = False - bulg_in = True - elif bulg_points[i] != None: - centerVec = Mathutils.Vector(bulg_points[i]) - if bulg_points[i+1] == None: last_bulg_point = True - bulg_in = True - else: bulg_in = False - - if bulg_in: - #makes clean intersections for arc-segments - radius1vec = point1vec - centerVec - radius2vec = point2vec - centerVec - angle = Mathutils.AngleBetweenVecs(normal_vector, radius1vec) - if angle < 90.0: - normal_vector1 = radius1vec.normalize() - normal_vector2 = radius2vec.normalize() - else: - normal_vector1 = - radius1vec.normalize() - normal_vector2 = - radius2vec.normalize() - - swidth05vec = swidth05 * normal_vector1 - ewidth05vec = ewidth05 * normal_vector2 - pointsLs.append(point1vec + swidth05vec) #vertex left start - pointsRs.append(point1vec - swidth05vec) #vertex right start - pointsLe.append(point2vec + ewidth05vec) #vertex left end - pointsRe.append(point2vec - ewidth05vec) #vertex right end - - else: - swidth05vec = swidth05 * normal_vector - ewidth05vec = ewidth05 * normal_vector - pointsLs.append(point1vec + swidth05vec) #vertex left start - pointsRs.append(point1vec - swidth05vec) #vertex right start - pointsLe.append(point2vec + ewidth05vec) #vertex left end - pointsRe.append(point2vec - ewidth05vec) #vertex right end - - # additional last point is also calculated - #pointsLs.append(pointsLs[0]) - #pointsRs.append(pointsRs[0]) - #pointsLe.append(pointsLe[0]) - #pointsRe.append(pointsRe[0]) - - pointsLc, pointsRc = [], [] # lists Left/Right corners = intersection points - - # 2.level:IF width and corner-trim - if settings.var['pl_trim_on']: #optional clean corner-intersections - # loop preset - # set STARTpoints of the first point points[0] - if not self.closed: - pointsLc.append(pointsLs[0]) - pointsRc.append(pointsRs[0]) - else: - pointsLs.append(pointsLs[0]) - pointsRs.append(pointsRs[0]) - pointsLe.append(pointsLe[0]) - pointsRe.append(pointsRe[0]) - points.append(points[0]) - vecL3, vecL4 = pointsLs[0], pointsLe[0] - vecR3, vecR4 = pointsRs[0], pointsRe[0] - lenL = len(pointsLs)-1 - #print 'deb:drawPoly2d pointsLs():\n', pointsLs #---------------- - #print 'deb:drawPoly2d lenL, len.pointsLs():', lenL,',', len(pointsLs) #---------------- - bulg_in = False - last_bulg_point = False - - # LOOP: makes (ENDpoints[i],STARTpoints[i+1]) - for i in xrange(lenL): - if bulg_points[i] != None: - if bulg_points[i+1] == None: #makes clean intersections for arc-segments - last_bulg_point = True - if not bulg_in: - bulg_in = True - #pointsLc.extend((points[i], pointsLs[i])) - #pointsRc.extend((points[i], pointsRs[i])) - vecL1, vecL2 = vecL3, vecL4 - vecR1, vecR2 = vecR3, vecR4 - vecL3, vecL4 = pointsLs[i+1], pointsLe[i+1] - vecR3, vecR4 = pointsRs[i+1], pointsRe[i+1] - #compute left- and right-cornerpoints - #cornerpointL = Geometry.LineIntersect2D(vec1, vec2, vec3, vec4) - cornerpointL = Mathutils.LineIntersect(vecL1, vecL2, vecL3, vecL4) - cornerpointR = Mathutils.LineIntersect(vecR1, vecR2, vecR3, vecR4) - #print 'deb:drawPoly2d cornerpointL: ', cornerpointL #------------- - #print 'deb:drawPoly2d cornerpointR: ', cornerpointR #------------- - - # IF not cornerpoint THEN check if identic start-endpoints (=collinear segments) - if cornerpointL == None or cornerpointR == None: - if vecL2 == vecL3 and vecR2 == vecR3: - #print 'deb:drawPoly2d pointVec: ####### identic ##########' #---------------- - pointsLc.append(pointsLe[i]) - pointsRc.append(pointsRe[i]) - else: - pointsLc.extend((pointsLe[i],points[i+1],pointsLs[i+1])) - pointsRc.extend((pointsRe[i],points[i+1],pointsRs[i+1])) - else: - cornerpointL = cornerpointL[0] # because Mathutils.LineIntersect() -> (pkt1,pkt2) - cornerpointR = cornerpointR[0] - #print 'deb:drawPoly2d cornerpointL: ', cornerpointL #------------- - #print 'deb:drawPoly2d cornerpointR: ', cornerpointR #------------- - pointVec0 = Mathutils.Vector(points[i]) - pointVec = Mathutils.Vector(points[i+1]) - pointVec2 = Mathutils.Vector(points[i+2]) - #print 'deb:drawPoly2d pointVec0: ', pointVec0 #------------- - #print 'deb:drawPoly2d pointVec: ', pointVec #------------- - #print 'deb:drawPoly2d pointVec2: ', pointVec2 #------------- - # if diststance(cornerL-center-cornerR) < limiter * (seg1_endWidth + seg2_startWidth) - max_cornerDist = (vecL2 - vecR2).length + (vecL3 - vecR3).length - is_cornerDist = (cornerpointL - pointVec).length + (cornerpointR - pointVec).length - #corner_angle = Mathutils.AngleBetweenVecs((pointVec0 - pointVec),(pointVec - pointVec2)) - #print 'deb:drawPoly2d corner_angle: ', corner_angle #------------- - #print 'deb:drawPoly2d max_cornerDist, is_cornerDist: ', max_cornerDist, is_cornerDist #------------- - #if abs(corner_angle) < 90.0: - # intersection --------- limited by TRIM_LIMIT (1.0 - 5.0) - if is_cornerDist < max_cornerDist * settings.var['pl_trim_max']: - # clean corner intersection - pointsLc.append(cornerpointL) - pointsRc.append(cornerpointR) - else: - pointsLc.extend((pointsLe[i],points[i+1],pointsLs[i+1])) - pointsRc.extend((pointsRe[i],points[i+1],pointsRs[i+1])) - if not self.closed: - pointsLc.append(pointsLe[-1]) - pointsRc.append(pointsRe[-1]) - - # 2.level:IF width but no-trim - else: - # loop preset - # set STARTpoints of the first point points[0] - if not self.closed: - pointsLc.append(pointsLs[0]) - pointsRc.append(pointsRs[0]) - else: - pointsLs.append(pointsLs[0]) - pointsRs.append(pointsRs[0]) - pointsLe.append(pointsLe[0]) - pointsRe.append(pointsRe[0]) - points.append(points[0]) - vecL3, vecL4 = pointsLs[0], pointsLe[0] - vecR3, vecR4 = pointsRs[0], pointsRe[0] - lenL = len(pointsLs)-1 - #print 'deb:drawPoly2d pointsLs():\n', pointsLs #---------------- - #print 'deb:drawPoly2d lenL, len.pointsLs():', lenL,',', len(pointsLs) #---------------- - bulg_in = False - last_bulg_point = False - - # LOOP: makes (ENDpoints[i],STARTpoints[i+1]) - for i in xrange(lenL): - vecL1, vecL2 = vecL3, vecL4 - vecR1, vecR2 = vecR3, vecR4 - vecL3, vecL4 = pointsLs[i+1], pointsLe[i+1] - vecR3, vecR4 = pointsRs[i+1], pointsRe[i+1] - if bulg_points[i] != None: - #compute left- and right-cornerpoints - cornerpointL = Mathutils.LineIntersect(vecL1, vecL2, vecL3, vecL4) - cornerpointR = Mathutils.LineIntersect(vecR1, vecR2, vecR3, vecR4) - pointsLc.append(cornerpointL[0]) - pointsRc.append(cornerpointR[0]) - else: # IF non-bulg - pointsLc.extend((pointsLe[i],points[i+1],pointsLs[i+1])) - pointsRc.extend((pointsRe[i],points[i+1],pointsRs[i+1])) - if not self.closed: - pointsLc.append(pointsLe[-1]) - pointsRc.append(pointsRe[-1]) - - len1 = len(pointsLc) - #print 'deb:drawPoly2d len1:', len1 #----------------------- - #print 'deb:drawPoly2d len1 len(pointsLc),len(pointsRc):', len(pointsLc),len(pointsRc) #----------------------- - pointsW = pointsLc + pointsRc # all_points_List = left_side + right_side - #print 'deb:drawPoly2d pointsW():\n', pointsW #---------------- - - # 2.level:IF width and thickness --------------------- - if thic != 0: - thic_pointsW = [] - thic_pointsW.extend([[point[0], point[1], point[2]+thic] for point in pointsW]) - if thic < 0.0: - thic_pointsW.extend(pointsW) - pointsW = thic_pointsW - else: - pointsW.extend(thic_pointsW) - faces = [] - f_start, f_end = [], [] - f_bottom = [[num, num+1, len1+num+1, len1+num] for num in xrange(len1-1)] - f_top = [[num, len1+num, len1+num+1, num+1] for num in xrange(len1+len1, len1+len1+len1-1)] - f_left = [[num, len1+len1+num, len1+len1+num+1, num+1] for num in xrange(len1-1)] - f_right = [[num, num+1, len1+len1+num+1, len1+len1+num] for num in xrange(len1, len1+len1-1)] - - if self.closed: - f_bottom.append([len1-1, 0, len1, len1+len1-1]) #bottom face - f_top.append( [len1+len1+len1-1, len1+len1+len1+len1-1, len1+len1+len1, len1+len1+0]) #top face - f_left.append( [0, len1-1, len1+len1+len1-1, len1+len1]) #left face - f_right.append( [len1, len1+len1+len1, len1+len1+len1+len1-1, len1+len1-1]) #right face - else: - f_start = [[0, len1, len1+len1+len1, len1+len1]] - f_end = [[len1+len1-1, 0+len1-1, len1+len1+len1-1, len1+len1+len1+len1-1]] - - faces = f_left + f_right + f_bottom + f_top + f_start + f_end - #faces = f_bottom + f_top - #faces = f_left + f_right + f_start + f_end - #print 'deb:faces_list:\n', faces #----------------------- - if M_OBJ: obname, me, ob = makeNewObject() - else: - me = Mesh.New(obname) # create a new mesh - ob = SCENE.objects.new(me) # create a new mesh_object - me.verts.extend(pointsW) # add vertices to mesh - me.faces.extend(faces) # add faces to the mesh - - # each MeshSide becomes vertexGroup for easier material assignment --------------------- - # The mesh must first be linked to an object so the method knows which object to update. - # This is because vertex groups in Blender are stored in the object -- not in the mesh, - # which may be linked to more than one object. - if settings.var['vGroup_on'] and not M_OBJ: - # each MeshSide becomes vertexGroup for easier material assignment --------------------- - replace = Mesh.AssignModes.REPLACE #or .AssignModes.ADD - vg_left, vg_right, vg_top, vg_bottom = [], [], [], [] - for v in f_left: vg_left.extend(v) - for v in f_right: vg_right.extend(v) - for v in f_top: vg_top.extend(v) - for v in f_bottom: vg_bottom.extend(v) - me.addVertGroup('side.left') ; me.assignVertsToGroup('side.left', vg_left, 1.0, replace) - me.addVertGroup('side.right') ; me.assignVertsToGroup('side.right', vg_right, 1.0, replace) - me.addVertGroup('side.top') ; me.assignVertsToGroup('side.top', vg_top, 1.0, replace) - me.addVertGroup('side.bottom'); me.assignVertsToGroup('side.bottom',vg_bottom, 1.0, replace) - if not self.closed: - me.addVertGroup('side.start'); me.assignVertsToGroup('side.start', f_start[0], 1.0, replace) - me.addVertGroup('side.end') ; me.assignVertsToGroup('side.end', f_end[0], 1.0, replace) - - if settings.var['meshSmooth_on']: # left and right side become smooth ---------------------- - #if self.spline or self.curved: - smooth_len = len(f_left) + len(f_right) - for i in xrange(smooth_len): - me.faces[i].smooth = True - #me.Modes(AUTOSMOOTH) - - # 2.level:IF width, but no-thickness --------------------- - else: - faces = [] - faces = [[num, len1+num, len1+num+1, num+1] for num in xrange(len1 - 1)] - if self.closed: - faces.append([len1, 0, len1-1, len1+len1-1]) - if M_OBJ: obname, me, ob = makeNewObject() - else: - me = Mesh.New(obname) # create a new mesh - ob = SCENE.objects.new(me) # create a new mesh_object - me.verts.extend(pointsW) # add vertices to mesh - me.faces.extend(faces) # add faces to the mesh - - - # 1.level:IF no-width, but thickness --------------------- - elif thic != 0: - len1 = len(points) - thic_points = [] - thic_points.extend([[point[0], point[1], point[2]+thic] for point in points]) - if thic < 0.0: - thic_points.extend(points) - points = thic_points - else: - points.extend(thic_points) - faces = [] - faces = [[num, num+1, num+len1+1, num+len1] for num in xrange(len1 - 1)] - if self.closed: - faces.append([len1-1, 0, len1, 2*len1-1]) - if M_OBJ: obname, me, ob = makeNewObject() - else: - me = Mesh.New(obname) # create a new mesh - ob = SCENE.objects.new(me) # create a new mesh_object - me.verts.extend(points) # add vertices to mesh - me.faces.extend(faces) # add faces to the mesh - - if settings.var['meshSmooth_on']: # left and right side become smooth ---------------------- - #if self.spline or self.curved: - for i in xrange(len(faces)): - me.faces[i].smooth = True - #me.Modes(AUTOSMOOTH) - - # 1.level:IF no-width and no-thickness --------------------- - else: - edges = [[num, num+1] for num in xrange(len(points)-1)] - if self.closed: - edges.append([len(points)-1, 0]) - if M_OBJ: obname, me, ob = makeNewObject() - else: - me = Mesh.New(obname) # create a new mesh - ob = SCENE.objects.new(me) # create a new mesh_object - me.verts.extend(points) # add vertices to mesh - me.edges.extend(edges) # add edges to the mesh - - transform(self.extrusion, 0, ob) - #print 'deb:polyline.draw.END:----------------' #----------------------- - return ob - - - - -class Vertex(object): #----------------------------------------------------------------- - """Generic vertex object used by POLYLINEs, (and maybe others). - also used by class_LWPOLYLINEs but without obj-parameter - """ - - def __init__(self, obj=None): - """Initializes vertex data. - - The optional obj arg is an entity object of type vertex. - """ - #print 'deb:Vertex.init.START:----------------' #----------------------- - self.loc = [0,0,0] - self.face = [] - self.swidth = None #0 - self.ewidth = None #0 - self.bulge = 0 - self.tangent = False - self.weight = 1.0 - if obj is not None: - if not obj.type == 'vertex': - raise TypeError, "Wrong type %s for vertex object!" %obj.type - self.type = obj.type -# self.data = obj.data[:] - self.get_props(obj) - else: - pass - #print 'deb:Vertex.init.END:----------------' #------------------------ - - - def get_props(self, data): - """Gets coords for a VERTEX type object. - - Each vert can have a number of properties. - Verts should be coded as - 10:xvalue - 20:yvalue - 40:startwidth or 0 - 41:endwidth or 0 - 42:bulge or 0 - """ - self.x = getit(data, 10, None) - self.y = getit(data, 20, None) - self.z = getit(data, 30, None) - - self.flags = getit(data, 70, 0) # flags - self.curved = self.flags&1 # Bezier-curve-fit:additional-vertex - self.curved_t = self.flags&2 # Bezier-curve-fit:tangent exists - self.spline = self.flags&8 # NURBSpline-fit:additional-vertex - self.spline_c = self.flags&16 # NURBSpline-fit:control-vertex - self.poly3d = self.flags&32 # polyline3d:control-vertex - self.plmesh = self.flags&64 # polymesh3d:control-vertex - self.plface = self.flags&128 # polyface - - # if PolyFace.Vertex with Face_definition - if self.curved_t: - self.curve_tangent = getit(data, 50, None) # curve_tangent - if not self.curve_tangent==None: - self.tangent = True - #elif self.spline_c: # NURBSpline:control-vertex - # self.weight = getit(data, 41, 1.0) # weight od control point - - elif self.plface and not self.plmesh: - v1 = getit(data, 71, 0) # polyface:Face.vertex 1. - v2 = getit(data, 72, 0) # polyface:Face.vertex 2. - v3 = getit(data, 73, 0) # polyface:Face.vertex 3. - v4 = getit(data, 74, None) # polyface:Face.vertex 4. - self.face = [abs(v1)-1,abs(v2)-1,abs(v3)-1] - if v4 != None: - if abs(v4) != abs(v1): - self.face.append(abs(v4)-1) - else: #--parameter for polyline2d - self.swidth = getit(data, 40, None) # start width - self.ewidth = getit(data, 41, None) # end width - self.bulge = getit(data, 42, 0) # bulge of segment - - - def __len__(self): - return 3 - - - def __getitem__(self, key): - return self.loc[key] - - - def __setitem__(self, key, value): - if key in [0,1,2]: - self.loc[key] - - - def __iter__(self): - return self.loc.__iter__() - - - def __str__(self): - return str(self.loc) - - - def __repr__(self): - return "Vertex %s, swidth=%s, ewidth=%s, bulge=%s, face=%s" %(self.loc, self.swidth, self.ewidth, self.bulge, self.face) - - - def getx(self): - return self.loc[0] - def setx(self, value): - self.loc[0] = value - x = property(getx, setx) - - - def gety(self): - return self.loc[1] - def sety(self, value): - self.loc[1] = value - y = property(gety, sety) - - - def getz(self): - return self.loc[2] - def setz(self, value): - self.loc[2] = value - z = property(getz, setz) - - - -class Spline(Polyline): #----------------------------------------------------------------- - """Class for objects representing dxf SPLINEs. - """ - """Expects an entity object of type spline as input. -100 - Subclass marker (AcDbSpline) -210,220, 230 - Normal vector (omitted if the spline is nonplanar) X,Y,Z values of normal vector -70 - Spline flag (bit coded): - 1 = Closed spline - 2 = Periodic spline - 4 = Rational spline - 8 = Planar - 16 = Linear (planar bit is also set) -71 - Degree of the spline curve -72 - Number of knots -73 - Number of control points -74 - Number of fit points (if any) -42 - Knot tolerance (default = 0.0000001) -43 - Control-point tolerance (default = 0.0000001) -44 - Fit tolerance (default = 0.0000000001) -12,22,32 - Start tangent--may be omitted (in WCS). X,Y,Z values of start tangent--may be omitted (in WCS). -13,23, 33 - End tangent--may be omitted (in WCS). X,Y,Z values of end tangent--may be omitted (in WCS) -40 - Knot value (one entry per knot) -41 - Weight (if not 1); with multiple group pairs, are present if all are not 1 -10,20, 30 - Control points (in WCS) one entry per control point. -DXF: X value; APP: 3D point, Y and Z values of control points (in WCS) (one entry per control point) -11,21, 31 - Fit points (in WCS) one entry per fit point. - X,Y,Z values of fit points (in WCS) (one entry per fit point) - """ - def __init__(self, obj): - #print 'deb:Spline.START:----------------' #------------------------ - if not obj.type == 'spline': - raise TypeError, "Wrong type %s for spline object!" %obj.type - self.type = obj.type -# self.data = obj.data[:] - - # required data - self.num_points = obj.get_type(73)[0] - - # optional data (with defaults) - self.space = getit(obj, 67, 0) - - self.color_index = getit(obj, 62, BYLAYER) - - #self.elevation = getit(obj, 30, 0) - self.thic = 0 # getit(obj, 39, 0) - - width = 0 - self.swidth = width # default start width - self.ewidth = width # default end width - - self.flags = getit(obj, 70, 0) - self.closed = self.flags & 1 # closed spline - self.period = self.flags & 2 # Periodic spline - self.ration = self.flags & 4 # Rational spline - self.planar = self.flags & 8 # Planar - self.linear = self.flags & 16 # Linear (and Planar) - - self.curvNoFitted = False - self.curvQuadrati = False - self.curvCubicBsp = False - self.curvBezier = False - self.degree = getit(obj, 71, 0) # Degree of the spline curve - if self.degree == 0: self.curvNoFitted = True - elif self.degree == 1: self.curvQuadrati = True - elif self.degree == 2: self.curvCubicBsp = True - #elif self.degree == 3: self.curvBezier = True - #elif self.degree == 3: self.spline = True - - self.knotpk_len = getit(obj, 72, 0) # Number of knots - self.ctrlpk_len = getit(obj, 73, 0) # Number of control points - self.fit_pk_len = getit(obj, 74, 0) # Number of fit points (if any) - - #TODO: import SPLINE as Bezier curve directly, possible? - #print 'deb:Spline self.fit_pk_len=', self.fit_pk_len #------------------------ - #self.fit_pk_len = 0 # temp for debug - if self.fit_pk_len and settings.var['splines_as']==5: - self.spline = False - self.curved = True - else: - self.spline = True - self.curved = False - - self.knotpk_tol = getit(obj, 42, 0.0000001) # Knot tolerance (default = 0.0000001) - self.ctrlpk_tol = getit(obj, 43, 0.0000001) # Control-point tolerance (default = 0.0000001) - self.fit_pk_tol = getit(obj, 44, 0.0000000001) # Fit tolerance (default = 0.0000000001) - - self.layer = getit(obj, 8, None) - self.extrusion = get_extrusion(obj) - - self.pltype = 'spline' # spline is a 2D- or 3D-polyline - - self.points = self.get_points(obj.data) - #self.knots_val = self.get_knots_val(obj.data) # 40 - Knot value (one entry per knot) - #self.knots_wgh = self.get_knots_wgh(obj.data) # 41 - Weight (default 1) - - #print 'deb:Spline obj.data:\n', obj.data #------------------------ - #print 'deb:Spline self.points:\n', self.points #------------------------ - #print 'deb:Spline.ENDinit:----------------' #------------------------ - - - def get_points(self, data): - """Gets points for a spline type object. - - Splines have fixed number of verts, and - each vert can have a number of properties. - Verts should be coded as - 10:xvalue - 20:yvalue - for each vert - """ - point = None - points = [] - pointend = None - #point = Vertex() - if self.spline: # NURBSpline definition - for item in data: - #print 'deb:Spline.get_points spilne_item:', item #------------------------ - if item[0] == 10: # control point - if point: points.append(point) - point = Vertex() - point.curved = True - point.x = item[1] - elif item[0] == 20: # 20 = y - point.y = item[1] - elif item[0] == 30: # 30 = z - point.z = item[1] - elif item[0] == 41: # 41 = weight - point.weight = item[1] - #print 'deb:Spline.get_points control point:', point #------------------------ - - elif self.curved: # Bezier definition - for item in data: - #print 'deb:Spline.get_points curved_item:', item #------------------------ - if item[0] == 11: # fit point - if point: points.append(point) - point = Vertex() - point.tangent = False - point.x = item[1] - elif item[0] == 21: # 20 = y - point.y = item[1] - elif item[0] == 31: # 30 = z - point.z = item[1] - #print 'deb:Spline.get_points fit point:', point #------------------------ - - elif item[0] == 12: # start tangent - if point: points.append(point) - point = Vertex() - point.tangent = True - point.x = item[1] - elif item[0] == 22: # = y - point.y = item[1] - elif item[0] == 32: # = z - point.z = item[1] - #print 'deb:Spline.get_points fit begtangent:', point #------------------------ - - elif item[0] == 13: # end tangent - if point: points.append(point) - pointend = Vertex() - pointend.tangent = True - pointend.x = item[1] - elif item[0] == 23: # 20 = y - pointend.y = item[1] - elif item[0] == 33: # 30 = z - pointend.z = item[1] - #print 'deb:Spline.get_points fit endtangent:', pointend #------------------------ - points.append(point) - if self.curved and pointend: - points.append(pointend) - #print 'deb:Spline points:\n', points #------------------------ - return points - - def __repr__(self): - return "%s: layer - %s, points - %s" %(self.__class__.__name__, self.layer, self.points) - - - -class LWpolyline(Polyline): #------------------------------------------------------------- - """Class for objects representing dxf LWPOLYLINEs. - """ - def __init__(self, obj): - """Expects an entity object of type lwpolyline as input. - """ - #print 'deb:LWpolyline.START:----------------' #------------------------ - if not obj.type == 'lwpolyline': - raise TypeError, "Wrong type %s for polyline object!" %obj.type - self.type = obj.type -# self.data = obj.data[:] - - # required data - self.num_points = obj.get_type(90)[0] - - # optional data (with defaults) - self.space = getit(obj, 67, 0) - self.elevation = getit(obj, 38, 0) - self.thic = getit(obj, 39, 0) - self.color_index = getit(obj, 62, BYLAYER) - width = getit(obj, 43, 0) - self.swidth = width # default start width - self.ewidth = width # default end width - #print 'deb:LWpolyline width=', width #------------------------ - #print 'deb:LWpolyline elevation=', self.elevation #------------------------ - - self.flags = getit(obj, 70, 0) - self.closed = self.flags&1 # byte coded, 1 = closed, 128 = plinegen - - self.layer = getit(obj, 8, None) - self.extrusion = get_extrusion(obj) - - self.points = self.get_points(obj.data) - - self.pltype = 'poly2d' # LW-polyline is a 2D-polyline - self.spline = False - self.curved = False - - #print 'deb:LWpolyline.obj.data:\n', obj.data #------------------------ - #print 'deb:LWpolyline.ENDinit:----------------' #------------------------ - - - def get_points(self, data): - """Gets points for a polyline type object. - - LW-Polylines have no fixed number of verts, and - each vert can have a number of properties. - Verts should be coded as - 10:xvalue - 20:yvalue - 40:startwidth or 0 - 41:endwidth or 0 - 42:bulge or 0 - for each vert - """ - num = self.num_points - point = None - points = [] - for item in data: - if item[0] == 10: # 10 = x - if point: - points.append(point) - point = Vertex() - point.x = item[1] - point.z = self.elevation - elif item[0] == 20: # 20 = y - point.y = item[1] - elif item[0] == 40: # 40 = start width - point.swidth = item[1] - elif item[0] == 41: # 41 = end width - point.ewidth = item[1] - elif item[0] == 42: # 42 = bulge - point.bulge = item[1] - points.append(point) - return points - - - def __repr__(self): - return "%s: layer - %s, points - %s" %(self.__class__.__name__, self.layer, self.points) - - -class Text: #----------------------------------------------------------------- - """Class for objects representing dxf TEXT. - """ - def __init__(self, obj): - """Expects an entity object of type text as input. - """ - if not obj.type == 'text': - raise TypeError, "Wrong type %s for text object!" %obj.type - self.type = obj.type -# self.data = obj.data[:] - - # required data - self.height = 1.7 * obj.get_type(40)[0] #text.height - self.value = obj.get_type(1)[0] #The text string value - - # optional data (with defaults) - self.space = getit(obj, 67, 0) - self.color_index = getit(obj, 62, BYLAYER) - self.thic = getit(obj, 39, 0) - - self.rotation = getit(obj, 50, 0) # radians - self.width_factor = getit(obj, 41, 1) # Scaling factor along local x axis - self.oblique = getit(obj, 51, 0) # oblique angle: skew in degrees -90 <= oblique <= 90 - - #self.style = getit(obj, 7, 'STANDARD') # --todo---- Text style name (optional, default = STANDARD) - - #Text generation flags (optional, default = 0): - #2 = backward (mirrored in X), - #4 = upside down (mirrored in Y) - self.flags = getit(obj, 71, 0) - self.mirrorX, self.mirrorY = 1.0, 1.0 - if self.flags&2: self.mirrorX = - 1.0 - if self.flags&4: self.mirrorY = - 1.0 - - # vertical.alignment: 0=baseline, 1=bottom, 2=middle, 3=top - self.valignment = getit(obj, 73, 0) - #Horizontal text justification type (optional, default = 0) integer codes (not bit-coded) - #0=left, 1=center, 2=right - #3=aligned, 4=middle, 5=fit - self.halignment = getit(obj, 72, 0) - - self.layer = getit(obj, 8, None) - self.loc1, self.loc2 = self.get_loc(obj) - if self.loc2[0] != None and self.halignment != 5: - self.loc = self.loc2 - else: - self.loc = self.loc1 - self.extrusion = get_extrusion(obj) - - - def get_loc(self, data): - """Gets adjusted location for text type objects. - - If group 72 and/or 73 values are nonzero then the first alignment point values - are ignored and AutoCAD calculates new values based on the second alignment - point and the length and height of the text string itself (after applying the - text style). If the 72 and 73 values are zero or missing, then the second - alignment point is meaningless. - I don't know how to calc text size... - """ - # bottom left x, y, z and justification x, y, z = 0 - #x, y, z, jx, jy, jz = 0, 0, 0, 0, 0, 0 - x = getit(data, 10, None) #First alignment point (in OCS). - y = getit(data, 20, None) - z = getit(data, 30, 0.0) - jx = getit(data, 11, None) #Second alignment point (in OCS). - jy = getit(data, 21, None) - jz = getit(data, 31, 0.0) - return [x, y, z],[jx, jy, jz] - - - def __repr__(self): - return "%s: layer - %s, value - %s" %(self.__class__.__name__, self.layer, self.value) - - - def draw(self, settings): - """for TEXTs: generate Blender_geometry. - """ - obname = 'tx_%s' %self.layer # create object name from layer name - obname = obname[:MAX_NAMELENGTH] - txt = Text3d.New(obname) - ob = SCENE.objects.new(txt) # create a new text_object - - txt.setText(self.value) - txt.setSize(1.0) #Blender<2.45 accepts only (0.0 - 5.0) - #txt.setSize(self.height) - #txt.setWidth(self.bold) - #setLineSeparation(sep) - txt.setShear(self.oblique/90) - - thic = set_thick(self.thic, settings) - if thic != 0.0: - thic = self.thic * 0.5 - self.loc[2] += thic - txt.setExtrudeDepth(1.0) #Blender<2.45 accepts only (0.1 - 10.0) - if self.halignment == 0: - align = Text3d.LEFT - elif self.halignment == 1: - align = Text3d.MIDDLE - elif self.halignment == 2: - align = Text3d.RIGHT - else: - align = Text3d.LEFT - txt.setAlignment(align) - - if self.valignment == 1: - txt.setYoffset(0.0) - elif self.valignment == 2: - txt.setYoffset(- self.height * 0.5) - elif self.valignment == 3: - txt.setYoffset(- self.height) - - # move the object center to the text location - ob.loc = tuple(self.loc) - transform(self.extrusion, self.rotation, ob) - - # flip it and scale it to the text width - ob.SizeX *= self.height * self.width_factor * self.mirrorX - ob.SizeY *= self.height * self.mirrorY - if thic != 0.0: ob.SizeZ *= abs(thic) - return ob - - - -def set_thick(thickness, settings): - """Set thickness relative to settings variables. - - Set thickness relative to settings variables: - 'thick_on','thick_force','thick_min'. - Accepted also minus values of thickness - python trick: sign(x)=cmp(x,0) - """ - if settings.var['thick_force']: - if settings.var['thick_on']: - if abs(thickness) < settings.var['thick_min']: - thic = settings.var['thick_min'] * cmp(thickness,0) - else: thic = thickness - else: thic = settings.var['thick_min'] - else: - if settings.var['thick_on']: thic = thickness - else: thic = 0.0 - return thic - - - - -class Mtext: #----------------------------------------------------------------- - """Class for objects representing dxf MTEXT. - """ - - def __init__(self, obj): - """Expects an entity object of type mtext as input. - """ - if not obj.type == 'mtext': - raise TypeError, "Wrong type %s for mtext object!" %obj.type - self.type = obj.type -# self.data = obj.data[:] - - # required data - self.height = obj.get_type(40)[0] - self.width = obj.get_type(41)[0] - self.alignment = obj.get_type(71)[0] # alignment 1=TL, 2=TC, 3=TR, 4=ML, 5=MC, 6=MR, 7=BL, 8=BC, 9=BR - self.value = self.get_text(obj) # The text string value - - # optional data (with defaults) - self.space = getit(obj, 67, 0) - self.color_index = getit(obj, 62, BYLAYER) - self.rotation = getit(obj, 50, 0) # radians - - self.width_factor = getit(obj, 42, 1) # Scaling factor along local x axis - self.line_space = getit(obj, 44, 1) # percentage of default - - self.layer = getit(obj, 8, None) - self.loc = self.get_loc(obj) - self.extrusion = get_extrusion(obj) - - - def get_text(self, data): - """Reconstructs mtext data from dxf codes. - """ - primary = '' - secondary = [] - for item in data: - if item[0] == 1: # There should be only one primary... - primary = item[1] - elif item[0] == 3: # There may be any number of extra strings (in order) - secondary.append(item[1]) - if not primary: - #raise ValueError, "Empty Mtext Object!" - string = "Empty Mtext Object!" - if not secondary: - string = primary.replace(r'\P', '\n') - else: - string = ''.join(secondary)+primary - string = string.replace(r'\P', '\n') - return string - - - def get_loc(self, data): - """Gets location for a mtext type objects. - - Mtext objects have only one point indicating - """ - loc = [0, 0, 0] - loc[0] = getit(data, 10, None) - loc[1] = getit(data, 20, None) - loc[2] = getit(data, 30, 0.0) - return loc - - - def __repr__(self): - return "%s: layer - %s, value - %s" %(self.__class__.__name__, self.layer, self.value) - - - def draw(self, settings): - """for MTEXTs: generate Blender_geometry. - """ - # Now Create an object - obname = 'tm_%s' %self.layer # create object name from layer name - obname = obname[:MAX_NAMELENGTH] - txt = Text3d.New(obname) - ob = SCENE.objects.new(txt) # create a new text_object - - txt.setSize(1) - # Blender doesn't give access to its text object width currently - # only to the text3d's curve width... - #txt.setWidth(text.width/10) - txt.setLineSeparation(self.line_space) - txt.setExtrudeDepth(0.5) - txt.setText(self.value) - - # scale it to the text size - ob.SizeX = self.height * self.width_factor - ob.SizeY = self.height - ob.SizeZ = self.height - - # move the object center to the text location - ob.loc = tuple(self.loc) - transform(self.extrusion, self.rotation, ob) - - return ob - - -class Circle: #----------------------------------------------------------------- - """Class for objects representing dxf CIRCLEs. - """ - - def __init__(self, obj): - """Expects an entity object of type circle as input. - """ - if not obj.type == 'circle': - raise TypeError, "Wrong type %s for circle object!" %obj.type - self.type = obj.type -# self.data = obj.data[:] - - # required data - self.radius = obj.get_type(40)[0] - - # optional data (with defaults) - self.space = getit(obj, 67, 0) - self.thic = getit(obj, 39, 0) - self.color_index = getit(obj, 62, BYLAYER) - - self.layer = getit(obj, 8, None) - self.loc = self.get_loc(obj) - self.extrusion = get_extrusion(obj) - - - - def get_loc(self, data): - """Gets the center location for circle type objects. - - Circles have a single coord location. - """ - loc = [0, 0, 0] - loc[0] = getit(data, 10, None) - loc[1] = getit(data, 20, None) - loc[2] = getit(data, 30, 0.0) - return loc - - - - def __repr__(self): - return "%s: layer - %s, radius - %s" %(self.__class__.__name__, self.layer, self.radius) - - - def draw(self, settings): - """for CIRCLE: generate Blender_geometry. - """ - obname = 'ci_%s' %self.layer # create object name from layer name - obname = obname[:MAX_NAMELENGTH] - radius = self.radius - - thic = set_thick(self.thic, settings) - width = 0.0 - if settings.var['lines_as'] == 4: # as thin_box - thic = settings.var['thick_min'] - width = settings.var['width_min'] - if settings.var['lines_as'] == 3: # as thin cylinder - cyl_rad = 0.5 * settings.var['width_min'] - - if settings.var['lines_as'] == 5: # draw CIRCLE as curve ------------- - arc_res = settings.var['curve_arc'] - #arc_res = 3 - start, end = 0.0, 360.0 - VectorTriples = calcArc(None, radius, start, end, arc_res, True) - c = Curve.New(obname) # create new curve data - curve = c.appendNurb(BezTriple.New(VectorTriples[0])) - for p in VectorTriples[1:-1]: - curve.append(BezTriple.New(p)) - for point in curve: - point.handleTypes = [FREE, FREE] - point.radius = 1.0 - curve.flagU = 1 # 1 sets the curve cyclic=closed - if settings.var['fill_on']: - c.setFlag(6) # 2+4 set top and button caps - else: - c.setFlag(c.getFlag() & ~6) # dont set top and button caps - - c.setResolu(settings.var['curve_res']) - c.update() - - #--todo-----to check--------------------------- - ob = SCENE.objects.new(c) # create a new curve_object - ob.loc = tuple(self.loc) - if thic != 0.0: #hack: Blender<2.45 curve-extrusion - thic = thic * 0.5 - c.setExt1(1.0) # curve-extrusion accepts only (0.0 - 2.0) - ob.LocZ = thic + self.loc[2] - transform(self.extrusion, 0, ob) - if thic != 0.0: - ob.SizeZ *= abs(thic) - return ob - - else: # draw CIRCLE as mesh ----------------------------------------------- - if M_OBJ: obname, me, ob = makeNewObject() - else: - me = Mesh.New(obname) # create a new mesh - ob = SCENE.objects.new(me) # create a new mesh_object - # set a number of segments in entire circle - arc_res = settings.var['arc_res'] * sqrt(radius) / sqrt(settings.var['arc_rad']) - start, end = 0.0 , 360.0 - verts = calcArc(None, radius, start, end, arc_res, False) - verts = verts[:-1] #list without last point/edge (cause by circle it is equal to the first point) - #print 'deb:circleDraw: verts:', verts #--------------- - - if thic != 0: - len1 = len(verts) - thic_verts = [] - thic_verts.extend([[point[0], point[1], point[2]+thic] for point in verts]) - if thic < 0.0: - thic_verts.extend(verts) - verts = thic_verts - else: - verts.extend(thic_verts) - faces = [] - f_band = [[num, num+1, num+len1+1, num+len1] for num in xrange(len1 - 1)] - #f_band = [[num, num+1, num+len1+1, num+len1] for num in xrange(len1)] - f_band.append([len1 - 1, 0, len1, len1 + len1 -1]) - faces = f_band - smooth_len = len(f_band) - if settings.var['fill_on']: - if thic < 0.0: - verts.append([0,0,thic]) #center of top side - verts.append([0,0,0]) #center of bottom side - else: - verts.append([0,0,0]) #center of bottom side - verts.append([0,0,thic]) #center of top side - center1 = len(verts)-2 - center2 = len(verts)-1 - f_bottom = [[num+1, num, center1] for num in xrange(len1 - 1)] - f_bottom.append([0, len1 - 1, center1]) - f_top = [[num+len1, num+1+len1, center2] for num in xrange(len1 - 1)] - f_top.append([len1-1+len1, 0+len1, center2]) - #print 'deb:circleDraw:verts:', verts #--------------- - faces = f_band + f_bottom + f_top - #print 'deb:circleDraw:faces:', faces #--------------- - me.verts.extend(verts) # add vertices to mesh - me.faces.extend(faces) # add faces to the mesh - - if settings.var['meshSmooth_on']: # left and right side become smooth ---------------------- - for i in xrange(smooth_len): - me.faces[i].smooth = True - # each MeshSide becomes vertexGroup for easier material assignment --------------------- - if settings.var['vGroup_on'] and not M_OBJ: - # each MeshSide becomes vertexGroup for easier material assignment --------------------- - replace = Mesh.AssignModes.REPLACE #or .AssignModes.ADD - vg_band, vg_top, vg_bottom = [], [], [] - for v in f_band: vg_band.extend(v) - me.addVertGroup('side.band') ; me.assignVertsToGroup('side.band', vg_band, 1.0, replace) - - if settings.var['fill_on']: - for v in f_top: vg_top.extend(v) - for v in f_bottom: vg_bottom.extend(v) - me.addVertGroup('side.top') ; me.assignVertsToGroup('side.top', vg_top, 1.0, replace) - me.addVertGroup('side.bottom'); me.assignVertsToGroup('side.bottom',vg_bottom, 1.0, replace) - - else: # if thic == 0 - if settings.var['fill_on']: - len1 = len(verts) - verts.append([0,0,0]) #center of circle - center1 = len1 - faces = [] - faces.extend([[num, num+1, center1] for num in xrange(len1)]) - faces.append([len1-1, 0, center1]) - #print 'deb:circleDraw:verts:', verts #--------------- - #print 'deb:circleDraw:faces:', faces #--------------- - me.verts.extend(verts) # add vertices to mesh - me.faces.extend(faces) # add faces to the mesh - else: - me.verts.extend(verts) # add vertices to mesh - edges = [[num, num+1] for num in xrange(len(verts))] - edges[-1][1] = 0 # it points the "new" last edge to the first vertex - me.edges.extend(edges) # add edges to the mesh - - ob.loc = tuple(self.loc) - transform(self.extrusion, 0, ob) - return ob - - -class Arc: #----------------------------------------------------------------- - """Class for objects representing dxf ARCs. - """ - - def __init__(self, obj): - """Expects an entity object of type arc as input. - """ - if not obj.type == 'arc': - raise TypeError, "Wrong type %s for arc object!" %obj.type - self.type = obj.type -# self.data = obj.data[:] - - # required data - self.radius = obj.get_type(40)[0] - self.start_angle = obj.get_type(50)[0] - self.end_angle = obj.get_type(51)[0] - - # optional data (with defaults) - self.space = getit(obj, 67, 0) - self.thic = getit(obj, 39, 0) - self.color_index = getit(obj, 62, BYLAYER) - - self.layer = getit(obj, 8, None) - self.loc = self.get_loc(obj) - self.extrusion = get_extrusion(obj) - #print 'deb:Arc__init__: center, radius, start, end:\n', self.loc, self.radius, self.start_angle, self.end_angle #--------- - - - - def get_loc(self, data): - """Gets the center location for arc type objects. - - Arcs have a single coord location. - """ - loc = [0, 0, 0] - loc[0] = getit(data, 10, None) - loc[1] = getit(data, 20, None) - loc[2] = getit(data, 30, 0.0) - return loc - - - - def __repr__(self): - return "%s: layer - %s, radius - %s" %(self.__class__.__name__, self.layer, self.radius) - - - def draw(self, settings): - """for ARC: generate Blender_geometry. - """ - obname = 'ar_%s' %self.layer # create object name from layer name - obname = obname[:MAX_NAMELENGTH] - - center = self.loc - radius = self.radius - start = self.start_angle - end = self.end_angle - #print 'deb:calcArcPoints:\n center, radius, start, end:\n', center, radius, start, end #--------- - thic = set_thick(self.thic, settings) - width = 0.0 - if settings.var['lines_as'] == 4: # as thin_box - thic = settings.var['thick_min'] - width = settings.var['width_min'] - if settings.var['lines_as'] == 3: # as thin cylinder - cyl_rad = 0.5 * settings.var['width_min'] - - if settings.var['lines_as'] == 5: # draw ARC as curve ------------- - arc_res = settings.var['curve_arc'] - triples = True - VectorTriples = calcArc(None, radius, start, end, arc_res, triples) - arc = Curve.New(obname) # create new curve data - curve = arc.appendNurb(BezTriple.New(VectorTriples[0])) - for p in VectorTriples[1:]: - curve.append(BezTriple.New(p)) - for point in curve: - point.handleTypes = [FREE, FREE] - point.radius = 1.0 - curve.flagU = 0 # 0 sets the curve not cyclic=open - arc.setResolu(settings.var['curve_res']) - - arc.update() #important for handles calculation - - ob = SCENE.objects.new(arc) # create a new curve_object - ob.loc = tuple(self.loc) - if thic != 0.0: #hack: Blender<2.45 curve-extrusion - thic = thic * 0.5 - arc.setExt1(1.0) # curve-extrusion: Blender2.45 accepts only (0.0 - 5.0) - ob.LocZ = thic + self.loc[2] - transform(self.extrusion, 0, ob) - if thic != 0.0: - ob.SizeZ *= abs(thic) - return ob - - else: # draw ARC as mesh -------------------- - if M_OBJ: obname, me, ob = makeNewObject() - else: - me = Mesh.New(obname) # create a new mesh - ob = SCENE.objects.new(me) # create a new mesh_object - # set a number of segments in entire circle - arc_res = settings.var['arc_res'] * sqrt(radius) / sqrt(settings.var['arc_rad']) - - verts = calcArc(None, radius, start, end, arc_res, False) - #verts = [list(point) for point in verts] - len1 = len(verts) - #print 'deb:len1:', len1 #----------------------- - if width != 0: - radius_out = radius + (0.5 * width) - radius_in = radius - (0.5 * width) - if radius_in <= 0.0: - radius_in = settings.var['dist_min'] - #radius_in = 0.0 - verts_in = [] - verts_out = [] - for point in verts: - pointVec = Mathutils.Vector(point) - pointVec = pointVec.normalize() - verts_in.append(list(radius_in * pointVec)) #vertex inside - verts_out.append(list(radius_out * pointVec)) #vertex outside - verts = verts_in + verts_out - - #print 'deb:verts:', verts #--------------------- - if thic != 0: - thic_verts = [] - thic_verts.extend([[point[0], point[1], point[2]+thic] for point in verts]) - if thic < 0.0: - thic_verts.extend(verts) - verts = thic_verts - else: - verts.extend(thic_verts) - f_bottom = [[num, num+1, len1+num+1, len1+num] for num in xrange(len1-1)] - f_top = [[num, len1+num, len1+num+1, num+1] for num in xrange(len1+len1, len1+len1+len1-1)] - f_left = [[num, len1+len1+num, len1+len1+num+1, num+1] for num in xrange(len1-1)] - f_right = [[num, num+1, len1+len1+num+1, len1+len1+num] for num in xrange(len1, len1+len1-1)] - f_start = [[0, len1, len1+len1+len1, len1+len1]] - f_end = [[len1+len1-1, 0+len1-1, len1+len1+len1-1, len1+len1+len1+len1-1]] - faces = f_left + f_right + f_bottom + f_top + f_start + f_end - - me.verts.extend(verts) # add vertices to mesh - me.faces.extend(faces) # add faces to the mesh - - if settings.var['meshSmooth_on']: # left and right side become smooth ---------------------- - smooth_len = len(f_left) + len(f_right) - for i in xrange(smooth_len): - me.faces[i].smooth = True - # each MeshSide becomes vertexGroup for easier material assignment --------------------- - if settings.var['vGroup_on'] and not M_OBJ: - # each MeshSide becomes vertexGroup for easier material assignment --------------------- - replace = Mesh.AssignModes.REPLACE #or .AssignModes.ADD - vg_left, vg_right, vg_top, vg_bottom = [], [], [], [] - for v in f_left: vg_left.extend(v) - for v in f_right: vg_right.extend(v) - for v in f_top: vg_top.extend(v) - for v in f_bottom: vg_bottom.extend(v) - me.addVertGroup('side.left') ; me.assignVertsToGroup('side.left', vg_left, 1.0, replace) - me.addVertGroup('side.right') ; me.assignVertsToGroup('side.right', vg_right, 1.0, replace) - me.addVertGroup('side.top') ; me.assignVertsToGroup('side.top', vg_top, 1.0, replace) - me.addVertGroup('side.bottom'); me.assignVertsToGroup('side.bottom',vg_bottom, 1.0, replace) - me.addVertGroup('side.start'); me.assignVertsToGroup('side.start', f_start[0], 1.0, replace) - me.addVertGroup('side.end') ; me.assignVertsToGroup('side.end', f_end[0], 1.0, replace) - - - else: # if thick=0 - draw only flat ring - faces = [[num, len1+num, len1+num+1, num+1] for num in xrange(len1 - 1)] - me.verts.extend(verts) # add vertices to mesh - me.faces.extend(faces) # add faces to the mesh - - elif thic != 0: - thic_verts = [] - thic_verts.extend([[point[0], point[1], point[2]+thic] for point in verts]) - if thic < 0.0: - thic_verts.extend(verts) - verts = thic_verts - else: - verts.extend(thic_verts) - faces = [] - #print 'deb:len1:', len1 #----------------------- - #print 'deb:verts:', verts #--------------------- - faces = [[num, num+1, num+len1+1, num+len1] for num in xrange(len1 - 1)] - - me.verts.extend(verts) # add vertices to mesh - me.faces.extend(faces) # add faces to the mesh - if settings.var['meshSmooth_on']: # left and right side become smooth ---------------------- - for i in xrange(len(faces)): - me.faces[i].smooth = True - - else: - edges = [[num, num+1] for num in xrange(len(verts)-1)] - me.verts.extend(verts) # add vertices to mesh - me.edges.extend(edges) # add edges to the mesh - - #me.update() - #ob = SCENE.objects.new(me) # create a new arc_object - #ob.link(me) - ob.loc = tuple(center) - #ob.loc = Mathutils.Vector(ob.loc) - transform(self.extrusion, 0, ob) - #ob.size = (1,1,1) - return ob - - -class BlockRecord: #----------------------------------------------------------------- - """Class for objects representing dxf block_records. - """ - - def __init__(self, obj): - """Expects an entity object of type block_record as input. - """ - if not obj.type == 'block_record': - raise TypeError, "Wrong type %s for block_record object!" %obj.type - self.type = obj.type -# self.data = obj.data[:] - - # required data - self.name = getit(obj, 2, None) - - # optional data (with defaults) - self.insertion_units = getit(obj, 70, None) - self.insert_units = getit(obj, 1070, None) - """code 1070 Einfuegeeinheiten: - 0 = Keine Einheiten; 1 = Zoll; 2 = Fuss; 3 = Meilen; 4 = Millimeter; - 5 = Zentimeter; 6 = Meter; 7 = Kilometer; 8 = Mikrozoll; - 9 = Mils; 10 = Yard; 11 = Angstrom; 12 = Nanometer; - 13 = Mikrons; 14 = Dezimeter; 15 = Dekameter; - 16 = Hektometer; 17 = Gigameter; 18 = Astronomische Einheiten; - 19 = Lichtjahre; 20 = Parsecs - """ - - - def __repr__(self): - return "%s: name - %s, insert units - %s" %(self.__class__.__name__, self.name, self.insertion_units) - - - - -class Block: #----------------------------------------------------------------- - """Class for objects representing dxf BLOCKs. - """ - - def __init__(self, obj): - """Expects an entity object of type block as input. - """ - if not obj.type == 'block': - raise TypeError, "Wrong type %s for block object!" %obj.type - - self.type = obj.type - self.name = obj.name - self.data = obj.data[:] - - # required data - self.flags = getit(obj, 70, 0) - self.anonim = self.flags & 1 #anonymous block generated by hatching, associative dimensioning, other - self.atrib = self.flags & 2 # has attribute definitions - self.xref = self.flags & 4 # is an external reference (xref) - self.xref_lay = self.flags & 8 # is an xref overlay - self.dep_ext = self.flags & 16 # is externally dependent - self.dep_res = self.flags & 32 # resolved external reference - self.xref_ext = self.flags & 64 # is a referenced external reference xref - #--todo--- if self.flag > 4: self.xref = True - - # optional data (with defaults) - self.path = getit(obj, 1, '') # Xref path name - self.discription = getit(obj, 4, '') - - self.entities = dxfObject('block_contents') #creates empty entities_container for this block - self.entities.data = objectify([ent for ent in obj.data if type(ent) != list]) - - self.layer = getit(obj, 8, None) - self.loc = self.get_loc(obj) - - #print 'deb:Block %s data:\n%s' %(self.name, self.data) #------------ - #print 'deb:Block %s self.entities.data:\n%s' %(self.name, self.entities.data) #------------ - - - - def get_loc(self, data): - """Gets the insert point of the block. - """ - loc = [0, 0, 0] - loc[0] = getit(data, 10, 0.0) # 10 = x - loc[1] = getit(data, 20, 0.0) # 20 = y - loc[2] = getit(data, 30, 0.0) # 30 = z - return loc - - - def __repr__(self): - return "%s: name - %s, description - %s, xref-path - %s" %(self.__class__.__name__, self.name, self.discription, self.path) - - - - -class Insert: #----------------------------------------------------------------- - """Class for objects representing dxf INSERTs. - """ - - def __init__(self, obj): - """Expects an entity object of type insert as input. - """ - if not obj.type == 'insert': - raise TypeError, "Wrong type %s for insert object!" %obj.type - self.type = obj.type - self.data = obj.data[:] - #print 'deb:Insert_init_ self.data:\n', self.data #----------- - - # required data - self.name = obj.get_type(2)[0] - - # optional data (with defaults) - self.rotation = getit(obj, 50, 0) - self.space = getit(obj, 67, 0) - self.color_index = getit(obj, 62, BYLAYER) - - self.layer = getit(obj, 8, None) - self.loc = self.get_loc(obj) - self.scale = self.get_scale(obj) - self.rows, self.columns = self.get_array(obj) - self.extrusion = get_extrusion(obj) - - #self.flags = getit(obj.data, 66, 0) # - #self.attrib = self.flags & 1 - - - def get_loc(self, data): - """Gets the origin location of the insert. - """ - loc = [0, 0, 0] - loc[0] = getit(data, 10, 0.0) - loc[1] = getit(data, 20, 0.0) - loc[2] = getit(data, 30, 0.0) - return loc - - - def get_scale(self, data): - """Gets the x/y/z scale factors of the insert. - """ - scale = [1, 1, 1] - scale[0] = getit(data, 41, 1.0) - scale[1] = getit(data, 42, 1.0) - scale[2] = getit(data, 43, 1.0) - return scale - - - def get_array(self, data): - """Returns the pair (row number, row spacing), (column number, column spacing). - """ - columns = getit(data, 70, 1) - rows = getit(data, 71, 1) - cspace = getit(data, 44, 0.0) - rspace = getit(data, 45, 0.0) - return (rows, rspace), (columns, cspace) - - - def get_target(self, data): - """Gets the origin location of the insert. - """ - loc = [0, 0, 0] - loc[0] = getit(data, 1011, 0.0) - loc[1] = getit(data, 1021, 0.0) - loc[2] = getit(data, 1031, 0.0) - return loc - - - def get_color(self, data): - """Gets the origin location of the insert. - """ - loc = [0, 0, 0] - loc[0] = getit(data, 1010, 0.0) - loc[1] = getit(data, 1020, 0.0) - loc[2] = getit(data, 1030, 0.0) - return loc - - - def get_ave_render(self, data): - """Gets the origin location of the insert. - """ - loc = [0, 0, 0] - loc[0] = getit(data, 1010, 0.0) - loc[1] = getit(data, 1020, 0.0) - loc[2] = getit(data, 1030, 0.0) - return loc - - - def __repr__(self): - return "%s: layer - %s, name - %s" %(self.__class__.__name__, self.layer, self.name) - - - def draw(self, settings, deltaloc): - """for INSERT(block): draw empty-marker for duplicated Blender_Group. - - Blocks are made of three objects: - the block_record in the tables section - the block in the blocks section - the insert object (one or more) in the entities section - block_record gives the insert units, - block provides the objects drawn in the block, - insert object gives the location/scale/rotation of the block instances. - """ - - name = self.name.lower() - if name == 'ave_render': - if settings.var['lights_on']: #if lights support activated - a_data = get_ave_data(self.data) - # AVE_RENDER objects: - # 7:'Pref', 0:'Full Opt', 0:'Quick Opt', 1:'Scanl Opt', 2:'Raytr Opt', 0:'RFile Opt' - # 0:'Fog Opt', 0:'BG Opt', 0:'SCENE1','','','','','','','','','', - # '','','','','','','','','','','','', - - if a_data.key == 'SCENE': # define set of lights as blender group - scene_lights = 1 - return - elif name == 'ave_global': - if settings.var['lights_on']: #if lights support activated - return - elif name == 'sh_spot': - if settings.var['lights_on']: #if lights support activated - obname = settings.blocknamesmap[self.name] - obname = 'sp_%s' %obname # create object name from block name - #obname = obname[:MAX_NAMELENGTH] - # blender: 'Lamp', 'Sun', 'Spot', 'Hemi', 'Area', or 'Photon' - li = Lamp.New('Spot', obname) - ob = SCENE.objects.new(li) - intensity = 2.0 #--todo-- ----------- - li.setEnergy(intensity) - target = self.get_target(self.data) - color = self.get_color(self.data) - li.R = color[0] - li.G = color[1] - li.B = color[2] - - ob.loc = tuple(self.loc) - transform(self.extrusion, 0, ob) - return ob - - elif name == 'overhead': - if settings.var['lights_on']: #if lights support activated - obname = settings.blocknamesmap[self.name] - obname = 'la_%s' %obname # create object name from block name - #obname = obname[:MAX_NAMELENGTH] - # blender: 'Lamp', 'Sun', 'Spot', 'Hemi', 'Area', or 'Photon' - li = Lamp.New('Lamp', obname) - ob = SCENE.objects.new(li) - intensity = 2.0 #--todo-- ----------- - li.setEnergy(intensity) - target = self.get_target(self.data) - color = self.get_color(self.data) - li.R = color[0] - li.G = color[1] - li.B = color[2] - - ob.loc = tuple(self.loc) - transform(self.extrusion, 0, ob) - return ob - - elif name == 'direct': - if settings.var['lights_on']: #if lights support activated - obname = settings.blocknamesmap[self.name] - obname = 'su_%s' %obname # create object name from block name - #obname = obname[:MAX_NAMELENGTH] - # blender: 'Lamp', 'Sun', 'Spot', 'Hemi', 'Area', or 'Photon' - li = Lamp.New('Sun', obname) - ob = SCENE.objects.new(li) - intensity = 2.0 #--todo-- ----------- - li.setEnergy(intensity) - color = self.get_color(self.data) - li.R = color[0] - li.G = color[1] - li.B = color[2] - - ob.loc = tuple(self.loc) - transform(self.extrusion, 0, ob) - return ob - - elif settings.drawTypes['insert']: #if insert_drawType activated - #print 'deb:draw. settings.blocknamesmap:', settings.blocknamesmap #-------------------- - obname = settings.blocknamesmap[self.name] - obname = 'in_%s' %obname # create object name from block name - #obname = obname[:MAX_NAMELENGTH] - - # if material BYBLOCK def needed: use as placeholder a mesh-vertex instead of empty - ob = SCENE.objects.new('Empty', obname) # create a new empty_object - empty_size = 1.0 * settings.var['g_scale'] - if empty_size < 0.01: empty_size = 0.01 #Blender limits (0.01-10.0) - elif empty_size > 10.0: empty_size = 10.0 - ob.drawSize = empty_size - - # get our block_def-group - block = settings.blocks(self.name) - ob.DupGroup = block - ob.enableDupGroup = True - - if block.name.startswith('xr_'): - ob.name = 'xb_' + ob.name[3:] - - #print 'deb:draw.block.deltaloc:', deltaloc #-------------------- - ob.loc = tuple(self.loc) - if deltaloc: - deltaloc = rotXY_Vec(self.rotation, deltaloc) - #print 'deb:draw.block.loc:', deltaloc #-------------------- - ob.loc = [ob.loc[0]+deltaloc[0], ob.loc[1]+deltaloc[1], ob.loc[2]+deltaloc[2]] - transform(self.extrusion, self.rotation, ob) - ob.size = tuple(self.scale) - return ob - - - - -class Ellipse: #----------------------------------------------------------------- - """Class for objects representing dxf ELLIPSEs. - """ - - def __init__(self, obj): - """Expects an entity object of type ellipse as input. - """ - if not obj.type == 'ellipse': - raise TypeError, "Wrong type %s for ellipse object!" %obj.type - self.type = obj.type -# self.data = obj.data[:] - - # required data - self.ratio = obj.get_type(40)[0] # Ratio of minor axis to major axis - self.start_angle = obj.get_type(41)[0] # in radians - self.end_angle = obj.get_type(42)[0] - - # optional data (with defaults) - self.space = getit(obj, 67, 0) - self.thic = getit(obj, 39, 0.0) - self.color_index = getit(obj, 62, BYLAYER) - - self.layer = getit(obj, 8, None) - self.loc = self.get_loc(obj) - self.major = self.get_major(obj) - self.extrusion = get_extrusion(obj) - - - def get_loc(self, data): - """Gets the center location for arc type objects. - - Arcs have a single coord location. - """ - loc = [0.0, 0.0, 0.0] - loc[0] = getit(data, 10, 0.0) - loc[1] = getit(data, 20, 0.0) - loc[2] = getit(data, 30, 0.0) - return loc - - - def get_major(self, data): - """Gets the major axis for ellipse type objects. - - The ellipse major axis defines the rotation of the ellipse and its radius. - """ - loc = [0.0, 0.0, 0.0] - loc[0] = getit(data, 11, 0.0) - loc[1] = getit(data, 21, 0.0) - loc[2] = getit(data, 31, 0.0) - return loc - - - def __repr__(self): - return "%s: layer - %s, radius - %s" %(self.__class__.__name__, self.layer, self.radius) - - - def draw(self, settings): - """for ELLIPSE: generate Blender_geometry. - """ - obname = 'el_%s' %self.layer # create object name from layer name - obname = obname[:MAX_NAMELENGTH] - - center = self.loc - start = degrees(self.start_angle) - end = degrees(self.end_angle) - if abs(end - 360.0) < 0.00001: end = 360.0 - ellipse_closed = False - if end - start == 360.0: ellipse_closed = True - - # rotation = Angle between major and WORLDX - # doesnt work, couse produces always positive value: rotation = Mathutils.AngleBetweenVecs(major, WORLDX) - if self.major[0] == 0: - rotation = 90.0 - if self.major[1] < 0: rotation += 180 - else: - rotation = degrees(atan(self.major[1] / self.major[0])) - if self.major[0] < 0: - rotation += 180.0 - - major = Mathutils.Vector(self.major) - #radius = sqrt(self.major[0]**2 + self.major[1]**2 + self.major[2]**2) - radius = major.length - #print 'deb:calcEllipse:\n center, radius, start, end:\n', center, radius, start, end #--------- - - thic = set_thick(self.thic, settings) - width = 0.0 - if settings.var['lines_as'] == 4: # as thin_box - thic = settings.var['thick_min'] - width = settings.var['width_min'] - elif settings.var['lines_as'] == 3: # as thin cylinder - cyl_rad = 0.5 * settings.var['width_min'] - - elif settings.var['lines_as'] == 5: # draw ELLIPSE as curve ------------- - arc_res = settings.var['curve_arc'] - triples = True - VectorTriples = calcArc(None, radius, start, end, arc_res, triples) - arc = Curve.New(obname) # create new curve data - curve = arc.appendNurb(BezTriple.New(VectorTriples[0])) - if ellipse_closed: - for p in VectorTriples[1:-1]: - curve.append(BezTriple.New(p)) - for point in curve: - point.handleTypes = [FREE, FREE] - point.radius = 1.0 - curve.flagU = 1 # 0 sets the curve not cyclic=open - if settings.var['fill_on']: - arc.setFlag(6) # 2+4 set top and button caps - else: - arc.setFlag(arc.getFlag() & ~6) # dont set top and button caps - else: - for p in VectorTriples[1:]: - curve.append(BezTriple.New(p)) - for point in curve: - point.handleTypes = [FREE, FREE] - point.radius = 1.0 - curve.flagU = 0 # 0 sets the curve not cyclic=open - - arc.setResolu(settings.var['curve_res']) - arc.update() #important for handles calculation - - ob = SCENE.objects.new(arc) # create a new curve_object - ob.loc = tuple(self.loc) - if thic != 0.0: #hack: Blender<2.45 curve-extrusion - thic = thic * 0.5 - arc.setExt1(1.0) # curve-extrusion: Blender2.45 accepts only (0.0 - 5.0) - ob.LocZ = thic + self.loc[2] - transform(self.extrusion, rotation, ob) - ob.SizeY *= self.ratio - if thic != 0.0: - ob.SizeZ *= abs(thic) - return ob - - - else: # draw ELLIPSE as mesh -------------------------------------- - if M_OBJ: obname, me, ob = makeNewObject() - else: - me = Mesh.New(obname) # create a new mesh - ob = SCENE.objects.new(me) # create a new mesh_object - # set a number of segments in entire circle - arc_res = settings.var['arc_res'] * sqrt(radius) / sqrt(settings.var['arc_rad']) - - verts = calcArc(None, radius, start, end, arc_res, False) - #verts = [list(point) for point in verts] - len1 = len(verts) - #print 'deb:len1:', len1 #----------------------- - if width != 0: - radius_out = radius + (0.5 * width) - radius_in = radius - (0.5 * width) - if radius_in <= 0.0: - radius_in = settings.var['dist_min'] - #radius_in = 0.0 - verts_in = [] - verts_out = [] - for point in verts: - pointVec = Mathutils.Vector(point) - pointVec = pointVec.normalize() - verts_in.append(list(radius_in * pointVec)) #vertex inside - verts_out.append(list(radius_out * pointVec)) #vertex outside - verts = verts_in + verts_out - - #print 'deb:verts:', verts #--------------------- - if thic != 0: - thic_verts = [] - thic_verts.extend([[point[0], point[1], point[2]+thic] for point in verts]) - if thic < 0.0: - thic_verts.extend(verts) - verts = thic_verts - else: - verts.extend(thic_verts) - f_bottom = [[num, num+1, len1+num+1, len1+num] for num in xrange(len1-1)] - f_top = [[num, len1+num, len1+num+1, num+1] for num in xrange(len1+len1, len1+len1+len1-1)] - f_left = [[num, len1+len1+num, len1+len1+num+1, num+1] for num in xrange(len1-1)] - f_right = [[num, num+1, len1+len1+num+1, len1+len1+num] for num in xrange(len1, len1+len1-1)] - f_start = [[0, len1, len1+len1+len1, len1+len1]] - f_end = [[len1+len1-1, 0+len1-1, len1+len1+len1-1, len1+len1+len1+len1-1]] - faces = f_left + f_right + f_bottom + f_top + f_start + f_end - - me.verts.extend(verts) # add vertices to mesh - me.faces.extend(faces) # add faces to the mesh - - if settings.var['meshSmooth_on']: # left and right side become smooth ---------------------- - smooth_len = len(f_left) + len(f_right) - for i in xrange(smooth_len): - me.faces[i].smooth = True - if settings.var['vGroup_on'] and not M_OBJ: - # each MeshSide becomes vertexGroup for easier material assignment --------------------- - replace = Mesh.AssignModes.REPLACE #or .AssignModes.ADD - vg_left, vg_right, vg_top, vg_bottom = [], [], [], [] - for v in f_left: vg_left.extend(v) - for v in f_right: vg_right.extend(v) - for v in f_top: vg_top.extend(v) - for v in f_bottom: vg_bottom.extend(v) - me.addVertGroup('side.left') ; me.assignVertsToGroup('side.left', vg_left, 1.0, replace) - me.addVertGroup('side.right') ; me.assignVertsToGroup('side.right', vg_right, 1.0, replace) - me.addVertGroup('side.top') ; me.assignVertsToGroup('side.top', vg_top, 1.0, replace) - me.addVertGroup('side.bottom'); me.assignVertsToGroup('side.bottom',vg_bottom, 1.0, replace) - me.addVertGroup('side.start'); me.assignVertsToGroup('side.start', f_start[0], 1.0, replace) - me.addVertGroup('side.end') ; me.assignVertsToGroup('side.end', f_end[0], 1.0, replace) - - - else: # if thick=0 - draw only flat ring - faces = [[num, len1+num, len1+num+1, num+1] for num in xrange(len1 - 1)] - me.verts.extend(verts) # add vertices to mesh - me.faces.extend(faces) # add faces to the mesh - - elif thic != 0: - thic_verts = [] - thic_verts.extend([[point[0], point[1], point[2]+thic] for point in verts]) - if thic < 0.0: - thic_verts.extend(verts) - verts = thic_verts - else: - verts.extend(thic_verts) - faces = [] - #print 'deb:len1:', len1 #----------------------- - #print 'deb:verts:', verts #--------------------- - faces = [[num, num+1, num+len1+1, num+len1] for num in xrange(len1 - 1)] - - me.verts.extend(verts) # add vertices to mesh - me.faces.extend(faces) # add faces to the mesh - if settings.var['meshSmooth_on']: # left and right side become smooth ---------------------- - for i in xrange(len(faces)): - me.faces[i].smooth = True - - else: - edges = [[num, num+1] for num in xrange(len(verts)-1)] - me.verts.extend(verts) # add vertices to mesh - me.edges.extend(edges) # add edges to the mesh - - #print 'deb:calcEllipse transform rotation: ', rotation #--------- - ob.loc = tuple(center) - #old ob.SizeY = self.ratio - transform(self.extrusion, rotation, ob) - #old transform(self.extrusion, 0, ob) - ob.SizeY *= self.ratio - - return ob - - - -class Face: #----------------------------------------------------------------- - """Class for objects representing dxf 3DFACEs. - """ - - def __init__(self, obj): - """Expects an entity object of type 3dfaceplot as input. - """ - if not obj.type == '3dface': - raise TypeError, "Wrong type %s for 3dface object!" %obj.type - self.type = obj.type -# self.data = obj.data[:] - - # optional data (with defaults) - self.space = getit(obj, 67, 0) - self.color_index = getit(obj, 62, BYLAYER) - - self.layer = getit(obj, 8, None) - self.points = self.get_points(obj) - - - def get_points(self, data): - """Gets 3-4 points for a 3d face type object. - - Faces have three or optionally four verts. - """ - a = [0, 0, 0] - b = [0, 0, 0] - c = [0, 0, 0] - d = [0, 0, 0] - a[0] = getit(data, 10, None) # 10 = x - a[1] = getit(data, 20, None) # 20 = y - a[2] = getit(data, 30, 0.0) # 30 = z - b[0] = getit(data, 11, None) - b[1] = getit(data, 21, None) - b[2] = getit(data, 31, 0.0) - c[0] = getit(data, 12, None) - c[1] = getit(data, 22, None) - c[2] = getit(data, 32, 0.0) - out = [a,b,c] - - d[0] = getit(data, 13, None) - if d[0] != None: - d[1] = getit(data, 23, None) - d[2] = getit(data, 33, 0.0) - out.append(d) - - #if len(out) < 4: print '3dface with only 3 vertices:\n',a,b,c,d #----------------- - return out - - - def __repr__(self): - return "%s: layer - %s, points - %s" %(self.__class__.__name__, self.layer, self.points) - - - def draw(self, settings): - """for 3DFACE: generate Blender_geometry. - """ - # Generate the geometery - points = self.points - - global activObjectLayer - global activObjectName - #print 'deb:draw:face.ob IN activObjectName: ', activObjectName #--------------------- - - if M_OBJ: obname, me, ob = makeNewObject() - else: - if activObjectLayer == self.layer and settings.var['one_mesh_on']: - obname = activObjectName - #print 'deb:face.draw obname from activObjectName: ', obname #--------------------- - ob = getSceneChild(obname) # open an existing mesh_object - #ob = SCENE.getChildren(obname) # open an existing mesh_object - me = ob.getData(name_only=False, mesh=True) - else: - obname = 'fa_%s' %self.layer # create object name from layer name - obname = obname[:MAX_NAMELENGTH] - me = Mesh.New(obname) # create a new mesh - ob = SCENE.objects.new(me) # create a new mesh_object - activObjectName = ob.name - activObjectLayer = self.layer - #print ('deb:except. new face.ob+mesh:"%s" created!' %ob.name) #--------------------- - - #me = Mesh.Get(ob.name) # open objects mesh data - faces, edges = [], [] - n = len(me.verts) - if len(self.points) == 4: - faces = [[0+n,1+n,2+n,3+n]] - elif len(self.points) == 3: - faces = [[0+n,1+n,2+n]] - elif len(self.points) == 2: - edges = [[0+n,1+n]] - - me.verts.extend(points) # add vertices to mesh - if faces: me.faces.extend(faces) # add faces to the mesh - if edges: me.edges.extend(edges) # add faces to the mesh - if settings.var['vGroup_on'] and not M_OBJ: - # entities with the same color build one vertexGroup for easier material assignment --------------------- - ob.link(me) # link mesh to that object - vG_name = 'color_%s' %self.color_index - if edges: faces = edges - replace = Mesh.AssignModes.ADD #or .AssignModes.REPLACE or ADD - try: - me.assignVertsToGroup(vG_name, faces[0], 1.0, replace) - #print 'deb: existed vGroup:', vG_name #--------------------- - except: - me.addVertGroup(vG_name) - me.assignVertsToGroup(vG_name, faces[0], 1.0, replace) - #print 'deb: create new vGroup:', vG_name #-------------------- - - #print 'deb:draw:face.ob OUT activObjectName: ', activObjectName #--------------------- - return ob - - -#--------------------------------------------------------------------------------------- -# type to object maping (sorted-dictionary for f_obiectify ONLY!, format={'key':Class} ) -type_map = { - 'vport':Vport, - 'view':View, - 'layer':Layer, - 'block_record':BlockRecord, - 'block':Block, - 'insert':Insert, - 'point':Point, - '3dface':Face, - 'line':Line, -# 'mline':MLine, - 'polyline':Polyline, - 'lwpolyline':LWpolyline, - 'spline':Spline, -# 'region':Region, - 'trace':Solid, - 'solid':Solid, - 'text':Text, - 'mtext':Mtext, - 'circle':Circle, - 'ellipse':Ellipse, - 'arc':Arc -} - - - -def objectify(data): #----------------------------------------------------------------- - """Expects a section type object's data as input. - - Maps object data to the correct object type. - """ - #print 'deb:objectify start %%%%%%%%%%%' #--------------- - objects = [] # colector for finished objects - known_types = type_map.keys() # so we don't have to call foo.keys() every iteration - curves_on = GUI_A['curves_on'].val - index = 0 - while index < len(data): - item = data[index] - #print 'deb:objectify item: \n', item #------------ - if type(item) != list and item.type == 'table': - item.data = objectify(item.data) # tables have sub-objects - objects.append(item) - elif type(item) != list and item.type == 'polyline': #remi --todo----------- - #print 'deb:gosub Polyline\n' #------------- - pline = Polyline(item) - while 1: - index += 1 - item = data[index] - if item.type == 'vertex': - #print 'deb:objectify gosub Vertex--------' #------------- - v = Vertex(item) - if pline.spline: # if NURBSpline-curve - # then for Blender-mesh filter only additional_vertices - # OR - # then for Blender-curve filter only spline_control_vertices - if (v.spline and not curves_on) or (curves_on and v.spline_c): #correct for real NURBS-import - #if (v.spline and not curves_on) or (curves_on and not v.spline_c): #fake for Bezier-emulation of NURBS-import - pline.points.append(v) - elif pline.curved: # if Bezier-curve - # then for Blender-mesh filter only curve_additional_vertices - # OR - # then for Blender-curve filter curve_control_vertices - if not curves_on or (curves_on and not v.curved): - pline.points.append(v) - else: - pline.points.append(v) - elif item.type == 'seqend': - #print 'deb:objectify it is seqEND ---------\n' #------------- - break - else: - print "Error: non-vertex found before seqend!" - index -= 1 #so go back one step - break - objects.append(pline) - elif type(item) != list and item.type in ['block', 'insert']: - if not settings.var['block_nn'] and item.name.startswith('*X'): - #print 'deb:objectify item.type:"%s", item.name:"%s"' %(item.type, item.name) #------------ - pass - elif settings.var['blockFilter_on'] and not settings.accepted_block(item.name): - pass - else: - try: - objects.append(type_map[item.type](item)) - except TypeError: - pass - elif type(item) != list and item.type in known_types: - # proccess the object and append the resulting object - try: - objects.append(type_map[item.type](item)) - except TypeError: - pass - else: - #we will just let the data pass un-harrased - #objects.append(item) - pass - index += 1 - #print 'deb:objectify objects:\n', objects #------------ - #print 'deb:objectify END %%%%%%%%' #------------ - return objects - - - -class MatColors: #----------------------------------------------------------------- - """A smart container for dxf-color based materials. - - This class is a wrapper around a dictionary mapping dxf-color indicies to materials. - When called with a color_index - it returns a material corresponding to that index. - Behind the scenes it checks if that index is in its keys, and if not it creates - a new material. It then adds the new index:material pair to its dict and returns - the material. - """ - - def __init__(self): - """Expects a map - a dictionary mapping layer names to layers. - """ - #self.layersmap = layersmap # a dictionary of layername:layerobject - self.colMaterials = {} # a dictionary of color_index:blender_material - #print 'deb:init_MatColors argument.map: ', map #------------------ - - - def __call__(self, color=None): - """Return the material associated with color. - - If a layer name is provided, the color of that layer is used. - """ - if color == None: color = 256 # color 256=BYLAYER - if type(color) == str: # looking for color of LAYER named "color" - #--todo---bug with ARC from ARC-T0.DXF layer="T-3DARC-1"----- - #print 'deb:color is string:--------: ', color - #try: - #color = layersmap[color].color - #print 'deb:color=self.map[color].color:', color #------------------ - #except KeyError: - #layer = Layer(name=color, color=256, frozen=False) - #layersmap[color] = layer - #color = 0 - if color in layersmap.keys(): - color = layersmap[color].color - if color == 256: # color 256 = BYLAYER - #--todo-- should looking for color of LAYER - #if layersmap: color = layersmap[color].color - color = 3 - if color == 0: # color 0 = BYBLOCK - #--todo-- should looking for color of paret-BLOCK - #if layersmap: color = layersmap[color].color - color = 3 - color = abs(color) # cause the value could be nagative = means the layer is turned off - - if color not in self.colMaterials.keys(): - self.add(color) - return self.colMaterials[color] - - - def add(self, color): - """Create a new material 'ColorNr-N' using the provided color index-N. - """ - #global color_map #--todo-- has not to be global? - mat = Material.New('ColorNr-%s' %color) - mat.setRGBCol(color_map[color]) - #mat.mode |= Material.Modes.SHADELESS #--todo-- - #mat.mode |= Material.Modes.WIRE -# try: mat.setMode('Shadeless', 'Wire') #work-around for 2.45rc-bug -# except: pass - self.colMaterials[color] = mat - - - -class MatLayers: #----------------------------------------------------------------- - """A smart container for dxf-layer based materials. - - This class is a wrapper around a dictionary mapping dxf-layer names to materials. - When called with a layer name it returns a material corrisponding to that. - Behind the scenes it checks if that layername is in its keys, and if not it creates - a new material. It then adds the new layername:material pair to its dict and returns - the material. - """ - - def __init__(self): - """Expects a map - a dictionary mapping layer names to layers. - """ - #self.layersmap = layersmap # a dictionary of layername:layer - self.layMaterials = {} # a dictionary of layer_name:blender_material - #print 'deb:init_MatLayers argument.map: ', map #------------------ - - - def __call__(self, layername=None, color=None): - """Return the material associated with dxf-layer. - - If a dxf-layername is not provided, create a new material - """ - #global layernamesmap - layername_short = layername - if layername in layernamesmap.keys(): - layername_short = layernamesmap[layername] - colorlayername = layername_short - if color: colorlayername = str(color) + colorlayername - if colorlayername not in self.layMaterials.keys(): - self.add(layername, color, colorlayername) - return self.layMaterials[colorlayername] - - - def add(self, layername, color, colorlayername): - """Create a new material 'layername'. - """ - try: mat = Material.Get('L-%s' %colorlayername) - except: mat = Material.New('L-%s' %colorlayername) - #print 'deb:MatLayers material: ', mat #---------- - #global settings - #print 'deb:MatLayers material_from: ', settings.var['material_from'] #---------- - if settings.var['material_from'] == 3 and color: - if color == 0 or color == 256: mat_color = 3 - else: mat_color = color - elif layersmap and layername: - mat_color = layersmap[layername].color - else: mat_color = 3 - #print 'deb:MatLayers color: ', color #----------- - #print 'deb:MatLayers mat_color: ', mat_color #----------- - mat.setRGBCol(color_map[abs(mat_color)]) - #mat.mode |= Material.Modes.SHADELESS - #mat.mode |= Material.Modes.WIRE -# try: mat.setMode('Shadeless', 'Wire') #work-around for 2.45rc-bug -# except: pass - self.layMaterials[colorlayername] = mat - - - - -class Blocks: #----------------------------------------------------------------- - """A smart container for blocks. - - This class is a wrapper around a dictionary mapping block names to Blender data blocks. - When called with a name string it returns a block corresponding to that name. - Behind the scenes it checks if that name is in its keys, and if not it creates - a new data block. It then adds the new name:block_data pair to its dict and returns - the block. - """ - - def __init__(self, blocksmap, settings): - """Expects a dictionary mapping block_name:block_data. - """ - self.blocksmap = blocksmap #a dictionary mapping block_name:block_data - self.settings = settings - self.blocks = {} #container for blender groups representing blocks - - - def __call__(self, name=None): - """Return the data block associated with that block_name. - - If that name is not in its keys, it creates a new data block. - If no name is provided return entire self.blocks container. - """ - if name == None: - return self.blocks - if name not in self.blocks.keys(): - self.addBlock(name) - return self.blocks[name] - - - def addBlock(self, name): - """Create a new 'block group' for the block name. - """ - block = self.blocksmap[name] - prefix = 'bl' - if block.xref: prefix = 'xr' - blender_group = Group.New('%s_%s' %(prefix,name)) # Blender groupObject contains definition of BLOCK - block_def = [blender_group, block.loc] - self.settings.write("\nDrawing block:\'%s\' ..." % name) - - if block.xref: - obname = 'xr_%s' %name # create object name from xref block name - #obname = obname[:MAX_NAMELENGTH] - # if material BYBLOCK def needed: use as placeholder a mesh-vertex instead of empty - ob = SCENE.objects.new('Empty', obname) # create a new empty_object - empty_size = 1.0 * settings.var['g_scale'] - if empty_size < 0.01: empty_size = 0.01 #Blender limits (0.01-10.0) - elif empty_size > 10.0: empty_size = 10.0 - ob.drawSize = empty_size - ob.loc = tuple(block.loc) - ob.properties['xref_path'] = block.path - ob.layers = [19] - insertFlag=True; blockFlag=True - global oblist - oblist.append((ob, insertFlag, blockFlag)) - else: - if M_OBJ: - car_end() - car_start() - drawEntities(block.entities, self.settings, block_def) - if M_OBJ: car_end() - self.settings.write("Drawing block:\'%s\' done!" %name) - self.blocks[name] = blender_group - - - - - -class Settings: #----------------------------------------------------------------- - """A container for all the import settings and objects used by the draw functions. - - This is like a collection of globally accessable persistant properties and functions. - """ - # Optimization constants - MIN = 0 - MID = 1 - PRO = 2 - MAX = 3 - - def __init__(self, keywords, drawTypes): - """initialize all the important settings used by the draw functions. - """ - self.obj_number = 1 #global object_number for progress_bar - - self.var = dict(keywords) #a dictionary of (key_variable:Value) control parameter - self.drawTypes = dict(drawTypes) #a dictionary of (entity_type:True/False) = import on/off for this entity_type - - self.var['colorFilter_on'] = False #deb:remi------------ - self.acceptedColors = [0,2,3,4,5,6,7,8,9, - 10 ] - - self.var['layerFilter_on'] = False #deb:remi------------ - self.acceptedLayers = ['3', - '0' - ] - - self.var['groupFilter_on'] = False #deb:remi------------ - self.acceptedLayers = ['3', - '0' - ] - - #self.var['blockFilter_on'] = 0 #deb:remi------------ - self.acceptedBlocks = ['WALL_1871', - 'BOX02' - ] - self.unwantedBlocks = ['BOX05', - 'BOX04' - ] - - - def update(self, keywords, drawTypes): - """update all the important settings used by the draw functions. - mostly used after loading parameters from INI-file - """ - - for k, v in keywords.iteritems(): - self.var[k] = v - #print 'deb:settings_update var %s= %s' %(k, self.var[k]) #-------------- - for t, v in drawTypes.iteritems(): - self.drawTypes[t] = v - #print 'deb:settings_update drawType %s= %s' %(t, self.drawTypes[t]) #-------------- - - self.drawTypes['arc'] = self.drawTypes['line'] - self.drawTypes['circle'] = self.drawTypes['line'] - self.drawTypes['ellipse'] = self.drawTypes['line'] - self.drawTypes['trace'] = self.drawTypes['solid'] - self.drawTypes['insert'] = self.drawTypes['block'] - #self.drawTypes['vport'] = self.drawTypes['view'] - - #print 'deb:self.drawTypes', self.drawTypes #--------------- - - - def validate(self, drawing): - """Given the drawing, build dictionaries of Layers, Colors and Blocks. - """ - - global oblist - #adjust the distance parameter to globalScale - if self.var['g_scale'] != 1.0: - self.var['dist_min'] = self.var['dist_min'] / self.var['g_scale'] - self.var['thick_min'] = self.var['thick_min'] / self.var['g_scale'] - self.var['width_min'] = self.var['width_min'] / self.var['g_scale'] - self.var['arc_rad'] = self.var['arc_rad'] / self.var['g_scale'] - - self.g_origin = Mathutils.Vector(self.var['g_originX'], self.var['g_originY'], self.var['g_originZ']) - - # First sort out all the section_items - sections = dict([(item.name, item) for item in drawing.data]) - - # The section:header may be omited - if 'header' in sections.keys(): - self.write("found section:header") - else: - self.write("File contains no section:header!") - - if self.var['optimization'] == 0: self.var['one_mesh_on'] = 0 - # The section:tables may be partialy or completely missing. - self.layersTable = False - self.colMaterials = MatColors() #A container for dxf-color based materials - self.layMaterials = MatLayers() #A container for dxf-layer based materials - #self.collayMaterials = MatColLayers({}) #A container for dxf-color+layer based materials - global layersmap, layernamesmap - layersmap, layernamesmap = {}, {} - if 'tables' in sections.keys(): - self.write("found section:tables") - views, vports, layers = False, False, False - for table in drawing.tables.data: - if table.name == 'layer': - self.write("found table:layers") - layers = table - elif table.name == 'view': - print "found table:view" - views = table - elif table.name == 'vport': - print "found table:vport" - vports = table - if layers: #---------------------------------- - # Read the layers table and get the layer colors - layersmap, layernamesmap = getLayersmap(layers) - #self.colMaterials = MatColors() - #self.layMaterials = MatLayers() - else: - self.write("File contains no table:layers!") - - - if views: #---------------------------------- - if self.var['views_on']: - for item in views.data: - if type(item) != list and item.type == 'view': - #print 'deb:settings_valid views dir(item)=', dir(item) #------------- - #print 'deb:settings_valid views item=', item #------------- - ob = item.draw(self) - #viewsmap[item.name] = [item.length] - #--todo-- add to obj_list for global.Scaling - insertFlag, blockFlag = False, False - oblist.append((ob, insertFlag, blockFlag)) - - else: - self.write("File contains no table:views!") - - - if vports: #---------------------------------- - if self.var['views_on']: - for item in vports.data: - if type(item) != list and item.type == 'vport': - #print 'deb:settings_valid views dir(item)=', dir(item) #------------- - #print 'deb:settings_valid views item=', item #------------- - ob = item.draw(self) - #viewsmap[item.name] = [item.length] - #--todo-- add to obj_list for global.Scaling - insertFlag, blockFlag = False, False - oblist.append((ob, insertFlag, blockFlag)) - else: - self.write("File contains no table:vports!") - - - else: - self.write("File contains no section:tables!") - self.write("File contains no table:layers!") - - - # The section:blocks may be omited - if 'blocks' in sections.keys(): - self.write("found section:blocks") - # Read the block definitions and build our block object - if self.drawTypes['insert']: #if support for entity type 'Insert' is activated - #Build a dictionary of blockname:block_data pairs - blocksmap, obj_number = getBlocksmap(drawing, layersmap, self.var['layFrozen_on']) - self.obj_number += obj_number - self.blocknamesmap = getBlocknamesmap(blocksmap) - self.blocks = Blocks(blocksmap, self) # initiates container for blocks_data - self.usedBlocks = blocksmap.keys() - #print 'deb:settings_valid self.usedBlocks', self.usedBlocks #---------- - else: - self.write("ignored, because support for BLOCKs is turn off!") - #print 'deb:settings_valid self.obj_number', self.obj_number #---------- - else: - self.write("File contains no section:blocks!") - self.drawTypes['insert'] = False - - # The section:entities - if 'entities' in sections.keys(): - self.write("found section:entities") - self.obj_number += len(drawing.entities.data) - self.obj_number = 1.0 / self.obj_number - - - def accepted_block(self, name): - if name not in self.usedBlocks: return False - if name in self.unwantedBlocks: return False - elif name in self.acceptedBlocks: return True - #elif (name.find('*X')+1): return False - #elif name.startswith('3'): return True - #elif name.endswith('H'): return False - return True - - - def write(self, text, newline=True): - """Wraps the built-in print command in a optimization check. - """ - if self.var['optimization'] <= self.MID: - if newline: print text - else: print text, - - - def redraw(self): - """Update Blender if optimization level is low enough. - """ - if self.var['optimization'] <= self.MIN: - Blender.Redraw() - - - def progress(self, done, text): - """Wrapper for Blender.Window.DrawProgressBar. - """ - if self.var['optimization'] <= self.PRO: - progressbar = done * self.obj_number - Window.DrawProgressBar(progressbar, text) - #print 'deb:drawer done, progressbar: ', done, progressbar #----------------------- - - def layer_isOff(self, layername): # no more used ------- - """Given a layer name, and return its visible status. - """ - # if layer is off then color_index is negative - if layersmap and layersmap[layername].color < 0: return True - #print 'deb:layer_isOff: layer is ON' #--------------- - return False - - - def layer_isFrozen(self, layername): # no more used ------- - """Given a layer name, and return its frozen status. - """ - if layersmap and layersmap[layername].frozen: return True - #print 'deb:layer_isFrozen: layer is not FROZEN' #--------------- - return False - - - -def analyzeDXF(dxfFile): #--------------------------------------- - """list statistics about LAYER and BLOCK dependences into textfile.INF - - """ - Window.WaitCursor(True) # Let the user know we are thinking - print 'reading DXF file: %s.' % dxfFile - time1 = sys.time() #time marker1 - drawing = readDXF(dxfFile, objectify) - print 'finish reading in %.4f sec.' % (sys.time()-time1) - - # First sort out all the section_items - sections = dict([(item.name, item) for item in drawing.data]) - - # The section:header may be omited - if 'header' in sections.keys(): print "found section:header" - else: print "File contains no section:header!" - - # The section:tables may be partialy or completely missing. - layersTable = False - global layersmap - layersmap = {} - viewsmap = {} - vportsmap = {} - layersmap_str = '#File contains no table:layers!' - viewsmap_str = '#File contains no table:views!' - vportsmap_str = '#File contains no table:vports!' - if 'tables' in sections.keys(): - print "found section:tables" - views, vports, layers = False, False, False - for table in drawing.tables.data: - if table.name == 'layer': - print "found table:layers" - layers = table - elif table.name == 'view': - print "found table:view" - views = table - elif table.name == 'vport': - print "found table:vport" - vports = table - if layers: #---------------------------------- - for item in layers.data: - if type(item) != list and item.type == 'layer': - #print dir(item) - layersmap[item.name] = [item.color, item.frozen] - #print 'deb:analyzeDXF: layersmap=' , layersmap #------------- - layersmap_str = '#list of LAYERs: name, color, frozen_status ---------------------------\n' - key_list = layersmap.keys() - key_list.sort() - for key in key_list: - #for layer_name, layer_data in layersmap.iteritems(): - layer_name, layer_data = key, layersmap[key] - layer_str = '\'%s\': col=%s' %(layer_name,layer_data[0])#------------- - if layer_data[1]: layer_str += ', frozen' - layersmap_str += layer_str + '\n' - #print 'deb:analyzeDXF: layersmap_str=\n' , layersmap_str #------------- - else: - print "File contains no table:layers!" - - if views: #---------------------------------- - for item in views.data: - if type(item) != list and item.type == 'view': - #print dir(item) - viewsmap[item.name] = [item.length] - #print 'deb:analyzeDXF: viewsmap=' , viewsmap #------------- - viewsmap_str = '#list of VIEWs: name, focus_length ------------------------------------\n' - key_list = viewsmap.keys() - key_list.sort() - for key in key_list: - #for view_name, view_data in viewsmap.iteritems(): - view_name, view_data = key, viewsmap[key] - view_str = '\'%s\': length=%s' %(view_name,view_data[0])#------------- - #if view_data[1]: view_str += ', something' - viewsmap_str += view_str + '\n' - #print 'deb:analyzeDXF: layersmap_str=\n' , layersmap_str #------------- - else: - print "File contains no table:views!" - - if vports: #---------------------------------- - for item in vports.data: - if type(item) != list and item.type == 'vport': - #print dir(item) - vportsmap[item.name] = [item.length] - #print 'deb:analyzeDXF: vportsmap=' , vportsmap #------------- - vportsmap_str = '#list of VPORTs: name, focus_length -----------------------------------\n' - key_list = vportsmap.keys() - key_list.sort() - for key in key_list: - #for vport_name, vport_data in vportsmap.iteritems(): - vport_name, vport_data = key, vportsmap[key] - vport_str = '\'%s\': length=%s' %(vport_name,vport_data[0])#------------- - #if vport_data[1]: vport_str += ', something' - vportsmap_str += vport_str + '\n' - #print 'deb:analyzeDXF: vportsmap_str=\n' , vportsmap_str #------------- - else: - print "File contains no table:vports!" - - else: - print "File contains no section:tables!" - print "File contains no tables:layers,views,vports!" - - # The section:blocks may be omited - if 'blocks' in sections.keys(): - print "found section:blocks" - blocksmap = {} - for item in drawing.blocks.data: - #print 'deb:getBlocksmap item=' ,item #-------- - #print 'deb:getBlocksmap item.entities=' ,item.entities #-------- - #print 'deb:getBlocksmap item.entities.data=' ,item.entities.data #-------- - if type(item) != list and item.type == 'block': - xref = False - if item.xref: xref = True - childList = [] - used = False - for item2 in item.entities.data: - if type(item2) != list and item2.type == 'insert': - #print 'deb:getBlocksmap dir(item2)=', dir(item2) #---------- - item2str = [item2.name, item2.layer, item2.color_index, item2.scale, item2.space] - childList.append(item2str) - try: blocksmap[item.name] = [used, childList, xref] - except KeyError: print 'Cannot map "%s" - "%s" as Block!' %(item.name, item) - #print 'deb:analyzeDXF: blocksmap=' , blocksmap #------------- - - for item2 in drawing.entities.data: - if type(item2) != list and item2.type == 'insert': - if item2.name in blocksmap.keys(): - if not layersmap or (layersmap and not layersmap[item2.layer][1]): #if insert_layer is not frozen - blocksmap[item2.name][0] = True # marked as world used BLOCK - - key_list = blocksmap.keys() - key_list.reverse() - for key in key_list: - if blocksmap[key][0]: #if used - for child in blocksmap[key][1]: - if not layersmap or (layersmap and not layersmap[child[1]][1]): #if insert_layer is not frozen - blocksmap[child[0]][0] = True # marked as used BLOCK - - blocksmap_str = '#list of BLOCKs: name:(unused)(xref) -[child_name, layer, color, scale, space]-------\n' - key_list = blocksmap.keys() - key_list.sort() - for key in key_list: - #for block_name, block_data in blocksmap.iteritems(): - block_name, block_data = key, blocksmap[key] - block_str = '\'%s\': ' %(block_name) #------------- - used = '(unused)' - if block_data[0]: used = '' -# else: used = '(unused)' - xref = '' - if block_data[2]: xref = '(xref)' - blocksmap_str += block_str + used + xref +'\n' - if block_data: - for block_item in block_data[1]: - block_data_str = ' - %s\n' %block_item - blocksmap_str += block_data_str - #print 'deb:analyzeDXF: blocksmap_str=\n' , blocksmap_str #------------- - else: - blocksmap_str = '#File contains no section:blocks!' - print "File contains no section:blocks!" - - Window.WaitCursor(False) - output_str = '%s\n%s\n%s\n%s' %(viewsmap_str, vportsmap_str, layersmap_str, blocksmap_str) - infFile = dxfFile[:-4] + '_DXF.INF' # replace last char:'.dxf' with '_DXF.inf' - try: - f = file(infFile, 'w') - f.write(INFFILE_HEADER + '\n# this is a comment line\n\n') - f.write(output_str) - f.close() - Draw.PupMenu('DXF importer: report saved in INF-file:%t|' + '\'%s\'' %infFile) - except: - Draw.PupMenu('DXF importer: ERROR by writing report in INF-file:%t|' + '\'%s\'' %infFile) - #finally: f.close() - - - - -def main(dxfFile): #---------------#############################----------- - #print 'deb:filename:', filename #-------------- - global SCENE - global oblist - editmode = Window.EditMode() # are we in edit mode? If so ... - if editmode: - Window.EditMode(0) # leave edit mode before - - #SCENE = bpy.data.scenes.active - #SCENE.objects.selected = [] # deselect all - - global cur_COUNTER #counter for progress_bar - cur_COUNTER = 0 - - #try: - if 1: - #print "Getting settings..." - global GUI_A, GUI_B, g_scale_as - if not GUI_A['g_scale_on'].val: - GUI_A['g_scale'].val = 1.0 - - keywords = {} - drawTypes = {} - for k, v in GUI_A.iteritems(): - keywords[k] = v.val - for k, v in GUI_B.iteritems(): - drawTypes[k] = v.val - #print 'deb:startUInew keywords: ', keywords #-------------- - #print 'deb:startUInew drawTypes: ', drawTypes #-------------- - - # The settings object controls how dxf entities are drawn - settings.update(keywords, drawTypes) - #print 'deb:settings.var:\n', settings.var #----------------------- - - if not settings: - #Draw.PupMenu('DXF importer: EXIT!%t') - #print '\nDXF Import: terminated by user!' - print '\nDXF Import: terminated, cause settings failure!' - Window.WaitCursor(False) - if editmode: Window.EditMode(1) # and put things back how we fond them - return None - - #no more used dxfFile = dxfFileName.val - #print 'deb: dxfFile file: ', dxfFile #---------------------- - if dxfFile.lower().endswith('.dxf') and sys.exists(dxfFile): - Window.WaitCursor(True) # Let the user know we are thinking - print 'reading file: %s.' % dxfFile - time1 = sys.time() #time marker1 - drawing = readDXF(dxfFile, objectify) - print 'reading finished in %.4f sec.' % (sys.time()-time1) - Window.WaitCursor(False) - elif dxfFile.lower().endswith('.dwg') and sys.exists(dxfFile): - if not extCONV_OK: - Draw.PupMenu(extCONV_TEXT) - Window.WaitCursor(False) - if editmode: Window.EditMode(1) # and put things back how we fond them - return None - else: - Window.WaitCursor(True) # Let the user know we are thinking - #todo: issue: in DConvertCon.exe the output filename is fixed to dwg_name.dxf - - if 0: # works only for Windows - dwgTemp = 'temp_01.dwg' - dxfTemp = 'temp_01.dxf' - os.system('copy %s %s' %(dxfFile,dwgTemp)) - else: - dwgTemp = dxfFile - dxfTemp = dxfFile[:-3]+'dxf' - #print 'temp. converting: %s\n to: %s' %(dxfFile, dxfTemp) - #os.system('%s %s -acad11 -dxf' %(extCONV_PATH, dxfFile)) - os.system('%s %s -dxf' %(extCONV_PATH, dwgTemp)) - #os.system('%s %s -dxf' %(extCONV_PATH, dxfFile_temp)) - if sys.exists(dxfTemp): - print 'reading file: %s.' % dxfTemp - time1 = sys.time() #time marker1 - drawing = readDXF(dxfTemp, objectify) - #os.remove(dwgTemp) - os.remove(dxfTemp) # clean up - print 'reading finished in %.4f sec.' % (sys.time()-time1) - Window.WaitCursor(False) - else: - if UI_MODE: Draw.PupMenu('DWG importer: nothing imported!%t|No valid DXF-representation found!') - print 'DWG importer: nothing imported. No valid DXF-representation found.' - Window.WaitCursor(False) - if editmode: Window.EditMode(1) # and put things back how we fond them - return None - else: - if UI_MODE: Draw.PupMenu('DXF importer: Alert!%t| no valid DXF-file selected!') - print "DXF importer: Alert! - no valid DXF-file selected." - Window.WaitCursor(False) - if editmode: Window.EditMode(1) # and put things back how we fond them - return None - - # Draw all the know entity types in the current scene - oblist = [] # a list of all created AND linked objects for final f_globalScale - time2 = sys.time() #time marker2 - - Window.WaitCursor(True) # Let the user know we are thinking - settings.write("\n\nDrawing entities...") - - settings.validate(drawing) - - global activObjectLayer, activObjectName - activObjectLayer, activObjectName = None, None - - if M_OBJ: car_init() - - drawEntities(drawing.entities, settings) - - #print 'deb:drawEntities after: oblist:', oblist #----------------------- - if M_OBJ: car_end() - if oblist: # and settings.var['g_scale'] != 1: - globalScale(oblist, settings.var['g_scale']) - - # Set visibility for all layers on all View3d - #Window.ViewLayers([i+1 for i in range(18)]) # for 2.45 - SCENE.setLayers([i+1 for i in range(18)]) - SCENE.update(1) - SCENE.objects.selected = [i[0] for i in oblist] #select only the imported objects - #SCENE.objects.selected = SCENE.objects #select all objects in current scene - Blender.Redraw() - - time_text = sys.time() - time2 - Window.WaitCursor(False) - if settings.var['paper_space_on']: space = 'from paper space' - else: space = 'from model space' - ob_len = len(oblist) - message = ' %s objects imported %s in %.4f sec. -----DONE-----' % (ob_len, space, time_text) - settings.progress(1.0/settings.obj_number, 'DXF import done!') - print message - #settings.write(message) - if UI_MODE: Draw.PupMenu('DXF importer: Done!|finished in %.4f sec.' % time_text) - - #finally: - # restore state even if things didn't work - #print 'deb:drawEntities finally!' #----------------------- - Window.WaitCursor(False) - if editmode: Window.EditMode(1) # and put things back how we fond them - - - -def getOCS(az): #----------------------------------------------------------------- - """An implimentation of the Arbitrary Axis Algorithm. - """ - #decide if we need to transform our coords - #if az[0] == 0 and az[1] == 0: - if abs(az[0]) < 0.00001 and abs(az[1]) < 0.00001: - if az[2] > 0.0: - return False - elif az[2] < 0.0: - ax = Mathutils.Vector(-1.0, 0, 0) - ay = Mathutils.Vector(0, 1.0, 0) - az = Mathutils.Vector(0, 0, -1.0) - return ax, ay, az - - az = Mathutils.Vector(az) - - cap = 0.015625 # square polar cap value (1/64.0) - if abs(az.x) < cap and abs(az.y) < cap: - ax = M_CrossVecs(WORLDY,az) - else: - ax = M_CrossVecs(WORLDZ,az) - ax = ax.normalize() - ay = M_CrossVecs(az, ax) - ay = ay.normalize() - return ax, ay, az - - - -def transform(normal, rotation, obj): #-------------------------------------------- - """Use the calculated ocs to determine the objects location/orientation in space. - - Quote from dxf docs: - The elevation value stored with an entity and output in DXF files is a sum - of the Z-coordinate difference between the UCS XY plane and the OCS XY - plane, and the elevation value that the user specified at the time the entity - was drawn. - """ - ma = Mathutils.Matrix([1,0,0],[0,1,0],[0,0,1]) - o = Mathutils.Vector(obj.loc) - ocs = getOCS(normal) - if ocs: - ma = Mathutils.Matrix(ocs[0], ocs[1], ocs[2]) - o = ma.invert() * o - ma = Mathutils.Matrix(ocs[0], ocs[1], ocs[2]) - - if rotation != 0: - g = radians(-rotation) - rmat = Mathutils.Matrix([cos(g), -sin(g), 0], [sin(g), cos(g), 0], [0, 0, 1]) - ma = rmat * ma - - obj.setMatrix(ma) - obj.loc = o - #print 'deb:new obj.matrix:\n', obj.getMatrix() #-------------------- - - - -def rotXY_Vec(rotation, vec): #---------------------------------------------------- - """Rotate vector vec in XY-plane. vec must be in radians - """ - if rotation != 0: - o = Mathutils.Vector(vec) - g = radians(-rotation) - vec = o * Mathutils.Matrix([cos(g), -sin(g), 0], [sin(g), cos(g), 0], [0, 0, 1]) - return vec - - - -def getLayersmap(dxflayers): #------------------------------------------------------ - """Build two dictionaries: 1.layername:layer object, and 2.layername:layername_short - gets set of layers from TABLES SECTION LAYERS - """ - layersmap = {} - layernamesmap = {} - for item in dxflayers.data: - if type(item) != list and item.type == 'layer': - layersmap[item.name] = item - layername_short = item.name[:MAX_NAMELENGTH-1] - i = 0 #sufix for layernames cause Blender-objectnames-limits - while layername_short in layernamesmap.keys(): - i += 1 - suffix = str(i) #--todo--set zero-leading number format - layername_short = layername_short[:-2] + suffix - layernamesmap[item.name] = layername_short - - #print 'deb:getLayersmap layersmap:\n', layersmap #------------ - #print 'deb:getLayersmap layernamesmap:\n', layernamesmap #------------ - return layersmap, layernamesmap - - - -def getBlocksmap(drawing, layersmap, layFrozen_on=False): #-------------------------------------------------------- - """Build a dictionary of blockname:block_data pairs - """ - usedblocks = {} - for item in drawing.blocks.data: - #print 'deb:getBlocksmap item=%s\n i.entities=%s\n i.data=%s' %(item,item.entities,item.entities.data) - if type(item) != list and item.type == 'block': - childList = [] - used = False - for item2 in item.entities.data: - if type(item2) != list and item2.type == 'insert': - #print 'deb:getBlocksmap dir(item2)=', dir(item2) #---------- - item2str = [item2.name, item2.layer] - childList.append(item2str) - try: usedblocks[item.name] = [used, childList] - except KeyError: print 'Cannot find "%s" Block!' %(item.name) - #print 'deb:getBlocksmap: usedblocks=' , usedblocks #------------- - #print 'deb:getBlocksmap: layersmap=' , layersmap #------------- - - for item in drawing.entities.data: - if type(item) != list and item.type == 'insert': - if not layersmap or (not layersmap[item.layer].frozen or layFrozen_on): #if insert_layer is not frozen - try: usedblocks[item.name][0] = True - except KeyError: print 'Cannot find "%s" Block!' %(item.name) - - key_list = usedblocks.keys() - key_list.reverse() - for key in key_list: - if usedblocks[key][0]: #if parent used, then set used also all child blocks - for child in usedblocks[key][1]: - if not layersmap or (layersmap and not layersmap[child[1]].frozen): #if insert_layer is not frozen - try: usedblocks[child[0]][0] = True # marked as used BLOCK - except KeyError: print 'Cannot find "%s" Block!' %(child[0]) - - usedblocks = [i for i in usedblocks.keys() if usedblocks[i][0]] - #print 'deb:getBlocksmap: usedblocks=' , usedblocks #------------- - obj_number = 0 - blocksmap = {} - for item in drawing.blocks.data: - if type(item) != list and item.type == 'block' and item.name in usedblocks: - #if item.name.startswith('*X'): #--todo-- - obj_number += len(item.entities.data) - try: blocksmap[item.name] = item - except KeyError: print 'Cannot map "%s" - "%s" as Block!' %(item.name, item) - - - #print 'deb:getBlocksmap: blocksmap:\n', blocksmap #------------ - return blocksmap, obj_number - - -def getBlocknamesmap(blocksmap): #-------------------------------------------------------- - """Build a dictionary of blockname:blockname_short pairs - """ - #print 'deb:getBlocknamesmap blocksmap:\n', blocksmap #------------ - blocknamesmap = {} - for n in blocksmap.keys(): - blockname_short = n[:MAX_NAMELENGTH-1] - i = 0 #sufix for blockname cause Blender-objectnamelength-limit - while blockname_short in blocknamesmap.keys(): - i += 1 - suffix = str(i) - blockname_short = blockname_short[:-2] + suffix - blocknamesmap[n] = blockname_short - #print 'deb:getBlocknamesmap blocknamesmap:\n', blocknamesmap #------------ - return blocknamesmap - - -def drawEntities(entities, settings, block_def=None): #---------------------------------------- - """Draw every kind of thing in the entity list. - - If provided 'block_def': the entities are to be added to the Blender 'group'. - """ - for _type in type_map.keys(): - #print 'deb:drawEntities_type:', _type #------------------ - # for each known type get a list of that type and call the associated draw function - entities_type = entities.get_type(_type) - if entities_type: drawer(_type, entities_type, settings, block_def) - - -def drawer(_type, entities, settings, block_def): #------------------------------------------ - """Call with a list of entities and a settings object to generate Blender geometry. - - If 'block_def': the entities are to be added to the Blender 'group'. - """ - global layersmap, layersmapshort - #print 'deb:drawer _type, entities:\n ', _type, entities #----------------------- - - if entities: - # Break out early if settings says we aren't drawing the current dxf-type - global cur_COUNTER #counter for progress_bar - group = None - #print 'deb:drawer.check:_type: ', _type #-------------------- - if _type == '3dface':_type = 'face' # hack, while python_variable_name can not beginn with a nummber - if not settings.drawTypes[_type] or _type == 'block_record': - message = 'Skipping dxf\'%ss\' entities' %_type - settings.write(message, True) - cur_COUNTER += len(entities) - settings.progress(cur_COUNTER, message) - return - #print 'deb:drawer.todo:_type:', _type #----------------------- - #print 'deb:drawer entities:\n ', entities #----------------------- - - len_temp = len(entities) - # filtering only model-space enitities (no paper-space enitities) - if settings.var['paper_space_on']: - entities = [entity for entity in entities if entity.space != 0] - else: - entities = [entity for entity in entities if entity.space == 0] - - # filtering only objects with color from acceptedColorsList - if settings.var['colorFilter_on']: - entities = [entity for entity in entities if entity.color in settings.acceptedColors] - - # filtering only objects on layers from acceptedLayersList - if settings.var['layerFilter_on']: - #entities = [entity for entity in entities if entity.layer[0] in ['M','3','0'] and not entity.layer.endswith('H')] - entities = [entity for entity in entities if entity.layer in settings.acceptedLayers] - - # patch for incomplete layer table in HL2-DXF-files - if layersmap: - for entity in entities: - oblayer = entity.layer - if oblayer not in layersmap.keys(): - layer_obj = Layer(None, name=oblayer) - layersmap[oblayer] = layer_obj - layername_short = oblayer[:MAX_NAMELENGTH-1] - i = 0 #sufix for layernames cause Blender-objectnames-limits - while layername_short in layernamesmap.keys(): - i += 1 - suffix = str(i) #--todo--set zero-leading number format - layername_short = layername_short[:-2] + suffix - layernamesmap[oblayer] = layername_short - - # filtering only objects on not-frozen layers - if layersmap and not settings.var['layFrozen_on']: - entities = [entity for entity in entities if not layersmap[entity.layer].frozen] - - global activObjectLayer, activObjectName - activObjectLayer = '' - activObjectName = '' - - message = "Drawing dxf \'%ss\'..." %_type - cur_COUNTER += len_temp - len(entities) - settings.write(message, False) - settings.progress(cur_COUNTER, message) - if len(entities) > 0.1 / settings.obj_number: - show_progress = int(0.03 / settings.obj_number) - else: show_progress = 0 - cur_temp = 0 - - #print 'deb:drawer cur_COUNTER: ', cur_COUNTER #----------------------- - - for entity in entities: #----loop------------------------------------- - settings.write('\b.', False) - cur_COUNTER += 1 - if show_progress: - cur_temp += 1 - if cur_temp == show_progress: - settings.progress(cur_COUNTER, message) - cur_temp = 0 - #print 'deb:drawer show_progress=',show_progress #---------------- - - # get the layer group (just to make things a little cleaner) - if settings.var['group_bylayer_on'] and not block_def: - group = getGroup('l:%s' % layernamesmap[entity.layer]) - - if _type == 'insert': #---- INSERT and MINSERT=array -------------------- - if not settings.var['block_nn']: #----turn off support for noname BLOCKs - prefix = entity.name[:2] - if prefix in ('*X', '*U', '*D'): - #print 'deb:drawer entity.name:', entity.name #------------ - continue - if settings.var['blockFilter_on'] and not settings.accepted_block(entity.name): - continue - - #print 'deb:insert entity.loc:', entity.loc #---------------- - insertFlag = True - columns = entity.columns[0] - coldist = entity.columns[1] - rows = entity.rows[0] - rowdist = entity.rows[1] - deltaloc = [0,0,0] - #print 'deb:insert columns, rows:', columns, rows #----------- - for col in xrange(columns): - deltaloc[0] = col * coldist - for row in xrange(rows): - deltaloc[1] = row * rowdist - #print 'deb:insert col=%s, row=%s,deltaloc=%s' %(col, row, deltaloc) #------ - ob = entity.draw(settings, deltaloc) #-----draw BLOCK---------- - if block_def: - blockFlag = True - bl_loc = block_def[1] - ob.loc = [ob.loc[0]-bl_loc[0],ob.loc[1]-bl_loc[1],ob.loc[2]-bl_loc[2]] - else: blockFlag = False - setObjectProperties(ob, group, entity, settings, block_def) - if ob: - if settings.var['optimization'] <= settings.MIN: - #if settings.var['g_origin_on'] and not block_def: ob.loc = Mathutils.Vector(ob.loc) + settings.g_origin - if settings.var['g_scale_on']: globalScaleOne(ob, insertFlag, blockFlag, settings.var['g_scale']) - settings.redraw() - else: oblist.append((ob, insertFlag, blockFlag)) - - else: #---draw entities except BLOCKs/INSERTs--------------------- - insertFlag = False - alt_obname = activObjectName - ob = entity.draw(settings) - if ob: - if M_OBJ and ob.type=='Mesh': #'Curve', 'Text' - if block_def: - blockFlag = True - bl_loc = block_def[1] - ob.loc = [ob.loc[0]-bl_loc[0],ob.loc[1]-bl_loc[1],ob.loc[2]-bl_loc[2]] - car_nr() - - elif ob.name != alt_obname: - if block_def: - blockFlag = True - bl_loc = block_def[1] - ob.loc = [ob.loc[0]-bl_loc[0],ob.loc[1]-bl_loc[1],ob.loc[2]-bl_loc[2]] - else: blockFlag = False - setObjectProperties(ob, group, entity, settings, block_def) - if settings.var['optimization'] <= settings.MIN: - #if settings.var['g_origin_on'] and not block_def: ob.loc = Mathutils.Vector(ob.loc) + settings.g_origin - if settings.var['g_scale_on']: globalScaleOne(ob, insertFlag, blockFlag, settings.var['g_scale']) - settings.redraw() - else: oblist.append((ob, insertFlag, blockFlag)) - - #print 'deb:Finished drawing:', entities[0].type #------------------------ - message = "\nDrawing dxf\'%ss\' done!" % _type - settings.write(message, True) - - - -def globalScale(oblist, SCALE): #--------------------------------------------------------- - """Global_scale for list of all imported objects. - - oblist is a list of pairs (ob, insertFlag), where insertFlag=True/False - """ - #print 'deb:globalScale.oblist: ---------%\n', oblist #--------------------- - for l in oblist: - ob, insertFlag, blockFlag = l[0], l[1], l[2] - globalScaleOne(ob, insertFlag, blockFlag, SCALE) - - -def globalScaleOne(ob, insertFlag, blockFlag, SCALE): #--------------------------------------------------------- - """Global_scale imported object. - """ - #print 'deb:globalScaleOne ob: ', ob #--------------------- - if settings.var['g_origin_on'] and not blockFlag: - ob.loc = Mathutils.Vector(ob.loc) + settings.g_origin - - SCALE_MAT= Mathutils.Matrix([SCALE,0,0,0],[0,SCALE,0,0],[0,0,SCALE,0],[0,0,0,1]) - if insertFlag: # by BLOCKs/INSERTs only insert-point coords must be scaled------------ - ob.loc = Mathutils.Vector(ob.loc) * SCALE_MAT - else: # entire scaling for all other imported objects ------------ - if ob.type == 'Mesh': - me = ob.getData(name_only=False, mesh=True) - #me = Mesh.Get(ob.name) - # set centers of all objects in (0,0,0) - #me.transform(ob.matrixWorld*SCALE_MAT) - #ob.loc = Mathutils.Vector([0,0,0]) - # preseve centers of all objects - me.transform(SCALE_MAT) - ob.loc = Mathutils.Vector(ob.loc) * SCALE_MAT - else: #--todo-- also for curves: neutral scale factor after import - ob.setMatrix(ob.matrixWorld*SCALE_MAT) - - -def setObjectProperties(ob, group, entity, settings, block_def): #----------------------- - """Link object to scene. - """ - - if not ob: #remi--todo----------------------- - message = "\nObject \'%s\' not found!" %entity - settings.write(message) - return - - if group: - setGroup(group, ob) # if object belongs to group - - if block_def: # if object belongs to BLOCK_def - Move it to layer nr19 - setGroup(block_def[0], ob) - #print 'deb:setObjectProperties \'%s\' set to block_def_group!' %ob.name #--------- - ob.layers = [19] - else: - #ob.layers = [i+1 for i in xrange(20)] #remi--todo------------ - ob.layers = [settings.var['target_layer']] - - # Set material for any objects except empties - if ob.type != 'Empty' and settings.var['material_on']: - setMaterial_from(entity, ob, settings, block_def) - - # Set the visibility - #if settings.layer_isOff(entity.layer): - if layersmap and layersmap[entity.layer].color < 0: # color is negative if layer is off - #ob.layers = [20] #remi--todo------------- - ob.restrictDisplay = True - ob.restrictRender = True - - #print 'deb:\n---------linking Object %s!' %ob.name #---------- - - - -def getGroup(name): #----------------------------------------------------------------- - """Returns a Blender group-object. - """ - try: - group = Group.Get(name) - except: # What is the exception? - group = Group.New(name) - return group - - -def setGroup(group, ob): #------------------------------------------------------------ - """Assigns object to Blender group. - """ - try: - group.objects.link(ob) - except: - group.objects.append(ob) #remi?--------------- - - - -def setMaterial_from(entity, ob, settings, block_def): #------------------------------------------------ - """ Set Blender-material for the object controled by item. - - Set Blender-material for the object - - controlled by settings.var['material_from'] - """ - if settings.var['material_from'] == 1: # 1= material from color - if entity.color_index == BYLAYER or entity.color_index == 256: - mat = settings.colMaterials(entity.layer) - elif entity.color_index == BYBLOCK or entity.color_index == 0: - #--todo-- looking for block.color_index - #mat = settings.colMaterials(block.color_index) - #if block_def: mat = settings.colMaterials(block_def[2]) - mat = settings.colMaterials(3) - else: - mat = settings.colMaterials(entity.color_index) - - elif settings.var['material_from'] == 2: # 2= material from layer_name - mat = settings.layMaterials(layername=entity.layer) - - elif settings.var['material_from'] == 3: # 3= material from layer+color - mat = settings.layMaterials(layername=entity.layer, color=entity.color_index) - -# elif settings.var['material_from'] == 4: # 4= material from block_name - -# elif settings.var['material_from'] == 5: # 5= material from XDATA - -# elif settings.var['material_from'] == 6: # 6= material from INI-file - - else: # set neutral material - try: - mat = Material.Get('dxf-neutral') - except: - mat = Material.New('dxf-neutral') - mat.setRGBCol(color_map[3]) - try:mat.setMode('Shadeless', 'Wire') #work-around for 2.45rc1-bug - except: - mat.mode |= Material.Modes.SHADELESS # - mat.mode |= Material.Modes.WIRE - try: - #print 'deb:material mat:', mat #----------- - ob.setMaterials([mat]) #assigns Blender-material to object - except ValueError: - settings.write("material error - \'%s\'!" %mat) - ob.colbits = 0x01 # Set OB materials. - - - -def calcBulge(p1, p2, arc_res, triples=False): #------------------------------------------------- - """given startpoint, endpoint and bulge of arc, returns points/segments of its representation. - - Needs to take into account bulge sign. - negative = clockwise - positive = counter-clockwise - - to find center given two points, and arc angle - calculate radius - Cord = sqrt(start^2 + end^2) - S = (bulge*Cord)/2 - radius = ((Cord/2)^2+S^2)/2*S - angle of arc = 4*atan( bulge ) - angle from p1 to center is (180-angle)/2 - get vector pointing from p1 to p2 (p2 - p1) - normalize it and multiply by radius - rotate around p1 by angle to center, point to center. - start angle = angle between (center - p1) and worldX - end angle = angle between (center - p2) and worldX - - calculate the center, radius, start angle, and end angle - returns points/segments of its mesh representation - incl.startpoint, without endpoint - """ - - bulge = p1.bulge - p1 = Mathutils.Vector(p1.loc) - p2 = Mathutils.Vector(p2.loc) - cord = p2 - p1 # vector from p1 to p2 - clength = cord.length - s = (bulge * clength)/2.0 # sagitta (height) - radius = abs(((clength/2.0)**2.0 + s**2.0)/(2.0*s)) # magic formula - angle = (degrees(4.0*atan(bulge))) # theta (included angle) - radial = cord.normalize() * radius # a radius length vector aligned with cord - delta = (180.0 - abs(angle))/2.0 # the angle from cord to center - if bulge < 0: delta = -delta - rmat = Mathutils.RotationMatrix(-delta, 3, 'Z') - center = p1 + (rmat * radial) # rotate radial by delta degrees, then add to p1 to find center - #length = radians(abs(angle)) * radius - #print 'deb:calcBulge:\n angle, delta: ', angle, delta #---------------- - #print 'deb:center, radius: ', center, radius #---------------------- - startpoint = p1 - center - endpoint = p2 - center - #print 'deb:calcBulg: startpoint:', startpoint #--------- - #print 'deb:calcBulg: endpoint:', endpoint #--------- - - if not triples: #IF mesh-representation ----------- - if arc_res > 1024: arc_res = 1024 - elif arc_res < 4: arc_res = 4 - pieces = int(abs(angle)/(360.0/arc_res)) # set a fixed step of ARC_RESOLUTION - if pieces < 3: pieces = 3 - else: #IF curve-representation ------------------------------- - if arc_res > 32: arc_res = 32 - elif arc_res < 3: arc_res = 3 - pieces = int(abs(angle)/(360.0/arc_res)) # set a fixed step of ARC_RESOLUTION - if pieces < 2: pieces = 2 - - step = angle/pieces # set step so pieces * step = degrees in arc - stepmatrix = Mathutils.RotationMatrix(-step, 3, "Z") - - if not triples: #IF mesh-representation ----------- - points = [startpoint] - point = startpoint - for i in xrange(int(pieces)-1): #fast (but not so acurate as: vector * RotMatrix(-step*i,3,"Z") - point = stepmatrix * point - points.append(point) - points = [ point+center for point in points] - # vector to point convertion: - points = [list(point) for point in points] - return points, list(center) - - else: #IF curve-representation ------------------------------- - # correct Bezier curves representation for free segmented circles/arcs - step2 = radians(step * 0.5) - bulg = radius * (1 - cos(step2)) - deltaY = 4.0 * bulg / (3.0 * sin(step2) ) - #print 'deb:calcArcCurve: bulg, deltaY:\n', bulg, deltaY #--------- - #print 'deb:calcArcCurve: step:\n', step #--------- - - #org handler0 = Mathutils.Vector(0.0, -deltaY, 0.0) - #handler = startmatrix * handler0 - #endhandler = endmatrix * handler0 - rotMatr90 = Mathutils.Matrix([0, -1, 0], [1, 0, 0], [0, 0, 1]) - handler = rotMatr90 * startpoint - handler = - deltaY * handler.normalize() - endhandler = rotMatr90 * endpoint - endhandler = - deltaY * endhandler.normalize() - - points = [startpoint] - handlers1 = [startpoint + handler] - handlers2 = [startpoint - handler] - point = Mathutils.Vector(startpoint) - for i in xrange(int(pieces)-1): - point = stepmatrix * point - handler = stepmatrix * handler - handler1 = point + handler - handler2 = point - handler - points.append(point) - handlers1.append(handler1) - handlers2.append(handler2) - points.append(endpoint) - handlers1.append(endpoint + endhandler) - handlers2.append(endpoint - endhandler) - - points = [point + center for point in points] - handlers1 = [point + center for point in handlers1] - handlers2 = [point + center for point in handlers2] - - VectorTriples = [list(h1)+list(p)+list(h2) for h1,p,h2 in zip(handlers1, points, handlers2)] - #print 'deb:calcBulgCurve: handlers1:\n', handlers1 #--------- - #print 'deb:calcBulgCurve: points:\n', points #--------- - #print 'deb:calcBulgCurve: handlers2:\n', handlers2 #--------- - #print 'deb:calcBulgCurve: VectorTriples:\n', VectorTriples #--------- - return VectorTriples - - - - -def calcArc(center, radius, start, end, arc_res, triples): #----------------------------------------- - """calculate Points (or BezierTriples) for ARC/CIRCLEs representation. - - Given parameters of the ARC/CIRCLE, - returns points/segments (or BezierTriples) and centerPoint - """ - # center is currently set by object - # if start > end: start = start - 360 - if end > 360: end = end % 360.0 - - startmatrix = Mathutils.RotationMatrix(-start, 3, "Z") - startpoint = startmatrix * Mathutils.Vector(radius, 0, 0) - endmatrix = Mathutils.RotationMatrix(-end, 3, "Z") - endpoint = endmatrix * Mathutils.Vector(radius, 0, 0) - - if end < start: end +=360.0 - angle = end - start - #length = radians(angle) * radius - - if not triples: #IF mesh-representation ----------- - if arc_res > 1024: arc_res = 1024 - elif arc_res < 4: arc_res = 4 - pieces = int(abs(angle)/(360.0/arc_res)) # set a fixed step of ARC_RESOLUTION - if pieces < 3: pieces = 3 - step = angle/pieces # set step so pieces * step = degrees in arc - stepmatrix = Mathutils.RotationMatrix(-step, 3, "Z") - - points = [startpoint] - point = startpoint - for i in xrange(int(pieces)-1): - point = stepmatrix * point - points.append(point) - points.append(endpoint) - - if center: - centerVec = Mathutils.Vector(center) - #points = [point + centerVec for point in points()] - points = [point + centerVec for point in points] - # vector to point convertion: - points = [list(point) for point in points] - return points - - else: #IF curve-representation --------------- - if arc_res > 32: arc_res = 32 - elif arc_res < 3: arc_res = 3 - pieces = int(abs(angle)/(360.0/arc_res)) # set a fixed step of ARC_RESOLUTION - if pieces < 2: pieces = 2 - step = angle/pieces # set step so pieces * step = degrees in arc - stepmatrix = Mathutils.RotationMatrix(-step, 3, "Z") - - # correct Bezier curves representation for free segmented circles/arcs - step2 = radians(step * 0.5) - bulg = radius * (1 - cos(step2)) - deltaY = 4.0 * bulg / (3.0 * sin(step2) ) - #print 'deb:calcArcCurve: bulg, deltaY:\n', bulg, deltaY #--------- - #print 'deb:calcArcCurve: step:\n', step #--------- - handler0 = Mathutils.Vector(0.0, -deltaY, 0.0) - - points = [startpoint] - handler = startmatrix * handler0 - endhandler = endmatrix * handler0 - handlers1 = [startpoint + handler] - handlers2 = [startpoint - handler] - point = Mathutils.Vector(startpoint) - for i in xrange(int(pieces)-1): - point = stepmatrix * point - handler = stepmatrix * handler - handler1 = point + handler - handler2 = point - handler - points.append(point) - handlers1.append(handler1) - handlers2.append(handler2) - points.append(endpoint) - handlers1.append(endpoint + endhandler) - handlers2.append(endpoint - endhandler) - VectorTriples = [list(h1)+list(p)+list(h2) for h1,p,h2 in zip(handlers1, points, handlers2)] - #print 'deb:calcArcCurve: handlers1:\n', handlers1 #--------- - #print 'deb:calcArcCurve: points:\n', points #--------- - #print 'deb:calcArcCurve: handlers2:\n', handlers2 #--------- - #print 'deb:calcArcCurve: VectorTriples:\n', VectorTriples #--------- - return VectorTriples - - -def drawCurveCircle(circle): #--- no more used -------------------------------------------- - """Given a dxf circle object return a blender circle object using curves. - """ - c = Curve.New('circle') # create new curve data - center = circle.loc - radius = circle.radius - - p1 = (0, -radius, 0) - p2 = (radius, 0, 0) - p3 = (0, radius, 0) - p4 = (-radius, 0, 0) - - p1 = BezTriple.New(p1) - p2 = BezTriple.New(p2) - p3 = BezTriple.New(p3) - p4 = BezTriple.New(p4) - - curve = c.appendNurb(p1) - curve.append(p2) - curve.append(p3) - curve.append(p4) - for point in curve: - point.handleTypes = [AUTO, AUTO] - point.radius = 1.0 - curve.flagU = 1 # Set curve cyclic - c.update() - - ob = Object.New('Curve', 'circle') # make curve object - return ob - - -def drawCurveArc(self): #---- only for ELLIPSE ------------------------------------------------------------- - """Given a dxf ELLIPSE object return a blender_curve. - """ - center = self.loc - radius = self.radius - start = self.start_angle - end = self.end_angle - - if start > end: - start = start - 360.0 - startmatrix = Mathutils.RotationMatrix(start, 3, "Z") - startpoint = startmatrix * Mathutils.Vector((radius, 0, 0)) - endmatrix = Mathutils.RotationMatrix(end, 3, "Z") - endpoint = endmatrix * Mathutils.Vector((radius, 0, 0)) - # Note: handles must be tangent to arc and of correct length... - - a = Curve.New('arc') # create new curve data - - p1 = (0, -radius, 0) - p2 = (radius, 0, 0) - p3 = (0, radius, 0) - p4 = (-radius, 0, 0) - - p1 = BezTriple.New(p1) - p2 = BezTriple.New(p2) - p3 = BezTriple.New(p3) - p4 = BezTriple.New(p4) - - curve = a.appendNurb(p1) - curve.append(p2) - curve.append(p3) - curve.append(p4) - for point in curve: - point.handleTypes = [AUTO, AUTO] - point.radius = 1.0 - curve.flagU = 1 # Set curve cyclic - a.update() - - ob = Object.New('Curve', 'arc') # make curve object - return ob - - - - -# GUI STUFF -----#################################################----------------- -from Blender.BGL import glColor3f, glRecti, glClear, glRasterPos2d - -EVENT_NONE = 1 -EVENT_START = 2 -EVENT_REDRAW = 3 -EVENT_LOAD_INI = 4 -EVENT_SAVE_INI = 5 -EVENT_RESET = 6 -EVENT_CHOOSE_INI = 7 -EVENT_CHOOSE_DXF = 8 -EVENT_HELP = 9 -EVENT_PRESETCURV = 10 -EVENT_PRESETS = 11 -EVENT_DXF_DIR = 12 -# = 13 -EVENT_LIST = 14 -EVENT_ORIGIN = 15 -EVENT_SCALE = 16 -EVENT_PRESET2D = 20 -EVENT_PRESET3D = 21 -EVENT_EXIT = 100 -GUI_EVENT = EVENT_NONE - -GUI_A = {} # GUI-buttons dictionary for parameter -GUI_B = {} # GUI-buttons dictionary for drawingTypes - -# settings default, initialize ------------------------ - -points_as_menu = "convert to: %t|empty %x1|mesh.vertex %x2|thin sphere %x3|thin box %x4|..curve.vertex %x5" -lines_as_menu = "convert to: %t|..edge %x1|mesh %x2|..thin cylinder %x3|thin box %x4|Bezier-curve %x5|..NURBS-curve %x6" -mlines_as_menu = "convert to: %t|..edge %x1|..mesh %x2|..thin cylinder %x3|..thin box %x|..curve %x5" -plines_as_menu = "convert to: %t|..edge %x1|mesh %x2|..thin cylinder %x3|..thin box %x4|Bezier-curve %x5|NURBS-curve %x6" -splines_as_menu = "convert to: %t|mesh %x2|..thin cylinder %x3|..thin box %x4|Bezier-curve %x5|NURBS-curve %x6" -plines3_as_menu = "convert to: %t|..edge %x1|mesh %x2|..thin cylinder %x3|..thin box %x4|Bezier-curve %x5|NURBS-curve %x6" -plmesh_as_menu = "convert to: %t|..edge %x1|mesh %x2|..NURBS-surface %x6" -solids_as_menu = "convert to: %t|..edge %x1|mesh %x2" -blocks_as_menu = "convert to: %t|dupliGroup %x1|..real.Group %x2|..exploded %x3" -texts_as_menu = "convert to: %t|text %x1|..mesh %x2|..curve %x5" -material_from_menu= "material from: %t|..LINESTYLE %x7|COLOR %x1|LAYER %x2|..LAYER+COLOR %x3|..BLOCK %x4|..XDATA %x5|..INI-File %x6" -g_scale_list = ''.join(( - 'scale factor: %t', - '|user def. %x12', - '|yard to m %x8', - '|feet to m %x7', - '|inch to m %x6', - '| x 1000 %x3', - '| x 100 %x2', - '| x 10 %x1', - '| x 1 %x0', - '| x 0.1 %x-1', - '| x 0.01 %x-2', - '| x 0.001 %x-3', - '| x 0.0001 %x-4', - '| x 0.00001 %x-5')) - -#print 'deb: g_scale_list', g_scale_list #----------- - -dxfFileName = Draw.Create("") -iniFileName = Draw.Create(INIFILE_DEFAULT_NAME + INIFILE_EXTENSION) -user_preset = 0 -config_UI = Draw.Create(0) #switch_on/off extended config_UI -g_scale_as = Draw.Create(int(log10(G_SCALE))) - - -keywords_org = { - 'curves_on' : 0, - 'optimization': 2, - 'one_mesh_on': 1, - 'vGroup_on' : 1, - 'dummy_on' : 0, - 'views_on' : 0, - 'cams_on' : 0, - 'lights_on' : 0, - 'xref_on' : 1, - 'block_nn': 0, - 'blockFilter_on': 0, - 'layerFilter_on': 0, - 'colorFilter_on': 0, - 'groupFilter_on': 0, - 'newScene_on' : 1, - 'target_layer' : TARGET_LAYER, - 'group_bylayer_on' : GROUP_BYLAYER, - 'g_originX' : G_ORIGIN_X, - 'g_originY' : G_ORIGIN_Y, - 'g_originZ' : G_ORIGIN_Z, - 'g_origin_on': 0, - 'g_scale' : float(G_SCALE), -# 'g_scale_as': int(log10(G_SCALE)), # 0, - 'g_scale_on': 0, - 'thick_on' : 1, - 'thick_min' : float(MIN_THICK), - 'thick_force': 0, - 'width_on' : 1, - 'width_min' : float(MIN_WIDTH), - 'width_force': 0, - 'dist_on' : 1, - 'dist_min' : float(MIN_DIST), - 'dist_force': 0, - 'material_on': 1, - 'material_from': 2, - 'fill_on' : 1, - 'meshSmooth_on': 1, - 'curve_res' : CURV_RESOLUTION, - 'curve_arc' : CURVARC_RESOLUTION, - 'arc_res' : ARC_RESOLUTION, - 'arc_rad' : ARC_RADIUS, - 'thin_res' : THIN_RESOLUTION, - 'pl_trim_max' : TRIM_LIMIT, - 'pl_trim_on': 1, - 'plmesh_flip': 0, - 'normals_out': 0, - 'paper_space_on': 0, - 'layFrozen_on': 0, - 'Z_force_on': 0, - 'Z_elev': float(ELEVATION), - 'points_as' : 2, - 'lines_as' : 2, - 'mlines_as' : 2, - 'plines_as' : 2, - 'splines_as' : 5, - 'plines3_as': 2, - 'plmesh_as' : 2, - 'solids_as' : 2, - 'blocks_as' : 1, - 'texts_as' : 1 - } - -drawTypes_org = { - 'point' : 1, - 'line' : 1, - 'arc' : 1, - 'circle': 1, - 'ellipse': 1, - 'mline' : 0, - 'polyline': 1, - 'spline': 1, - 'plmesh': 1, - 'pline3': 1, - 'lwpolyline': 1, - 'text' : 1, - 'mtext' : 0, - 'block' : 1, - 'insert': 1, - 'solid' : 1, - 'trace' : 1, - 'face' : 1, -# 'view' : 0, - } - -# creating of GUI-buttons -# GUI_A - GUI-buttons dictionary for parameter -# GUI_B - GUI-buttons dictionary for drawingTypes -for k, v in keywords_org.iteritems(): - GUI_A[k] = Draw.Create(v) -for k, v in drawTypes_org.iteritems(): - GUI_B[k] = Draw.Create(v) -#print 'deb:init GUI_A: ', GUI_A #--------------- -#print 'deb:init GUI_B: ', GUI_B #--------------- - -model_space_on = Draw.Create(1) - -# initialize settings-object controls how dxf entities are drawn -settings = Settings(keywords_org, drawTypes_org) - - -def update_RegistryKey(key, item): # - """updates key in Blender.Registry - """ - cache = True # data is also saved to a file - rdict = Registry.GetKey('DXF_Importer', cache) - if not rdict: rdict = {} - if item: - rdict[key] = item - Registry.SetKey('DXF_Importer', rdict, cache) - #print 'deb:update_RegistryKey rdict', rdict #--------------- - - -def check_RegistryKey(key): - """ check if the key is already there (saved on a previous execution of this script) - """ - cache = True # data is also saved to a file - rdict = Registry.GetKey('DXF_Importer', cache) - #print 'deb:check_RegistryKey rdict:', rdict #---------------- - if rdict: # if found, get the values saved there - try: - item = rdict[key] - return item - except: - #update_RegistryKey() # if data isn't valid rewrite it - pass - -def saveConfig(): #--todo----------------------------------------------- - """Save settings/config/materials from GUI to INI-file. - - Write all config data to INI-file. - """ - global iniFileName - - iniFile = iniFileName.val - #print 'deb:saveConfig inifFile: ', inifFile #---------------------- - if iniFile.lower().endswith(INIFILE_EXTENSION): - - #--todo-- sort key.list for output - #key_list = GUI_A.keys().val - #key_list.sort() - #for key in key_list: - # l_name, l_data = key, GUI_A[key].val - # list_A - - output_str = '[%s,%s]' %(GUI_A, GUI_B) - if output_str =='None': - Draw.PupMenu('DXF importer: INI-file: Alert!%t|no config-data present to save!') - else: - #if BPyMessages.Warning_SaveOver(iniFile): #<- remi find it too abstarct - if sys.exists(iniFile): - f = file(iniFile, 'r') - header_str = f.readline() - f.close() - if header_str.startswith(INIFILE_HEADER[0:13]): - if Draw.PupMenu(' OK ? %t|SAVE OVER: ' + '\'%s\'' %iniFile) == 1: - save_ok = True - else: save_ok = False - elif Draw.PupMenu(' OK ? %t|SAVE OVER: ' + '\'%s\'' %iniFile + - '|Alert: this file has no valid ImportDXF-header| ! it may belong to another aplication !') == 1: - save_ok = True - else: save_ok = False - else: save_ok = True - - if save_ok: - # replace: ',' -> ',\n' - # replace: '{' -> '\n{\n' - # replace: '}' -> '\n}\n' - output_str = ',\n'.join(output_str.split(',')) - output_str = '\n}'.join(output_str.split('}')) - output_str = '{\n'.join(output_str.split('{')) - try: - f = file(iniFile, 'w') - f.write(INIFILE_HEADER + '\n# this is a comment line\n') - f.write(output_str) - f.close() - #Draw.PupMenu('DXF importer: INI-file: Done!%t|config-data saved in ' + '\'%s\'' %iniFile) - except: - Draw.PupMenu('DXF importer: INI-file: Error!%t|failure by writing to ' + '\'%s\'|no config-data saved!' %iniFile) - - else: - Draw.PupMenu('DXF importer: INI-file: Alert!%t|no valid name/extension for INI-file selected!') - print "DXF importer: Alert!: no valid INI-file selected." - if not iniFile: - if dxfFileName.val.lower().endswith('.dxf'): - iniFileName.val = dxfFileName.val[0:-4] + INIFILE_EXTENSION - - -def loadConfig(): #remi--todo----------------------------------------------- - """Load settings/config/materials from INI-file. - - Read material-assignements from config-file. - """ - #070724 buggy Window.FileSelector(loadConfigFile, 'Load config data from INI-file', inifilename) - global iniFileName, GUI_A, GUI_B - - iniFile = iniFileName.val - update_RegistryKey('iniFileName', iniFile) - #print 'deb:loadConfig iniFile: ', iniFile #---------------------- - if iniFile.lower().endswith(INIFILE_EXTENSION) and sys.exists(iniFile): - f = file(iniFile, 'r') - header_str = f.readline() - if header_str.startswith(INIFILE_HEADER): - data_str = f.read() - f.close() - #print 'deb:loadConfig data_str from %s: \n' %iniFile , data_str #----------------- - data = eval(data_str) - for k, v in data[0].iteritems(): - try: GUI_A[k].val = v - except: GUI_A[k] = Draw.Create(v) - for k, v in data[1].iteritems(): - try: GUI_B[k].val = v - except: GUI_B[k] = Draw.Create(v) - else: - f.close() - Draw.PupMenu('DXF importer: INI-file: Alert!%t|no valid header in INI-file: ' + '\'%s\'' %iniFile) - else: - Draw.PupMenu('DXF importer: INI-file: Alert!%t|no valid INI-file selected!') - print "DXF importer: Alert!: no valid INI-file selected." - if not iniFileName: - if dxfFileName.val.lower().endswith('.dxf'): - iniFileName.val = dxfFileName.val[0:-4] + INIFILE_EXTENSION - - - -def updateConfig(keywords, drawTypes): #----------------------------------------------- - """updates GUI_settings with given dictionaries - - """ - global GUI_A, GUI_B - #print 'deb:lresetDefaultConfig keywords_org: \n', keywords_org #--------- - for k, v in keywords.iteritems(): - GUI_A[k].val = v - for k, v in drawTypes.iteritems(): - GUI_B[k].val = v - -def resetDefaultConfig(): #----------------------------------------------- - """Resets settings/config/materials to defaults. - - """ - #print 'deb:lresetDefaultConfig keywords_org: \n', keywords_org #--------- - updateConfig(keywords_org, drawTypes_org) - - -def presetConfig_curv(activate): #----------------------------------------------- - """Sets settings/config/materials for curve representation. - - """ - global GUI_A - if activate: - GUI_A['curves_on'].val = 1 - GUI_A['points_as'].val = 5 - GUI_A['lines_as'].val = 5 - GUI_A['mlines_as'].val = 5 - GUI_A['plines_as'].val = 5 - GUI_A['splines_as'].val = 5 - GUI_A['plines3_as'].val = 5 - else: - GUI_A['curves_on'].val = 0 - GUI_A['points_as'].val = 2 - GUI_A['lines_as'].val = 2 - GUI_A['mlines_as'].val = 2 - GUI_A['plines_as'].val = 2 - GUI_A['splines_as'].val = 6 - GUI_A['plines3_as'].val = 2 - - -def resetDefaultConfig_2D(): #----------------------------------------------- - """Sets settings/config/materials to defaults 2D. - - """ - presetConfig_curv(1) - keywords2d = { - 'views_on' : 0, - 'cams_on' : 0, - 'lights_on' : 0, - 'vGroup_on' : 1, - 'thick_on' : 0, - 'thick_force': 0, - 'width_on' : 1, - 'width_force': 0, - 'dist_on' : 1, - 'dist_force': 0, - 'fill_on' : 0, - 'pl_trim_on': 1, - 'Z_force_on': 0, - 'meshSmooth_on': 0, - 'solids_as' : 2, - 'blocks_as' : 1, - 'texts_as' : 1 - } - - drawTypes2d = { - 'point' : 1, - 'line' : 1, - 'arc' : 1, - 'circle': 1, - 'ellipse': 1, - 'mline' : 0, - 'polyline': 1, - 'spline': 1, - 'plmesh': 0, - 'pline3': 1, - 'lwpolyline': 1, - 'text' : 1, - 'mtext' : 0, - 'block' : 1, - 'insert': 1, - 'solid' : 1, - 'trace' : 1, - 'face' : 0, -# 'view' : 0, - } - - updateConfig(keywords2d, drawTypes2d) - -def resetDefaultConfig_3D(): #----------------------------------------------- - """Sets settings/config/materials to defaults 3D. - - """ - presetConfig_curv(0) - keywords3d = { -# 'views_on' : 1, -# 'cams_on' : 1, -# 'lights_on' : 1, - 'vGroup_on' : 1, - 'thick_on' : 1, - 'thick_force': 0, - 'width_on' : 1, - 'width_force': 0, - 'dist_on' : 1, - 'dist_force': 0, - 'fill_on' : 1, - 'pl_trim_on': 1, - 'Z_force_on': 0, - 'meshSmooth_on': 1, - 'solids_as' : 2, - 'blocks_as' : 1, - 'texts_as' : 1 - } - - drawTypes3d = { - 'point' : 1, - 'line' : 1, - 'arc' : 1, - 'circle': 1, - 'ellipse': 1, - 'mline' : 0, - 'polyline': 1, - 'spline': 1, - 'plmesh': 1, - 'pline3': 1, - 'lwpolyline': 1, - 'text' : 0, - 'mtext' : 0, - 'block' : 1, - 'insert': 1, - 'solid' : 1, - 'trace' : 1, - 'face' : 1, -# 'view' : 0, - } - - updateConfig(keywords3d, drawTypes3d) - - -def inputGlobalScale(): - """Pop-up UI-Block for global scale factor - """ - global GUI_A - #print 'deb:inputGlobalScale ##########' #------------ - x_scale = Draw.Create(GUI_A['g_scale'].val) - block = [] - #block.append("global translation vector:") - block.append(("", x_scale, 0.0, 10000000.0)) - - retval = Draw.PupBlock("set global scale factor:", block) - - GUI_A['g_scale'].val = float(x_scale.val) - - -def inputOriginVector(): - """Pop-up UI-Block for global translation vector - """ - global GUI_A - #print 'deb:inputOriginVector ##########' #------------ - x_origin = Draw.Create(GUI_A['g_originX'].val) - y_origin = Draw.Create(GUI_A['g_originY'].val) - z_origin = Draw.Create(GUI_A['g_originZ'].val) - block = [] - #block.append("global translation vector:") - block.append(("X: ", x_origin, -100000000.0, 100000000.0)) - block.append(("Y: ", y_origin, -100000000.0, 100000000.0)) - block.append(("Z: ", z_origin, -100000000.0, 100000000.0)) - - retval = Draw.PupBlock("set global translation vector:", block) - - GUI_A['g_originX'].val = x_origin.val - GUI_A['g_originY'].val = y_origin.val - GUI_A['g_originZ'].val = z_origin.val - - -def draw_UI(): #----------------------------------------------------------------- - """ Draw startUI and setup Settings. - """ - global GUI_A, GUI_B #__version__ - global user_preset, iniFileName, dxfFileName, config_UI, g_scale_as - global model_space_on - - # This is for easy layout changes - but_0c = 70 #button 1.column width - but_1c = 70 #button 1.column width - but_2c = 70 #button 2.column - but_3c = 70 #button 3.column - menu_margin = 10 - butt_margin = 10 - menu_w = (3 * butt_margin) + but_0c + but_1c + but_2c + but_3c #menu width - - simple_menu_h = 100 - extend_menu_h = 350 - y = simple_menu_h # y is menu upper.y - if config_UI.val: y += extend_menu_h - x = 20 #menu left.x - but0c = x + menu_margin #buttons 0.column position.x - but1c = but0c + but_0c + butt_margin - but2c = but1c + but_1c + butt_margin - but3c = but2c + but_2c + butt_margin - but4c = but3c + but_3c - - # Here starts menu ----------------------------------------------------- - #glClear(GL_COLOR_BUFFER_BIT) - #glRasterPos2d(8, 125) - - y += 30 - colorbox(x, y+20, x+menu_w+menu_margin*2, menu_margin) - Draw.Label("DXF/DWG-Importer v" + __version__, but0c, y, menu_w, 20) - - if config_UI.val: - b0, b0_ = but0c, but_0c + butt_margin - b1, b1_ = but1c, but_1c - y_top = y - - y -= 10 - y -= 20 - Draw.BeginAlign() - GUI_B['point'] = Draw.Toggle('POINT', EVENT_REDRAW, b0, y, b0_, 20, GUI_B['point'].val, "support dxf-POINT on/off") - if GUI_B['point'].val: - GUI_A['points_as'] = Draw.Menu(points_as_menu, EVENT_NONE, b1, y, b1_, 20, GUI_A['points_as'].val, "select target Blender-object") -# Draw.Label('-->', but2c, y, but_2c, 20) - Draw.EndAlign() - - y -= 20 - Draw.BeginAlign() - GUI_B['line'] = Draw.Toggle('LINE...etc', EVENT_REDRAW, b0, y, b0_, 20, GUI_B['line'].val, "support dxf-LINE,ARC,CIRCLE,ELLIPSE on/off") - if GUI_B['line'].val: - GUI_A['lines_as'] = Draw.Menu(lines_as_menu, EVENT_NONE, but1c, y, but_1c, 20, GUI_A['lines_as'].val, "select target Blender-object") - Draw.EndAlign() - - y -= 20 - Draw.BeginAlign() - GUI_B['mline'] = Draw.Toggle('..MLINE', EVENT_REDRAW, b0, y, b0_, 20, GUI_B['mline'].val, "(*todo)support dxf-MLINE on/off") - if GUI_B['mline'].val: - GUI_A['mlines_as'] = Draw.Menu(mlines_as_menu, EVENT_NONE, but1c, y, but_1c, 20, GUI_A['mlines_as'].val, "select target Blender-object") - Draw.EndAlign() - - y -= 20 - Draw.BeginAlign() - GUI_B['spline'] = Draw.Toggle('SPLINE', EVENT_REDRAW, b0, y, b0_, 20, GUI_B['spline'].val, "support dxf-SPLINE on/off") - if GUI_B['spline'].val: - GUI_A['splines_as'] = Draw.Menu(splines_as_menu, EVENT_NONE, but1c, y, but_1c, 20, GUI_A['splines_as'].val, "select target Blender-object") - Draw.EndAlign() - - y -= 20 - Draw.BeginAlign() - GUI_B['polyline'] = Draw.Toggle('2D/LWPLINE', EVENT_REDRAW, b0, y, b0_, 20, GUI_B['polyline'].val, "support dxf-2D-POLYLINE on/off") - if GUI_B['polyline'].val: - GUI_A['plines_as'] = Draw.Menu(plines_as_menu, EVENT_NONE, but1c, y, but_1c, 20, GUI_A['plines_as'].val, "select target Blender-object") - Draw.EndAlign() - - y -= 20 - Draw.BeginAlign() - GUI_B['pline3'] = Draw.Toggle('3D-PLINE', EVENT_REDRAW, b0, y, b0_, 20, GUI_B['pline3'].val, "support dxf-3D-POLYLINE on/off") - if GUI_B['pline3'].val: - GUI_A['plines3_as'] = Draw.Menu(plines3_as_menu, EVENT_NONE, but1c, y, but_1c, 20, GUI_A['plines3_as'].val, "select target Blender-object") - Draw.EndAlign() - - y_down = y - # ----------------------------------------------- - - y = y_top - b0, b0_ = but2c, but_2c + butt_margin - b1, b1_ = but3c, but_3c - - y -= 10 - y -= 20 - Draw.BeginAlign() - GUI_B['plmesh'] = Draw.Toggle('PL-MESH/FACE', EVENT_NONE, b0, y, b0_+b1_-40, 20, GUI_B['plmesh'].val, "support dxf-POLYMESH/POLYFACE on/off") -# GUI_A['plmesh_as'] = Draw.Menu(plmesh_as_menu, EVENT_NONE, but1c, y, but_1c, 20, GUI_A['plmesh_as'].val, "select target Blender-object") - GUI_A['plmesh_flip'] = Draw.Toggle('N', EVENT_NONE, b1+b1_-40, y, 20, 20, GUI_A['plmesh_flip'].val, "flip DXF normals on/off") - GUI_A['normals_out'] = Draw.Toggle('N', EVENT_NONE, b1+b1_-20, y, 20, 20, GUI_A['normals_out'].val, "force Blender normals to outside on/off") - Draw.EndAlign() - - y -= 20 - GUI_B['solid'] = Draw.Toggle('SOLID', EVENT_NONE, b0, y, b0_, 20, GUI_B['solid'].val, "support dxf-SOLID and TRACE on/off") - GUI_B['face'] = Draw.Toggle('3DFACE', EVENT_NONE, b1, y, b1_, 20, GUI_B['face'].val, "support dxf-3DFACE on/off") -# GUI_A['solids_as'] = Draw.Menu(solids_as_menu, EVENT_NONE, but3c, y, but_3c, 20, GUI_A['solids_as'].val, "select target Blender-object") - #print 'deb:support solid, trace', GUI_B['trace'].val, GUI_B['solid'].val # ------------ - - - y -= 20 - GUI_B['text'] = Draw.Toggle('TEXT', EVENT_NONE, b0, y, b0_, 20, GUI_B['text'].val, "support dxf-TEXT on/off") - GUI_B['mtext'] = Draw.Toggle('..MTEXT', EVENT_NONE, b1, y, b1_, 20, GUI_B['mtext'].val, "(*todo)support dxf-MTEXT on/off") -# GUI_A['texts_as'] = Draw.Menu(texts_as_menu, EVENT_NONE, but3c, y, but_3c, 20, GUI_A['texts_as'].val, "select target Blender-object") - - y -= 20 - Draw.BeginAlign() - GUI_B['block'] = Draw.Toggle('BLOCK', EVENT_REDRAW, b0, y, b0_-30, 20, GUI_B['block'].val, "support dxf-BLOCK and ARRAY on/off") - GUI_B['insert'].val = GUI_B['block'].val - if GUI_B['block'].val: - GUI_A['block_nn'] = Draw.Toggle('n', EVENT_NONE, b1-30, y, 15, 20, GUI_A['block_nn'].val, "support hatch/noname BLOCKs *X... on/off") - GUI_A['xref_on'] = Draw.Toggle('Xref', EVENT_NONE, b1-15, y, 35, 20, GUI_A['xref_on'].val, "support for XREF-BLOCKs (place holders) on/off") - GUI_A['blocks_as'] = Draw.Menu(blocks_as_menu, EVENT_NONE, b1+20, y, b1_-20, 20, GUI_A['blocks_as'].val, "select target representation for imported BLOCKs") - Draw.EndAlign() - - - y -= 20 - y -= 20 - - Draw.BeginAlign() - GUI_A['views_on'] = Draw.Toggle('views', EVENT_NONE, b0, y, b0_-25, 20, GUI_A['views_on'].val, "imports VIEWs and VIEWPORTs as cameras on/off") - GUI_A['cams_on'] = Draw.Toggle('..cams', EVENT_NONE, b1-25, y, b1_-25, 20, GUI_A['cams_on'].val, "(*todo) support ASHADE cameras on/off") - GUI_A['lights_on'] = Draw.Toggle('..lights', EVENT_NONE, b1+25, y, b1_-25, 20, GUI_A['lights_on'].val, "(*todo) support AVE_RENDER lights on/off") - Draw.EndAlign() - - - if y < y_down: y_down = y - # -----end supported objects-------------------------------------- - - y_top = y_down - y = y_top - y -= 10 - y -= 20 - but_ = menu_w / 6 - b0 = but0c + (menu_w - but_*6)/2 - Draw.BeginAlign() - GUI_A['paper_space_on'] = Draw.Toggle('paper', EVENT_NONE, b0+but_*0, y, but_, 20, GUI_A['paper_space_on'].val, "import only from Paper-Space on/off") - GUI_A['layFrozen_on'] = Draw.Toggle ('frozen', EVENT_NONE, b0+but_*1, y, but_, 20, GUI_A['layFrozen_on'].val, "import also from frozen LAYERs on/off") - GUI_A['layerFilter_on'] = Draw.Toggle('..layer', EVENT_NONE, b0+but_*2, y, but_, 20, GUI_A['layerFilter_on'].val, "(*todo) LAYER filtering on/off") - GUI_A['colorFilter_on'] = Draw.Toggle('..color', EVENT_NONE, b0+but_*3, y, but_, 20, GUI_A['colorFilter_on'].val, "(*todo) COLOR filtering on/off") - GUI_A['groupFilter_on'] = Draw.Toggle('..group', EVENT_NONE, b0+but_*4, y, but_, 20, GUI_A['groupFilter_on'].val, "(*todo) GROUP filtering on/off") - GUI_A['blockFilter_on'] = Draw.Toggle('..block', EVENT_NONE, b0+but_*5, y, but_, 20, GUI_A['blockFilter_on'].val, "(*todo) BLOCK filtering on/off") - #GUI_A['dummy_on'] = Draw.Toggle('-', EVENT_NONE, but3c, y, but_3c, 20, GUI_A['dummy_on'].val, "dummy on/off") - Draw.EndAlign() - - # -----end filters-------------------------------------- - - b0, b0_ = but0c, but_0c + butt_margin - b1, b1_ = but1c, but_1c - - y -= 10 - y -= 20 - Draw.BeginAlign() - GUI_A['g_origin_on'] = Draw.Toggle('glob.reLoc', EVENT_REDRAW, b0, y, b0_, 20, GUI_A['g_origin_on'].val, "global relocate all DXF objects on/off") - if GUI_A['g_origin_on'].val: - tmp = Draw.PushButton('=', EVENT_ORIGIN, b1, y, 20, 20, "edit relocation-vector (x,y,z in DXF units)") - origin_str = '(%.4f, %.4f, %.4f)' % ( - GUI_A['g_originX'].val, - GUI_A['g_originY'].val, - GUI_A['g_originZ'].val - ) - tmp = Draw.Label(origin_str, b1+20, y, 300, 20) - #GUI_A['g_origin'] = Draw.String('', EVENT_ORIGIN, b1, y, b1_, 20, GUI_A['g_origin'].val, "global translation-vector (x,y,z) in DXF units") - Draw.EndAlign() - - y -= 20 - Draw.BeginAlign() - GUI_A['g_scale_on'] = Draw.Toggle('glob.Scale', EVENT_REDRAW, b0, y, b0_, 20, GUI_A['g_scale_on'].val, "global scale all DXF objects on/off") - if GUI_A['g_scale_on'].val: - g_scale_as = Draw.Menu(g_scale_list, EVENT_SCALE, b1, y, 45, 20, g_scale_as.val, "factor for scaling the DXFdata") - if g_scale_as.val == 12: - pass - else: - if g_scale_as.val == 6: #scale inches to meters - GUI_A['g_scale'].val = 0.0254000 - elif g_scale_as.val == 7: #scale feets to meters - GUI_A['g_scale'].val = 0.3048000 - elif g_scale_as.val == 8: #scale yards to meters - GUI_A['g_scale'].val = 0.9144000 - else: - GUI_A['g_scale'].val = 10.0 ** int(g_scale_as.val) - scale_float = GUI_A['g_scale'].val - if scale_float < 0.000001 or scale_float > 1000000: - scale_str = ' = %s' % GUI_A['g_scale'].val - else: - scale_str = ' = %.6f' % GUI_A['g_scale'].val - Draw.Label(scale_str, b1+45, y, 200, 20) - Draw.EndAlign() - - y_down = y - # -----end material,translate,scale------------------------------------------ - - b0, b0_ = but0c, but_0c + butt_margin - b1, b1_ = but1c, but_1c - - y_top = y_down - y = y_top - y -= 10 - y -= 20 - Draw.BeginAlign() - GUI_A['meshSmooth_on'] = Draw.Toggle('smooth', EVENT_NONE, b0, y, b0_-20, 20, GUI_A['meshSmooth_on'].val, "mesh smooth for circles/arc-segments on/off") - GUI_A['pl_trim_on'] = Draw.Toggle('trim', EVENT_NONE, b1-20, y, 32, 20, GUI_A['pl_trim_on'].val, "clean intersection of POLYLINE-wide-segments on/off") - GUI_A['pl_trim_max'] = Draw.Number('', EVENT_NONE, b1+12, y, b1_-12, 20, GUI_A['pl_trim_max'].val, 0, 5, "threshold intersection of POLYLINE-wide-segments: 0.0-5.0") - Draw.EndAlign() - - y -= 20 - Draw.BeginAlign() -# GUI_A['thin_res'] = Draw.Number('thin:', EVENT_NONE, but0c, y, but_0c, 20, GUI_A['thin_res'].val, 4, 64, "thin cylinder resolution - number of segments (4-64)") - GUI_A['arc_rad'] = Draw.Number('bR:', EVENT_NONE, b0, y, b0_, 20, GUI_A['arc_rad'].val, 0.01, 100, "basis radius for arc/circle resolution (0.01-100)") - GUI_A['arc_res'] = Draw.Number('', EVENT_NONE, b1, y, b1_/2, 20, GUI_A['arc_res'].val, 3, 500, "arc/circle resolution - number of segments (3-500)") - GUI_A['fill_on'] = Draw.Toggle('caps', EVENT_NONE, b1+b1_/2, y, b1_/2, 20, GUI_A['fill_on'].val, "draws top and bottom caps of CYLINDERs/closed curves on/off") - Draw.EndAlign() - - y -= 20 - Draw.BeginAlign() - GUI_A['curve_arc'] = Draw.Number('', EVENT_NONE, b0, y, b0_/2, 20, GUI_A['curve_arc'].val, 3, 32, "Bezier circle: amount of segments: 3-32") - GUI_A['curve_res'] = Draw.Number('', EVENT_NONE, b0+b0_/2, y, b0_/2, 20, GUI_A['curve_res'].val, 1, 128, "Set the Curve's U-resolution value: 1-128") - GUI_A['curves_on'] = Draw.Toggle('to Curves', EVENT_PRESETCURV, b1, y, b1_, 20, GUI_A['curves_on'].val, "set Curve as target object type on/off") - Draw.EndAlign() - - y -= 20 - GUI_A['group_bylayer_on'] = Draw.Toggle('Layer', EVENT_NONE, b0, y, 30, 20, GUI_A['group_bylayer_on'].val, "DXF-entities group by layer on/off") - GUI_A['vGroup_on'] = Draw.Toggle('vGroups', EVENT_NONE, b0+30, y, b1_-10, 20, GUI_A['vGroup_on'].val, "sort faces into VertexGroups on/off") - GUI_A['one_mesh_on'] = Draw.Toggle('oneMesh', EVENT_NONE, b1+10, y, b1_-10, 20, GUI_A['one_mesh_on'].val, "draw DXF-entities into one mesh-object. Recommended for big DXF-files. on/off") - - y -= 30 - Draw.BeginAlign() - GUI_A['material_on'] = Draw.Toggle('material', EVENT_REDRAW, b0, y, b0_-20, 20, GUI_A['material_on'].val, "support for material assignment on/off") - if GUI_A['material_on'].val: - GUI_A['material_from'] = Draw.Menu(material_from_menu, EVENT_NONE, b1-20, y, b1_+20, 20, GUI_A['material_from'].val, "material assignment from?") - Draw.EndAlign() - - y_down = y - # ----------------------------------------------- - - b0, b0_ = but2c, but_2c + butt_margin - b1, b1_ = but3c, but_3c - - y = y_top - y -= 10 - y -= 20 - Draw.BeginAlign() - GUI_A['Z_force_on'] = Draw.Toggle('.elevation', EVENT_REDRAW, b0, y, b0_, 20, GUI_A['Z_force_on'].val, ".set objects Z-coordinates to elevation on/off") - if GUI_A['Z_force_on'].val: - GUI_A['Z_elev'] = Draw.Number('', EVENT_NONE, b1, y, b1_, 20, GUI_A['Z_elev'].val, -1000, 1000, "set default elevation(Z-coordinate)") - Draw.EndAlign() - - y -= 20 - Draw.BeginAlign() - GUI_A['dist_on'] = Draw.Toggle('dist.:', EVENT_NONE, b0, y, b0_-20, 20, GUI_A['dist_on'].val, "support distance on/off") - GUI_A['dist_force'] = Draw.Toggle('F', EVENT_NONE, b0+b0_-20, y, 20, 20, GUI_A['dist_force'].val, "force minimal distance on/off") - GUI_A['dist_min'] = Draw.Number('', EVENT_NONE, b1, y, b1_, 20, GUI_A['dist_min'].val, 0, 10, "minimal length/distance (double.vertex removing)") - Draw.EndAlign() - - y -= 20 - Draw.BeginAlign() - GUI_A['thick_on'] = Draw.Toggle('thick:', EVENT_NONE, b0, y, b0_-20, 20, GUI_A['thick_on'].val, "support thickness on/off") - GUI_A['thick_force'] = Draw.Toggle('F', EVENT_REDRAW, b0+b0_-20, y, 20, 20, GUI_A['thick_force'].val, "force for thickness at least limiter value on/off") - if GUI_A['thick_force'].val: - GUI_A['thick_min'] = Draw.Number('', EVENT_NONE, b1, y, b1_, 20, GUI_A['thick_min'].val, 0, 10, "minimal value for thickness") - Draw.EndAlign() - - y -= 20 - Draw.BeginAlign() - GUI_A['width_on'] = Draw.Toggle('width:', EVENT_NONE, b0, y, b0_-20, 20, GUI_A['width_on'].val, "support width on/off") - GUI_A['width_force'] = Draw.Toggle('F', EVENT_REDRAW, b0+b0_-20, y, 20, 20, GUI_A['width_force'].val, "force for width at least limiter value on/off") - if GUI_A['width_force'].val: - GUI_A['width_min'] = Draw.Number('', EVENT_NONE, b1, y, b1_, 20, GUI_A['width_min'].val, 0, 10, "minimal value for width") - Draw.EndAlign() - - y -= 30 - but, but_ = but2c, 25 - Draw.BeginAlign() - Draw.EndAlign() - - if y < y_down: y_down = y - # -----end options -------------------------------------- - - - #-------------------------------------- - y_top = y_down - y = y_top - #GUI_A['dummy_on'] = Draw.Toggle(' - ', EVENT_NONE, but0c, y, but_0c, 20, GUI_A['dummy_on'].val, "reserved") - y -= 30 - Draw.BeginAlign() - Draw.PushButton('INI file >', EVENT_CHOOSE_INI, but0c, y, but_0c, 20, 'Select INI-file from project directory') - iniFileName = Draw.String(' :', EVENT_NONE, but1c, y, menu_w-but_1c-60, 20, iniFileName.val, FILENAME_MAX, "write here the name of the INI-file") - but = but4c-60 - Draw.PushButton('#', EVENT_PRESETS, but, y, 20, 20, "toggle Preset-INI-files") - Draw.PushButton('L', EVENT_LOAD_INI, but+20, y, 20, 20, 'Loads configuration from ini-file: %s' % iniFileName.val) - Draw.PushButton('S', EVENT_SAVE_INI, but+40, y, 20, 20, 'Saves configuration to ini-file: %s' % iniFileName.val) - Draw.EndAlign() - - - b0, b0_ = but2c, but_2c + butt_margin - b1, b1_ = but3c, but_3c - - y = simple_menu_h - bm = butt_margin/2 - - #y -= 10 - Draw.BeginAlign() - Draw.PushButton('DXFfile >', EVENT_CHOOSE_DXF, but0c, y, but_0c, 20, 'Select DXF/DWG-file for import') - dxfFileName = Draw.String(' :', EVENT_NONE, but1c, y, but_1c+but_2c+but_3c-20, 20, dxfFileName.val, FILENAME_MAX, "type the name of DXF/DWG-file or type *.dxf/*.dwg for multiple files") - Draw.PushButton('*.*', EVENT_DXF_DIR, but3c+but_3c-20, y, 20, 20, 'set filter for import all files from this directory') - Draw.EndAlign() - - y -= 30 - config_UI = Draw.Toggle('CONFIG', EVENT_REDRAW, but0c, y, but_0c+bm, 20, config_UI.val, 'Advanced configuration on/off' ) - Draw.BeginAlign() - but, but_ = but1c, but_1c+bm - but_ /= 3 - Draw.PushButton('X', EVENT_RESET, but, y, 15, 20, "reset configuration to defaults") - Draw.PushButton('2D', EVENT_PRESET2D, but+but_, y, but_, 20, 'set configuration for 2D import') - Draw.PushButton('3D', EVENT_PRESET3D, but+(but_*2), y, but_, 20, 'set configuration for 3D import') - Draw.EndAlign() - - Draw.BeginAlign() - GUI_A['newScene_on'] = Draw.Toggle('newScene', EVENT_NONE, but2c, y, but_2c, 20, GUI_A['newScene_on'].val, "create new Scene for each imported dxf file on/off") - GUI_A['target_layer'] = Draw.Number('layer', EVENT_NONE, but3c, y, but_3c, 20, GUI_A['target_layer'].val, 1, 18, "target Blender-layer (<19> reserved for block_definitions)") - Draw.EndAlign() - - y -= 40 - Draw.PushButton('EXIT', EVENT_EXIT, but0c, y, but_0c+bm, 20, '' ) - Draw.PushButton('HELP', EVENT_HELP, but1c, y, but_1c+bm, 20, 'calls DXF-Importer Manual Page on Wiki.Blender.org') - Draw.BeginAlign() - GUI_A['optimization'] = Draw.Number('', EVENT_NONE, but2c, y+20, 40, 20, GUI_A['optimization'].val, 0, 3, "Optimization Level: 0=Debug/directDrawing, 1=Verbose, 2=ProgressBar, 3=SilentMode") - Draw.EndAlign() - Draw.BeginAlign() - Draw.PushButton('TEST', EVENT_LIST, but2c, y, 40, 20, 'DXF-Analyze-Tool: reads data from selected dxf file and writes report in project_directory/dxf_blendname.INF') - Draw.PushButton('START IMPORT', EVENT_START, but2c+40, y, but_2c-40+but_3c+butt_margin, 40, 'Start the import process. For Cancel go to console and hit Ctrl-C') - Draw.EndAlign() - - - - - y -= 20 - Draw.BeginAlign() - Draw.Label(' ', but0c-menu_margin, y, menu_margin, 20) - Draw.Label(LAB, but0c, y, menu_w, 20) - Draw.Label(' ', but0c+menu_w, y, menu_margin, 20) - Draw.EndAlign() - -#-- END GUI Stuf----------------------------------------------------- - -def colorbox(x,y,xright,bottom): - glColor3f(0.75, 0.75, 0.75) - glRecti(x + 1, y + 1, xright - 1, bottom - 1) - -def dxf_callback(input_filename): - global dxfFileName - if input_filename.lower()[-3:] in ('dwg','dxf'): - dxfFileName.val=input_filename -# dirname == sys.dirname(Blender.Get('filename')) -# update_RegistryKey('DirName', dirname) -# update_RegistryKey('dxfFileName', input_filename) - -def ini_callback(input_filename): - global iniFileName - iniFileName.val=input_filename - -def event(evt, val): - if evt in (Draw.QKEY, Draw.ESCKEY) and not val: - Draw.Exit() - -def bevent(evt): -# global EVENT_NONE,EVENT_LOAD_DXF,EVENT_LOAD_INI,EVENT_SAVE_INI,EVENT_EXIT - global config_UI, user_preset - global GUI_A, UI_MODE - - ######### Manages GUI events - if (evt==EVENT_EXIT): - Draw.Exit() - print 'DXF/DWG-Importer *** exit ***' #--------------------- - elif (evt==EVENT_CHOOSE_INI): - Window.FileSelector(ini_callback, "INI-file Selection", '*.ini') - elif (evt==EVENT_REDRAW): - Draw.Redraw() - elif (evt==EVENT_RESET): - resetDefaultConfig() - Draw.Redraw() - elif (evt==EVENT_PRESET2D): - resetDefaultConfig_2D() - Draw.Redraw() - elif (evt==EVENT_SCALE): - if g_scale_as.val == 12: - inputGlobalScale() - if GUI_A['g_scale'].val < 0.00000001: - GUI_A['g_scale'].val = 0.00000001 - Draw.Redraw() - elif (evt==EVENT_ORIGIN): - inputOriginVector() - Draw.Redraw() - elif (evt==EVENT_PRESET3D): - resetDefaultConfig_3D() - Draw.Redraw() - elif (evt==EVENT_PRESETCURV): - presetConfig_curv(GUI_A['curves_on'].val) - Draw.Redraw() - elif (evt==EVENT_PRESETS): - user_preset += 1 - index = str(user_preset) - if user_preset > 5: user_preset = 0; index = '' - iniFileName.val = INIFILE_DEFAULT_NAME + index + INIFILE_EXTENSION - Draw.Redraw() - elif (evt==EVENT_LIST): - dxfFile = dxfFileName.val - update_RegistryKey('dxfFileName', dxfFileName.val) - if dxfFile.lower().endswith('.dxf') and sys.exists(dxfFile): - analyzeDXF(dxfFile) - else: - Draw.PupMenu('DXF importer: Alert!%t|no valid DXF-file selected!') - print "DXF importer: error, no valid DXF-file selected! try again" - Draw.Redraw() - elif (evt==EVENT_HELP): - try: - import webbrowser - webbrowser.open('http://wiki.blender.org/index.php?title=Scripts/Manual/Import/DXF-3D') - except: - Draw.PupMenu('DXF importer: HELP Alert!%t|no connection to manual-page on Blender-Wiki! try:|\ -http://wiki.blender.org/index.php?title=Scripts/Manual/Import/DXF-3D') - Draw.Redraw() - elif (evt==EVENT_LOAD_INI): - loadConfig() - Draw.Redraw() - elif (evt==EVENT_SAVE_INI): - saveConfig() - Draw.Redraw() - elif (evt==EVENT_DXF_DIR): - dxfFile = dxfFileName.val - dxfFileExt = '*'+dxfFile.lower()[-4:] #can be .dxf or .dwg - dxfPathName = '' - if '/' in dxfFile: - dxfPathName = '/'.join(dxfFile.split('/')[:-1]) + '/' - elif '\\' in dxfFile: - dxfPathName = '\\'.join(dxfFile.split('\\')[:-1]) + '\\' - dxfFileName.val = dxfPathName + dxfFileExt -# dirname == sys.dirname(Blender.Get('filename')) -# update_RegistryKey('DirName', dirname) -# update_RegistryKey('dxfFileName', dxfFileName.val) - GUI_A['newScene_on'].val = 1 - Draw.Redraw() - elif (evt==EVENT_CHOOSE_DXF): - filename = '' # '*.dxf' - if dxfFileName.val: filename = dxfFileName.val - Window.FileSelector(dxf_callback, "DXF/DWG-file Selection", filename) - elif (evt==EVENT_START): - dxfFile = dxfFileName.val - #print 'deb: dxfFile file: ', dxfFile #---------------------- - if E_M: dxfFileName.val, dxfFile = e_mode(dxfFile) #evaluation mode - update_RegistryKey('dxfFileName', dxfFileName.val) - if dxfFile.lower().endswith('*.dxf'): - if Draw.PupMenu('DXF importer will import all DXF-files from:|%s|OK?' % dxfFile) != -1: - UI_MODE = False - multi_import(dxfFile) - UI_MODE = True - Draw.Redraw() - - elif dxfFile.lower().endswith('*.dwg'): - if not extCONV_OK: Draw.PupMenu(extCONV_TEXT) - elif Draw.PupMenu('DWG importer will import all DWG-files from:|%s|OK?' % dxfFile) != -1: - #elif Draw.PupMenu('DWG importer will import all DWG-files from:|%s|Caution! overwrites existing DXF-files!| OK?' % dxfFile) != -1: - UI_MODE = False - multi_import(dxfFile) - UI_MODE = True - Draw.Redraw() - - elif sys.exists(dxfFile) and dxfFile.lower()[-4:] in ('.dxf','.dwg'): - if dxfFile.lower().endswith('.dwg') and (not extCONV_OK): - Draw.PupMenu(extCONV_TEXT) - else: - #print '\nStandard Mode: active' - if GUI_A['newScene_on'].val: - _dxf_file = dxfFile.split('/')[-1].split('\\')[-1] - _dxf_file = _dxf_file[:-4] # cut last char:'.dxf' - _dxf_file = _dxf_file[:MAX_NAMELENGTH] #? [-MAX_NAMELENGTH:]) - global SCENE - SCENE = Blender.Scene.New(_dxf_file) - SCENE.makeCurrent() - Blender.Redraw() - #or so? Blender.Scene.makeCurrent(_dxf_file) - #sce = bpy.data.scenes.new(_dxf_file) - #bpy.data.scenes.active = sce - else: - SCENE = Blender.Scene.GetCurrent() - SCENE.objects.selected = [] # deselect all - main(dxfFile) - #SCENE.objects.selected = SCENE.objects - #Window.RedrawAll() - #Blender.Redraw() - #Draw.Redraw() - else: - Draw.PupMenu('DXF importer: nothing imported!%t|no valid DXF-file selected!') - print "DXF importer: nothing imported, no valid DXF-file selected! try again" - Draw.Redraw() - - - - -def multi_import(DIR): - """Imports all DXF-files from directory DIR. - - """ - global SCENE - batchTIME = sys.time() - #if #DIR == "": DIR = os.path.curdir - if DIR == "": - DIR = sys.dirname(Blender.Get('filename')) - EXT = '.dxf' - else: - EXT = DIR[-4:] # get last 4 characters '.dxf' - DIR = DIR[:-5] # cut last 5 characters '*.dxf' - print 'importing multiple %s files from %s' %(EXT,DIR) - files = \ - [sys.join(DIR, f) for f in os.listdir(DIR) if f.lower().endswith(EXT)] - if not files: - print '...None %s-files found. Abort!' %EXT - return - - i = 0 - for dxfFile in files: - i += 1 - print '\n%s-file' %EXT, i, 'of', len(files) #,'\nImporting', dxfFile - if GUI_A['newScene_on'].val: - _dxf_file = dxfFile.split('/')[-1].split('\\')[-1] - _dxf_file = _dxf_file[:-4] # cut last char:'.dxf' - _dxf_file = _dxf_file[:MAX_NAMELENGTH] #? [-MAX_NAMELENGTH:]) - SCENE = Blender.Scene.New(_dxf_file) - SCENE.makeCurrent() - #or so? Blender.Scene.makeCurrent(_dxf_file) - #sce = bpy.data.scenes.new(_dxf_file) - #bpy.data.scenes.active = sce - else: - SCENE = Blender.Scene.GetCurrent() - SCENE.objects.selected = [] # deselect all - main(dxfFile) - #Blender.Redraw() - - print 'TOTAL TIME: %.6f' % (sys.time() - batchTIME) - print '\a\r', # beep when done - Draw.PupMenu('DXF importer: Done!|finished in %.4f sec.' % (sys.time() - batchTIME)) - - -if __name__ == "__main__": - #Draw.PupMenu('DXF importer: Abort%t|This script version works for Blender up 2.49 only!') - UI_MODE = True - # recall last used DXF-file and INI-file names - dxffilename = check_RegistryKey('dxfFileName') - #print 'deb:start dxffilename:', dxffilename #---------------- - if dxffilename: dxfFileName.val = dxffilename - else: - dirname = sys.dirname(Blender.Get('filename')) - #print 'deb:start dirname:', dirname #---------------- - dxfFileName.val = sys.join(dirname, '') - inifilename = check_RegistryKey('iniFileName') - if inifilename: iniFileName.val = inifilename - - Draw.Register(draw_UI, event, bevent) - - -""" -if 1: - # DEBUG ONLY - UI_MODE = False - TIME= sys.time() - #DIR = '/dxf_r12_testfiles/' - DIR = '/metavr/' - import os - print 'Searching for files' - os.system('find %s -iname "*.dxf" > /tmp/tempdxf_list' % DIR) - # os.system('find /storage/ -iname "*.dxf" > /tmp/tempdxf_list') - print '...Done' - file= open('/tmp/tempdxf_list', 'r') - lines= file.readlines() - file.close() - # sort by filesize for faster testing - lines_size = [(os.path.getsize(f[:-1]), f[:-1]) for f in lines] - lines_size.sort() - lines = [f[1] for f in lines_size] - - for i, _dxf in enumerate(lines): - if i >= 70: - #if 1: - print 'Importing', _dxf, '\nNUMBER', i, 'of', len(lines) - if True: - _dxf_file= _dxf.split('/')[-1].split('\\')[-1] - _dxf_file = _dxf_file[:-4] # cut last char:'.dxf' - _dxf_file = _dxf_file[:MAX_NAMELENGTH] #? [-MAX_NAMELENGTH:]) - sce = bpy.data.scenes.new(_dxf_file) - bpy.data.scenes.active = sce - dxfFileName.val = _dxf - main(_dxf) - - print 'TOTAL TIME: %.6f' % (sys.time() - TIME) -"""
\ No newline at end of file diff --git a/release/scripts/import_edl.py b/release/scripts/import_edl.py deleted file mode 100644 index 8c5d041b34c..00000000000 --- a/release/scripts/import_edl.py +++ /dev/null @@ -1,961 +0,0 @@ -#!BPY - -""" -Name: 'Video Sequence (.edl)...' -Blender: 248 -Group: 'Import' -Tooltip: 'Load a CMX formatted EDL into the sequencer' -""" - -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Copyright (C) 2009: Campbell Barton, ideasman42@gmail.com -# -# 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, -# -------------------------------------------------------------------------- - -class TimeCode(object): - ''' - Simple timecode class - also supports conversion from other time strings used by EDL - ''' - def __init__(self, data, fps): - self.fps= fps - if type(data)==str: - self.fromString(data) - frame = self.asFrame() - self.fromFrame(frame) - else: - self.fromFrame(data) - - def fromString(self, text): - # hh:mm:ss:ff - # No dropframe support yet - - if text.lower().endswith('mps'): # 5.2mps - return self.fromFrame( int( float(text[:-3]) * self.fps ) ) - elif text.lower().endswith('s'): # 5.2s - return self.fromFrame( int( float(text[:-1]) * self.fps ) ) - elif text.isdigit(): # 1234 - return self.fromFrame( int(text) ) - elif ':' in text: # hh:mm:ss:ff - text= text.replace(';', ':').replace(',', ':').replace('.', ':') - text= text.split(':') - - self.hours= int(text[0]) - self.minutes= int(text[1]) - self.seconds= int(text[2]) - self.frame= int(text[3]) - return self - else: - print 'ERROR: could not convert this into timecode "%s"' % test - return self - - - def fromFrame(self, frame): - - if frame < 0: - frame = -frame; - neg=True - else: - neg=False - - fpm = 60 * self.fps - fph = 60 * fpm - - if frame < fph: - self.hours= 0 - else: - self.hours= int(frame/fph) - frame = frame % fph - - if frame < fpm: - self.minutes= 0 - else: - self.minutes= int(frame/fpm) - frame = frame % fpm - - if frame < self.fps: - self.seconds= 0 - else: - self.seconds= int(frame/self.fps) - frame = frame % self.fps - - self.frame= frame - - if neg: - self.frame = -self.frame - self.seconds = -self.seconds - self.minutes = -self.minutes - self.hours = -self.hours - - return self - - def asFrame(self): - abs_frame= self.frame - abs_frame += self.seconds * self.fps - abs_frame += self.minutes * 60 * self.fps - abs_frame += self.hours * 60 * 60 * self.fps - - return abs_frame - - def asString(self): - self.fromFrame(int(self)) - return '%.2d:%.2d:%.2d:%.2d' % (self.hours, self.minutes, self.seconds, self.frame) - - def __repr__(self): - return self.asString() - - # Numeric stuff, may as well have this - def __neg__(self): return TimeCode(-int(self), self.fps) - def __int__(self): return self.asFrame() - def __sub__(self, other): return TimeCode(int(self)-int(other), self.fps) - def __add__(self, other): return TimeCode(int(self)+int(other), self.fps) - def __mul__(self, other): return TimeCode(int(self)*int(other), self.fps) - def __div__(self, other): return TimeCode(int(self)/int(other), self.fps) - def __abs__(self): return TimeCode(abs(int(self)), self.fps) - def __iadd__(self, other): return self.fromFrame(int(self)+int(other)) - def __imul__(self, other): return self.fromFrame(int(self)*int(other)) - def __idiv__(self, other): return self.fromFrame(int(self)/int(other)) -# end timecode - - -'''Comments -Comments can appear at the beginning of the EDL file (header) or between the edit lines in the EDL. The first block of comments in the file is defined to be the header comments and they are associated with the EDL as a whole. Subsequent comments in the EDL file are associated with the first edit line that appears after them. -Edit Entries -<filename|tag> <EditMode> <TransitionType>[num] [duration] [srcIn] [srcOut] [recIn] [recOut] - - * <filename|tag>: Filename or tag value. Filename can be for an MPEG file, Image file, or Image file template. Image file templates use the same pattern matching as for command line glob, and can be used to specify images to encode into MPEG. i.e. /usr/data/images/image*.jpg - * <EditMode>: 'V' | 'A' | 'VA' | 'B' | 'v' | 'a' | 'va' | 'b' which equals Video, Audio, Video_Audio edits (note B or b can be used in place of VA or va). - * <TransitonType>: 'C' | 'D' | 'E' | 'FI' | 'FO' | 'W' | 'c' | 'd' | 'e' | 'fi' | 'fo' | 'w'. which equals Cut, Dissolve, Effect, FadeIn, FadeOut, Wipe. - * [num]: if TransitionType = Wipe, then a wipe number must be given. At the moment only wipe 'W0' and 'W1' are supported. - * [duration]: if the TransitionType is not equal to Cut, then an effect duration must be given. Duration is in frames. - * [srcIn]: Src in. If no srcIn is given, then it defaults to the first frame of the video or the first frame in the image pattern. If srcIn isn't specified, then srcOut, recIn, recOut can't be specified. - * [srcOut]: Src out. If no srcOut is given, then it defaults to the last frame of the video - or last image in the image pattern. if srcOut isn't given, then recIn and recOut can't be specified. - * [recIn]: Rec in. If no recIn is given, then it is calculated based on its position in the EDL and the length of its input. - [recOut]: Rec out. If no recOut is given, then it is calculated based on its position in the EDL and the length of its input. first frame of the video. - -For srcIn, srcOut, recIn, recOut, the values can be specified as either timecode, frame number, seconds, or mps seconds. i.e. -[tcode | fnum | sec | mps], where: - - * tcode : SMPTE timecode in hh:mm:ss:ff - * fnum : frame number (the first decodable frame in the video is taken to be frame 0). - * sec : seconds with 's' suffix (e.g. 5.2s) - * mps : seconds with 'mps' suffix (e.g. 5.2mps). This corresponds to the 'seconds' value displayed by Windows MediaPlayer. - -More notes, -Key - -''' - -enum= 0 -TRANSITION_UNKNOWN= enum -TRANSITION_CUT= enum; enum+=1 -TRANSITION_DISSOLVE= enum; enum+=1 -TRANSITION_EFFECT= enum; enum+=1 -TRANSITION_FADEIN= enum; enum+=1 -TRANSITION_FADEOUT= enum; enum+=1 -TRANSITION_WIPE= enum; enum+=1 -TRANSITION_KEY= enum; enum+=1 - -TRANSITION_DICT={ \ - 'c':TRANSITION_CUT, - 'd':TRANSITION_DISSOLVE, - 'e':TRANSITION_EFFECT, - 'fi':TRANSITION_FADEIN, - 'fo':TRANSITION_FADEOUT, - 'w':TRANSITION_WIPE, - 'k':TRANSITION_KEY, - } - -enum= 0 -EDIT_UNKNOWN= 1<<enum; enum+=1 -EDIT_VIDEO= 1<<enum; enum+=1 -EDIT_AUDIO= 1<<enum; enum+=1 -EDIT_AUDIO_STEREO= 1<<enum; enum+=1 -EDIT_VIDEO_AUDIO= 1<<enum; enum+=1 - -EDIT_DICT= { \ - 'v':EDIT_VIDEO, - 'a':EDIT_AUDIO, - 'aa':EDIT_AUDIO_STEREO, - 'va':EDIT_VIDEO_AUDIO, - 'b':EDIT_VIDEO_AUDIO - } - - -enum= 0 -WIPE_UNKNOWN= enum -WIPE_0= enum; enum+=1 -WIPE_1= enum; enum+=1 - -enum= 0 -KEY_UNKNOWN= enum -KEY_BG= enum; enum+=1 # K B -KEY_IN= enum; enum+=1 # This is assumed if no second type is set -KEY_OUT= enum; enum+=1 # K O - - -''' -Most sytems: -Non-dropframe: 1:00:00:00 - colon in last position -Dropframe: 1:00:00;00 - semicolon in last position -PAL/SECAM: 1:00:00:00 - colon in last position - -SONY: -Non-dropframe: 1:00:00.00 - period in last position -Dropframe: 1:00:00,00 - comma in last position -PAL/SECAM: 1:00:00.00 - period in last position -''' - -''' -t = abs(timecode('-124:-12:-43:-22', 25)) -t /= 2 -print t -''' - -def editFlagsToText(flag): - items = [] - for item, val in EDIT_DICT.items(): - if val & flag: - items.append(item) - return '/'.join(items) - - -class EditDecision(object): - def __init__(self, text= None, fps= 25): - # print text - self.number = -1 - self.reel = '' # Uniqie name for this 'file' but not filename, when BL signifies black - self.transition_duration= 0 - self.edit_type= EDIT_UNKNOWN - self.transition_type= TRANSITION_UNKNOWN - self.wipe_type = WIPE_UNKNOWN - self.key_type = KEY_UNKNOWN - self.key_fade = -1 # true/false - self.srcIn = None # Where on the original field recording the event begins - self.srcOut = None # Where on the original field recording the event ends - self.recIn = None # Beginning of the original event in the edited program - self.recOut = None # End of the original event in the edited program - self.m2 = None # fps set by the m2 command - self.filename = '' - - self.custom_data= [] # use for storing any data you want (blender strip for eg) - - if text != None: - self.read(text, fps) - - def __repr__(self): - txt= 'num: %d, ' % self.number - txt += 'reel: %s, ' % self.reel - txt += 'edit_type: ' - txt += editFlagsToText(self.edit_type) + ', ' - - txt += 'trans_type: ' - for item, val in TRANSITION_DICT.items(): - if val == self.transition_type: - txt += item + ', ' - break - - - txt += 'm2: ' - if self.m2: - txt += '%g' % float(self.m2.fps) - txt += '\n\t' - txt += self.m2.data - else: - txt += 'nil' - - txt += ', ' - txt += 'recIn: ' + str(self.recIn) + ', ' - txt += 'recOut: ' + str(self.recOut) + ', ' - txt += 'srcIn: ' + str(self.srcIn) + ', ' - txt += 'srcOut: ' + str(self.srcOut) + ', ' - - return txt - - - def read(self, line, fps): - line= line.split() - index= 0 - self.number= int(line[index]); index+=1 - self.reel= line[index].lower(); index+=1 - - # AA/V can be an edit type - self.edit_type= 0 - for edit_type in line[index].lower().split('/'): - self.edit_type |= EDIT_DICT[edit_type]; - index+=1 - - tx_name = ''.join([c for c in line[index].lower() if not c.isdigit()]) - self.transition_type= TRANSITION_DICT[tx_name]; # advance the index later - - if self.transition_type== TRANSITION_WIPE: - tx_num = ''.join([c for c in line[index].lower() if c.isdigit()]) - if tx_num: tx_num = int(tx_num) - else: tx_num = 0 - - self.wipe_type= tx_num - - elif self.transition_type== TRANSITION_KEY: # UNTESTED - - val= line[index+1].lower() - - if val == 'b': - self.key_type= KEY_BG - index+=1 - elif val == 'o': - self.key_type= KEY_OUT - index+=1 - else: - self.key_type= KEY_IN # if no args given - - # there may be an (F) after, eg 'K B (F)' - # in the docs this should only be after K B but who knows, it may be after K O also? - val= line[index+1].lower() - if val == '(f)': - index+=1 - self.key_fade = True - else: - self.key_fade = False - - index+=1 - - if self.transition_type in (TRANSITION_DISSOLVE, TRANSITION_EFFECT, TRANSITION_FADEIN, TRANSITION_FADEOUT, TRANSITION_WIPE): - self.transition_duration= TimeCode(line[index], fps); index+=1 - - if index < len(line): - self.srcIn= TimeCode(line[index], fps); index+=1 - if index < len(line): - self.srcOut= TimeCode(line[index], fps); index+=1 - - if index < len(line): - self.recIn= TimeCode(line[index], fps); index+=1 - if index < len(line): - self.recOut= TimeCode(line[index], fps); index+=1 - - def renumber(self): - self.edits.sort( key=lambda e: int(e.recIn) ) - for i, edit in enumerate(self.edits): - edit.number= i - - def clean(self): - ''' - Clean up double ups - ''' - self.renumber() - - # TODO - def asName(self): - cut_type = 'nil' - for k,v in TRANSITION_DICT.iteritems(): - if v==self.transition_type: - cut_type = k - break - - return '%d_%s_%s' % (self.number, self.reel, cut_type) - -class M2(object): - def __init__(self): - self.reel = None - self.fps = None - self.time = None - self.data = None - - self.index = -1 - self.tot = -1 - - def read(self, line, fps): - - # M2 TAPEC 050.5 00:08:11:08 - words = line.split() - - self.reel= words[1].lower() - self.fps= float(words[2]) - self.time= TimeCode(words[3], fps) - - self.data = line - -class EditList(object): - def __init__(self): - self.edits= [] - self.title= '' - - def parse(self, filename, fps): - try: - file= open(filename, 'rU') - except: - return False - - self.edits= [] - edits_m2 = [] # edits with m2's - - has_m2 = False - - for line in file: - line= ' '.join(line.split()) - - if not line or line.startswith('*') or line.startswith('#'): - continue - elif line.startswith('TITLE:'): - self.title= ' '.join(line.split()[1:]) - elif line.split()[0].lower() == 'm2': - has_m2 = True - m2 = M2() - m2.read(line, fps) - edits_m2.append( m2 ) - elif not line.split()[0].isdigit(): - print 'Ignoring:', line - else: - self.edits.append( EditDecision(line, fps) ) - edits_m2.append( self.edits[-1] ) - - if has_m2: - # Group indexes - i = 0 - for item in edits_m2: - if isinstance(item, M2): - item.index = i - i += 1 - else: - # not an m2 - i = 0 - - # Set total group indexes - for item in reversed(edits_m2): - if isinstance(item, M2): - if tot_m2 == -1: - tot_m2 = item.index + 1 - - item.tot = tot_m2 - else: - # not an m2 - tot_m2 = -1 - - - for i, item in enumerate(edits_m2): - if isinstance(item, M2): - # make a list of all items that match the m2's reel name - edits_m2_tmp = [item_tmp for item_tmp in edits_m2 if (isinstance(item, M2) or item_tmp.reel == item.reel)] - - # get the new index - i_tmp = edits_m2_tmp.index(item) - - # Seek back to get the edit. - edit = edits_m2[i_tmp-item.tot] - - # Note, docs say time should also match with edit start time - # but from final cut pro, this seems not to be the case - if not isinstance(edit, EditDecision): - print "ERROR!", 'M2 incorrect' - else: - edit.m2 = item - - - return True - - def testOverlap(self, edit_test): - recIn= int(edit_test.recIn) - recOut= int(edit_test.recOut) - - for edit in self.edits: - if edit is edit_test: - break - - recIn_other= int(edit.recIn) - recOut_other= int(edit.recOut) - - if recIn_other < recIn < recOut_other: - return True - if recIn_other < recOut < recOut_other: - return True - - if recIn < recIn_other < recOut: - return True - if recIn < recOut_other < recOut: - return True - - return False - - def getReels(self): - reels = {} - for edit in self.edits: - reels.setdefault(edit.reel, []).append(edit) - - return reels - - - -# from DNA -SEQ_IMAGE= 0 -SEQ_META= 1 -SEQ_SCENE= 2 -SEQ_MOVIE= 3 -SEQ_RAM_SOUND= 4 -SEQ_HD_SOUND= 5 -SEQ_MOVIE_AND_HD_SOUND= 6 - -SEQ_EFFECT= 8 -SEQ_CROSS= 8 -SEQ_ADD= 9 -SEQ_SUB= 10 -SEQ_ALPHAOVER= 11 -SEQ_ALPHAUNDER= 12 -SEQ_GAMCROSS= 13 -SEQ_MUL= 14 -SEQ_OVERDROP= 15 -SEQ_PLUGIN= 24 -SEQ_WIPE= 25 -SEQ_GLOW= 26 -SEQ_TRANSFORM= 27 -SEQ_COLOR= 28 -SEQ_SPEED= 29 - -# Blender spesific stuff starts here -import bpy -import Blender - -def scale_meta_speed(seq, mov, scale): - # Add an effect - speed= seq.new((SEQ_SPEED, mov,), 199, mov.channel+1) - speed.speedEffectFrameBlending = True - meta= seq.new([mov, speed], 199, mov.channel) - - if scale >= 1.0: - mov.endStill = int(mov.length * (scale - 1.0)) - else: - speed.speedEffectGlobalSpeed = 1.0/scale - meta.endOffset = mov.length - int(mov.length*scale) - - speed.update() - meta.update() - return meta - -def apply_dissolve_ipo(mov, blendin): - len_disp = float(mov.endDisp - mov.startDisp) - - if len_disp <= 0.0: - print 'Error, strip is zero length' - return - - mov.ipo= ipo= bpy.data.ipos.new("fade", "Sequence") - icu= ipo.addCurve('Fac') - - icu.interpolation= Blender.IpoCurve.InterpTypes.LINEAR - icu.append((0, 0)) - icu.append(((int(blendin)/len_disp) * 100, 1)) - - if mov.type not in (SEQ_HD_SOUND, SEQ_RAM_SOUND): - mov.blendMode = Blender.Scene.Sequence.BlendModes.ALPHAOVER - - -def replace_ext(path, ext): - return path[:path.rfind('.')+1] + ext - -def load_edl(filename, reel_files, reel_offsets): - ''' - reel_files - key:reel <--> reel:filename - ''' - - # For test file - # frame_offset = -769 - - - sce= bpy.data.scenes.active - fps= sce.render.fps - - elist= EditList() - if not elist.parse(filename, fps): - return 'Unable to parse "%s"' % filename - # elist.clean() - - - seq= sce.sequence - - track= 0 - - edits = elist.edits[:] - # edits.sort(key = lambda edit: int(edit.recIn)) - - prev_edit = None - for edit in edits: - print edit - frame_offset = reel_offsets[edit.reel] - - - src_start= int(edit.srcIn) + frame_offset - src_end= int(edit.srcOut) + frame_offset - src_length= src_end-src_start - - rec_start= int(edit.recIn) + 1 - rec_end= int(edit.recOut) + 1 - rec_length= rec_end-rec_start - - # print src_length, rec_length, src_start - - if edit.m2 != None: scale = fps/float(edit.m2.fps) - else: scale = 1.0 - - unedited_start= rec_start - src_start - offset_start = src_start - int(src_start*scale) # works for scaling up AND down - - if edit.transition_type == TRANSITION_CUT and (not elist.testOverlap(edit)): - track = 1 - - strip= None - final_strips = [] - if edit.reel.lower()=='bw': - strip= seq.new((0,0,0), rec_start, track+1) - strip.length= rec_length # for color its simple - final_strips.append(strip) - else: - - path_full = reel_files[edit.reel] - path_fileonly= path_full.split('/')[-1].split('\\')[-1] # os.path.basename(full) - path_dironly= path_full[:-len(path_fileonly)] # os.path.dirname(full) - - if edit.edit_type & EDIT_VIDEO: #and edit.transition_type == TRANSITION_CUT: - - try: - strip= seq.new((path_fileonly, path_dironly, path_full, 'movie'), unedited_start + offset_start, track+1) - except: - return 'Invalid input for movie' - - # Apply scaled rec in bounds - if scale != 1.0: - meta = scale_meta_speed(seq, strip, scale) - final_strip = meta - else: - final_strip = strip - - - final_strip.update() - final_strip.startOffset= rec_start - final_strip.startDisp - final_strip.endOffset= rec_end- final_strip.endDisp - final_strip.update() - final_strip.endOffset += (final_strip.endDisp - rec_end) - final_strip.update() - - - if edit.transition_duration: - if not prev_edit: - print "Error no previous strip" - else: - new_end = rec_start + int(edit.transition_duration) - for other in prev_edit.custom_data: - if other.type != SEQ_HD_SOUND and other.type != SEQ_RAM_SOUND: - other.endOffset += (other.endDisp - new_end) - other.update() - - # Apply disolve - if edit.transition_type == TRANSITION_DISSOLVE: - apply_dissolve_ipo(final_strip, edit.transition_duration) - - if edit.transition_type == TRANSITION_WIPE: - other_track = track + 2 - for other in prev_edit.custom_data: - if other.type != SEQ_HD_SOUND and other.type != SEQ_RAM_SOUND: - - strip_wipe= seq.new((SEQ_WIPE, other, final_strip), 1, other_track) - - if edit.wipe_type == WIPE_0: - strip_wipe.wipeEffectAngle = 90 - else: - strip_wipe.wipeEffectAngle = -90 - - other_track += 1 - - - - # strip.endOffset= strip.length - int(edit.srcOut) - #end_offset= (unedited_start+strip.length) - end - # print start, end, end_offset - #strip.endOffset = end_offset - - # break - # print strip - - final_strips.append(final_strip) - - - if edit.edit_type & (EDIT_AUDIO | EDIT_AUDIO_STEREO | EDIT_VIDEO_AUDIO): - - if scale == 1.0: # TODO - scaled audio - - try: - strip= seq.new((path_fileonly, path_dironly, path_full, 'audio_hd'), unedited_start + offset_start, track+6) - except: - - # See if there is a wave file there - path_full_wav = replace_ext(path_full, 'wav') - path_fileonly_wav = replace_ext(path_fileonly, 'wav') - - #try: - strip= seq.new((path_fileonly_wav, path_dironly, path_full_wav, 'audio_hd'), unedited_start + offset_start, track+6) - #except: - # return 'Invalid input for audio' - - final_strip = strip - - # Copied from above - final_strip.update() - final_strip.startOffset= rec_start - final_strip.startDisp - final_strip.endOffset= rec_end- final_strip.endDisp - final_strip.update() - final_strip.endOffset += (final_strip.endDisp - rec_end) - final_strip.update() - - if edit.transition_type == TRANSITION_DISSOLVE: - apply_dissolve_ipo(final_strip, edit.transition_duration) - - final_strips.append(final_strip) - - # strip= seq.new((0.6, 0.6, 0.6), start, track+1) - - if final_strips: - for strip in final_strips: - # strip.length= length - final_strip.name = edit.asName() - edit.custom_data[:]= final_strips - # track = not track - prev_edit = edit - track += 1 - - #break - - - def recursive_update(s): - s.update(1) - for s_kid in s: - recursive_update(s_kid) - - - for s in seq: - recursive_update(s) - - return '' - - - -#load_edl('/fe/edl/EP30CMXtrk1.edl') # /tmp/test.edl -#load_edl('/fe/edl/EP30CMXtrk2.edl') # /tmp/test.edl -#load_edl('/fe/edl/EP30CMXtrk3.edl') # /tmp/test.edl -#load_edl('/root/vid/rush/blender_edl.edl', ['/root/vid/rush/rushes3.avi',]) # /tmp/test.edl - - - - -# ---------------------- Blender UI part -from Blender import Draw, Window -import BPyWindow - -if 0: - DEFAULT_FILE_EDL = '/root/vid/rush/blender_edl.edl' - DEFAULT_FILE_MEDIA = '/root/vid/rush/rushes3_wav.avi' - DEFAULT_FRAME_OFFSET = -769 -else: - DEFAULT_FILE_EDL = '' - DEFAULT_FILE_MEDIA = '' - DEFAULT_FRAME_OFFSET = 0 - -B_EVENT_IMPORT = 1 -B_EVENT_RELOAD = 2 -B_EVENT_FILESEL_EDL = 3 -B_EVENT_NOP = 4 - -B_EVENT_FILESEL = 100 # or greater - -class ReelItemUI(object): - __slots__ = 'filename_but', 'offset_but', 'ui_text' - def __init__(self): - self.filename_but = Draw.Create(DEFAULT_FILE_MEDIA) - self.offset_but = Draw.Create(DEFAULT_FRAME_OFFSET) - self.ui_text = '' - - - -REEL_UI = {} # reel:ui_string - - -#REEL_FILENAMES = {} # reel:filename -#REEL_OFFSETS = {} # reel:filename - -PREF = {} - -PREF['filename'] = Draw.Create(DEFAULT_FILE_EDL) -PREF['reel_act'] = '' - -def edl_reload(): - Window.WaitCursor(1) - filename = PREF['filename'].val - sce= bpy.data.scenes.active - fps= sce.render.fps - - elist= EditList() - - if filename: - if not elist.parse(filename, fps): - Draw.PupMenu('Error%t|Could not open the file "' + filename + '"') - reels = elist.getReels() - else: - reels = {} - - REEL_UI.clear() - for reel_key, edits in reels.iteritems(): - - if reel_key == 'bw': - continue - - flag = 0 - for edit in edits: - flag |= edit.edit_type - - reel_item = REEL_UI[reel_key] = ReelItemUI() - - reel_item.ui_text = '%s (%s): ' % (reel_key, editFlagsToText(flag)) - - Window.WaitCursor(0) - -def edl_set_path(filename): - PREF['filename'].val = filename - edl_reload() - Draw.Redraw() - -def edl_set_path_reel(filename): - REEL_UI[PREF['reel_act']].filename_but.val = filename - Draw.Redraw() - -def edl_reel_keys(): - reel_keys = REEL_UI.keys() - - if 'bw' in reel_keys: - reel_keys.remove('bw') - - reel_keys.sort() - return reel_keys - -def edl_draw(): - - MARGIN = 4 - rect = BPyWindow.spaceRect() - but_width = int((rect[2]-MARGIN*2)/4.0) # 72 - # Clamp - if but_width>100: but_width = 100 - but_height = 17 - - x=MARGIN - y=rect[3]-but_height-MARGIN - xtmp = x - - - - # ---------- ---------- ---------- ---------- - Blender.Draw.BeginAlign() - PREF['filename'] = Draw.String('edl path: ', B_EVENT_RELOAD, xtmp, y, (but_width*3)-20, but_height, PREF['filename'].val, 256, 'EDL Path'); xtmp += (but_width*3)-20; - Draw.PushButton('..', B_EVENT_FILESEL_EDL, xtmp, y, 20, but_height, 'Select an EDL file'); xtmp += 20; - Blender.Draw.EndAlign() - - Draw.PushButton('Reload', B_EVENT_RELOAD, xtmp + MARGIN, y, but_width - MARGIN, but_height, 'Read the ID Property settings from the active curve object'); xtmp += but_width; - y-=but_height + MARGIN - xtmp = x - # ---------- ---------- ---------- ---------- - - reel_keys = edl_reel_keys() - - - - if reel_keys: text = 'Reel file list...' - elif PREF['filename'].val == '': text = 'No EDL loaded.' - else: text = 'No reels found!' - - Draw.Label(text, xtmp + MARGIN, y, but_width*4, but_height); xtmp += but_width*4; - - y-=but_height + MARGIN - xtmp = x - - # ---------- ---------- ---------- ---------- - - - for i, reel_key in enumerate(reel_keys): - reel_item = REEL_UI[reel_key] - - Blender.Draw.BeginAlign() - REEL_UI[reel_key].filename_but = Draw.String(reel_item.ui_text, B_EVENT_NOP, xtmp, y, (but_width*3)-20, but_height, REEL_UI[reel_key].filename_but.val, 256, 'Select the reel path'); xtmp += (but_width*3)-20; - Draw.PushButton('..', B_EVENT_FILESEL + i, xtmp, y, 20, but_height, 'Media path to use for this reel'); xtmp += 20; - Blender.Draw.EndAlign() - - reel_item.offset_but= Draw.Number('ofs:', B_EVENT_NOP, xtmp + MARGIN, y, but_width - MARGIN, but_height, reel_item.offset_but.val, -100000, 100000, 'Start offset in frames when applying timecode'); xtmp += but_width - MARGIN; - - y-=but_height + MARGIN - xtmp = x - - # ---------- ---------- ---------- ---------- - - Draw.PushButton('Import CMX-EDL Sequencer Strips', B_EVENT_IMPORT, xtmp + MARGIN, MARGIN, but_width*4 - MARGIN, but_height, 'Load the EDL file into the sequencer'); xtmp += but_width*4; - y-=but_height + MARGIN - xtmp = x - - -def edl_event(evt, val): - pass - -def edl_bevent(evt): - - if evt == B_EVENT_NOP: - pass - elif evt == B_EVENT_IMPORT: - ''' - Load the file into blender with UI settings - ''' - filename = PREF['filename'].val - - reel_files = {} - reel_offsets = {} - - for reel_key, reel_item in REEL_UI.iteritems(): - reel_files[reel_key] = reel_item.filename_but.val - reel_offsets[reel_key] = reel_item.offset_but.val - - error = load_edl(filename, reel_files, reel_offsets) - if error != '': - Draw.PupMenu('Error%t|' + error) - else: - Window.RedrawAll() - - elif evt == B_EVENT_RELOAD: - edl_reload() - Draw.Redraw() - - elif evt == B_EVENT_FILESEL_EDL: - filename = PREF['filename'].val - if not filename: filename = Blender.sys.join(Blender.sys.expandpath('//'), '*.edl') - - Window.FileSelector(edl_set_path, 'Select EDL', filename) - - elif evt >= B_EVENT_FILESEL: - reel_keys = edl_reel_keys() - reel_key = reel_keys[evt - B_EVENT_FILESEL] - - filename = REEL_UI[reel_key].filename_but.val - if not filename: filename = Blender.sys.expandpath('//') - - PREF['reel_act'] = reel_key # so file set path knows which one to set - Window.FileSelector(edl_set_path_reel, 'Reel Media', filename) - - - -if __name__ == '__main__': - Draw.Register(edl_draw, edl_event, edl_bevent) - edl_reload() - diff --git a/release/scripts/import_lightwave_motion.py b/release/scripts/import_lightwave_motion.py deleted file mode 100644 index 20c87dfd5c6..00000000000 --- a/release/scripts/import_lightwave_motion.py +++ /dev/null @@ -1,244 +0,0 @@ -#!BPY - -""" Registration info for Blender menus: <- these words are ignored -Name: 'Lightwave Motion (.mot)...' -Blender: 245 -Group: 'Import' -Tip: 'Import Loc Rot Size chanels from a Lightwave .mot file' -""" - -__author__ = "Daniel Salazar (ZanQdo)" -__url__ = ("blender", "blenderartists.org", -"e-mail: zanqdo@gmail.com") -__version__ = "16/04/08" - -__bpydoc__ = """\ -This script loads Lightwave motion files (.mot) -into the selected objects - -Usage: -Run the script with one or more objects selected (any kind) -Be sure to set the framerate correctly - -""" - -# $Id$ -# -------------------------------------------------------------------------- -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Copyright (C) 2003, 2004: A Vanpoucke -# -# 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 ***** -# -------------------------------------------------------------------------- - -import math as M -import Blender as B -import bpy - - -def FuncionPrincipal (Dir): - B.Window.WaitCursor(1) - ObjSelect = B.Object.GetSelected() - - if not ObjSelect: - B.Draw.PupMenu('Select one or more objects, aborting.') - return - - - SC = B.Scene.GetCurrent() - SCR = SC.getRenderingContext() - FrameRate = float(SCR.framesPerSec()) - - - # Creating new IPO - - IPO = B.Ipo.New('Object', 'LW_Motion') - - - # Creating Curves in the IPO - - LocX = IPO.addCurve("LocX") - LocX.setInterpolation("Bezier") - - LocY = IPO.addCurve("LocY") - LocX.setInterpolation("Bezier") - - LocZ = IPO.addCurve("LocZ") - LocX.setInterpolation("Bezier") - - RotX = IPO.addCurve("RotX") - LocX.setInterpolation("Bezier") - - RotY = IPO.addCurve("RotY") - LocX.setInterpolation("Bezier") - - RotZ = IPO.addCurve("RotZ") - LocX.setInterpolation("Bezier") - - ScaleX = IPO.addCurve("ScaleX") - LocX.setInterpolation("Bezier") - - ScaleY = IPO.addCurve("ScaleY") - LocX.setInterpolation("Bezier") - - ScaleZ = IPO.addCurve("ScaleZ") - LocX.setInterpolation("Bezier") - - - # Opening the mot file - - File = open (Dir, 'rU') - - - # Init flags - - CurChannel = -1 - ScaleFlag = 0 - - # Main file reading cycle - - for Line in File: - - ''' - # Number of channels in the file - - if "NumChannels" in Line: - Line = Line.split (' ') - NumChannels = int(Line[1]) - ''' - - # Current Channel Flag - - if "Channel 0" in Line: - CurChannel = 0 - - elif "Channel 1" in Line: - CurChannel = 1 - - elif "Channel 2" in Line: - CurChannel = 2 - - elif "Channel 3" in Line: - CurChannel = 3 - - elif "Channel 4" in Line: - CurChannel = 4 - - elif "Channel 5" in Line: - CurChannel = 5 - - elif "Channel 6" in Line: - CurChannel = 6 - - elif "Channel 7" in Line: - CurChannel = 7 - - elif "Channel 8" in Line: - CurChannel = 8 - - - # Getting the data and writing to IPOs - - if CurChannel == 0: - if "Key" in Line: - Line = Line.split (' ') - ValCh_0 = float (Line [3]) - TimeCh_0 = float (Line [4]) * FrameRate - LocX.addBezier ((TimeCh_0, ValCh_0)) - - if CurChannel == 1: - if "Key" in Line: - Line = Line.split (' ') - ValCh_1 = float (Line [3]) - TimeCh_1 = float (Line [4]) * FrameRate - LocZ.addBezier ((TimeCh_1, ValCh_1)) - - if CurChannel == 2: - if "Key" in Line: - Line = Line.split (' ') - ValCh_2 = float (Line [3]) - TimeCh_2 = float (Line [4]) * FrameRate - LocY.addBezier ((TimeCh_2, ValCh_2)) - - if CurChannel == 3: - if "Key" in Line: - Line = Line.split (' ') - ValCh_3 = M.degrees ( - float (Line [3]) ) / 10 - TimeCh_3 = float (Line [4]) * FrameRate - RotZ.addBezier ((TimeCh_3, ValCh_3)) - - if CurChannel == 4: - if "Key" in Line: - Line = Line.split (' ') - ValCh_4 = M.degrees ( - float (Line [3]) ) / 10 - TimeCh_4 = float (Line [4]) * FrameRate - RotX.addBezier ((TimeCh_4, ValCh_4)) - - if CurChannel == 5: - if "Key" in Line: - Line = Line.split (' ') - ValCh_5 = M.degrees ( - float (Line [3]) ) / 10 - TimeCh_5 = float (Line [4]) * FrameRate - RotY.addBezier ((TimeCh_5, ValCh_5)) - - if CurChannel == 6: - if "Key" in Line: - Line = Line.split (' ') - ValCh_6 = float (Line [3]) - TimeCh_6 = float (Line [4]) * FrameRate - ScaleX.addBezier ((TimeCh_6, ValCh_6)) - elif ScaleFlag < 3: - ScaleFlag += 1 - ScaleX.addBezier ((0, 1)) - - if CurChannel == 7: - if "Key" in Line: - Line = Line.split (' ') - ValCh_7 = float (Line [3]) - TimeCh_7 = float (Line [4]) * FrameRate - ScaleZ.addBezier ((TimeCh_7, ValCh_7)) - elif ScaleFlag < 3: - ScaleFlag += 1 - ScaleZ.addBezier ((0, 1)) - - if CurChannel == 8: - if "Key" in Line: - Line = Line.split (' ') - ValCh_8 = float (Line [3]) - TimeCh_8 = float (Line [4]) * FrameRate - ScaleY.addBezier ((TimeCh_8, ValCh_8)) - elif ScaleFlag < 3: - ScaleFlag += 1 - ScaleY.addBezier ((0, 1)) - - - # Link the IPO to all selected objects - - for ob in ObjSelect: - ob.setIpo(IPO) - - File.close() - - print '\nDone, the following motion file has been loaded:\n\n%s' % Dir - B.Window.WaitCursor(0) - -def main(): - B.Window.FileSelector(FuncionPrincipal, "Load IPO from .mot File", B.sys.makename(ext='.mot')) - -if __name__=='__main__': - main() - diff --git a/release/scripts/import_mdd.py b/release/scripts/import_mdd.py deleted file mode 100644 index 1ee196ab67f..00000000000 --- a/release/scripts/import_mdd.py +++ /dev/null @@ -1,158 +0,0 @@ -#!BPY - -""" - Name: 'Load MDD to Mesh RVKs' - Blender: 242 - Group: 'Import' - Tooltip: 'baked vertex animation to active mesh object.' -""" -__author__ = "Bill L.Nieuwendorp" -__bpydoc__ = """\ -This script Imports Lightwaves MotionDesigner format. - -The .mdd format has become quite a popular Pipeline format<br> -for moving animations from package to package. -""" -# mdd importer -# -# Warning if the vertex order or vertex count differs from the -# origonal model the mdd was Baked out from their will be Strange -# behavior -# -# -#vertex animation to ShapeKeys with ipo and gives the frame a value of 1.0 -#A modifier to read mdd files would be Ideal but thats for another day :) -# -#Please send any fixes,updates,bugs to Slow67_at_Gmail.com -#Bill Niewuendorp - -# ***** 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 ***** - - - - -try: - from struct import unpack -except: - unpack = None - -import Blender -from Blender import Mesh, Object, Scene -import BPyMessages - -def mdd_import(filepath, ob, PREF_IPONAME, PREF_START_FRAME, PREF_JUMP): - - print '\n\nimporting mdd "%s"' % filepath - - Blender.Window.DrawProgressBar (0.0, "Importing mdd ...") - Blender.Window.EditMode(0) - Blender.Window.WaitCursor(1) - - file = open(filepath, 'rb') - frames, points = unpack(">2i", file.read(8)) - time = unpack((">%df" % frames), file.read(frames * 4)) - - print '\tpoints:%d frames:%d' % (points,frames) - - scn = Scene.GetCurrent() - ctx = scn.getRenderingContext() - Blender.Set("curframe", PREF_START_FRAME) - me = ob.getData(mesh=1) - - def UpdateMesh(me,fr): - for v in me.verts: - # 12 is the size of 3 floats - x,y,z= unpack('>3f', file.read(12)) - v.co[:] = x,z,y - me.update() - - Blender.Window.DrawProgressBar (0.4, "4 Importing mdd ...") - - - curfr = ctx.currentFrame() - print'\twriting mdd data...' - for i in xrange(frames): - Blender.Set("curframe", i+PREF_START_FRAME) - if len(me.verts) > 1 and (curfr >= PREF_START_FRAME) and (curfr <= PREF_START_FRAME+frames): - UpdateMesh(me, i) - ob.insertShapeKey() - - Blender.Window.DrawProgressBar (0.5, "5 Importing mdd ...") - - key= me.key - - # Add the key of its not there - if not key: - me.insertKey(1, 'relative') - key= me.key - - key.ipo = Blender.Ipo.New('Key', PREF_IPONAME) - ipo = key.ipo - # block = key.getBlocks() # not used. - all_keys = ipo.curveConsts - - for i in xrange(PREF_JUMP+1, len(all_keys), PREF_JUMP): - curve = ipo.getCurve(i) - if curve == None: - curve = ipo.addCurve(all_keys[i]) - - curve.append((PREF_START_FRAME+i-1,1)) - curve.append((PREF_START_FRAME+i- PREF_JUMP -1,0)) - curve.append((PREF_START_FRAME+i+ PREF_JUMP-1,0)) - curve.setInterpolation('Linear') - curve.recalc() - - print 'done' - Blender.Window.WaitCursor(0) - Blender.Window.DrawProgressBar (1.0, '') - - -def mdd_import_ui(filepath): - - if BPyMessages.Error_NoFile(filepath): - return - - scn= Scene.GetCurrent() - ob_act= scn.objects.active - - if ob_act == None or ob_act.type != 'Mesh': - BPyMessages.Error_NoMeshActive() - return - - PREF_IPONAME = Blender.Draw.Create(filepath.split('/')[-1].split('\\')[-1].split('.')[0]) - PREF_START_FRAME = Blender.Draw.Create(1) - PREF_JUMP = Blender.Draw.Create(1) - - block = [\ - ("Ipo Name: ", PREF_IPONAME, 0, 30, "Ipo name for the new shape key"),\ - ("Start Frame: ", PREF_START_FRAME, 1, 3000, "Start frame for the animation"),\ - ("Key Skip: ", PREF_JUMP, 1, 100, "KeyReduction, Skip every Nth Frame")\ - ] - - if not Blender.Draw.PupBlock("Import MDD", block): - return - orig_frame = Blender.Get('curframe') - mdd_import(filepath, ob_act, PREF_IPONAME.val, PREF_START_FRAME.val, PREF_JUMP.val) - Blender.Set('curframe', orig_frame) - -if __name__ == '__main__': - if not unpack: - Draw.PupMenu('Error%t|This script requires a full python install') - - Blender.Window.FileSelector(mdd_import_ui, 'IMPORT MDD', '*.mdd') diff --git a/release/scripts/import_obj.py b/release/scripts/import_obj.py deleted file mode 100644 index 81230bfcf03..00000000000 --- a/release/scripts/import_obj.py +++ /dev/null @@ -1,1234 +0,0 @@ -#!BPY - -""" -Name: 'Wavefront (.obj)...' -Blender: 249 -Group: 'Import' -Tooltip: 'Load a Wavefront OBJ File, Shift: batch import all dir.' -""" - -__author__= "Campbell Barton", "Jiri Hnidek", "Paolo Ciccone" -__url__= ['http://wiki.blender.org/index.php/Scripts/Manual/Import/wavefront_obj', 'blender.org', 'blenderartists.org'] -__version__= "2.13" - -__bpydoc__= """\ -This script imports a Wavefront OBJ files to Blender. - -Usage: -Run this script from "File->Import" menu and then load the desired OBJ file. -Note, This loads mesh objects and materials only, nurbs and curves are not supported. -""" - -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Script copyright (C) Campbell J Barton 2007-2009 -# - V2.12- bspline import/export added (funded by PolyDimensions GmbH) -# -# 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 ***** -# -------------------------------------------------------------------------- - -from Blender import Mesh, Draw, Window, Texture, Material, sys -import bpy -import BPyMesh -import BPyImage -import BPyMessages - -try: import os -except: os= False - -# Generic path functions -def stripFile(path): - '''Return directory, where the file is''' - lastSlash= max(path.rfind('\\'), path.rfind('/')) - if lastSlash != -1: - path= path[:lastSlash] - return '%s%s' % (path, sys.sep) - -def stripPath(path): - '''Strips the slashes from the back of a string''' - return path.split('/')[-1].split('\\')[-1] - -def stripExt(name): # name is a string - '''Strips the prefix off the name before writing''' - index= name.rfind('.') - if index != -1: - return name[ : index ] - else: - return name -# end path funcs - - - -def line_value(line_split): - ''' - Returns 1 string represneting the value for this line - None will be returned if theres only 1 word - ''' - length= len(line_split) - if length == 1: - return None - - elif length == 2: - return line_split[1] - - elif length > 2: - return ' '.join( line_split[1:] ) - -def obj_image_load(imagepath, DIR, IMAGE_SEARCH): - ''' - Mainly uses comprehensiveImageLoad - but tries to replace '_' with ' ' for Max's exporter replaces spaces with underscores. - ''' - - if '_' in imagepath: - image= BPyImage.comprehensiveImageLoad(imagepath, DIR, PLACE_HOLDER= False, RECURSIVE= IMAGE_SEARCH) - if image: return image - # Did the exporter rename the image? - image= BPyImage.comprehensiveImageLoad(imagepath.replace('_', ' '), DIR, PLACE_HOLDER= False, RECURSIVE= IMAGE_SEARCH) - if image: return image - - # Return an image, placeholder if it dosnt exist - image= BPyImage.comprehensiveImageLoad(imagepath, DIR, PLACE_HOLDER= True, RECURSIVE= IMAGE_SEARCH) - return image - - -def create_materials(filepath, material_libs, unique_materials, unique_material_images, IMAGE_SEARCH): - ''' - Create all the used materials in this obj, - assign colors and images to the materials from all referenced material libs - ''' - DIR= stripFile(filepath) - - #==================================================================================# - # This function sets textures defined in .mtl file # - #==================================================================================# - def load_material_image(blender_material, context_material_name, imagepath, type): - - texture= bpy.data.textures.new(type) - texture.setType('Image') - - # Absolute path - c:\.. etc would work here - image= obj_image_load(imagepath, DIR, IMAGE_SEARCH) - has_data = image.has_data - texture.image = image - - if not has_data: - try: - # first time using this image. We need to load it first - image.glLoad() - except: - # probably the image is crashed - pass - else: - has_data = image.has_data - - # Adds textures for materials (rendering) - if type == 'Kd': - if has_data and image.depth == 32: - # Image has alpha - blender_material.setTexture(0, texture, Texture.TexCo.UV, Texture.MapTo.COL | Texture.MapTo.ALPHA) - texture.setImageFlags('MipMap', 'InterPol', 'UseAlpha') - blender_material.mode |= Material.Modes.ZTRANSP - blender_material.alpha = 0.0 - else: - blender_material.setTexture(0, texture, Texture.TexCo.UV, Texture.MapTo.COL) - - # adds textures to faces (Textured/Alt-Z mode) - # Only apply the diffuse texture to the face if the image has not been set with the inline usemat func. - unique_material_images[context_material_name]= image, has_data # set the texface image - - elif type == 'Ka': - blender_material.setTexture(1, texture, Texture.TexCo.UV, Texture.MapTo.CMIR) # TODO- Add AMB to BPY API - - elif type == 'Ks': - blender_material.setTexture(2, texture, Texture.TexCo.UV, Texture.MapTo.SPEC) - - elif type == 'Bump': - blender_material.setTexture(3, texture, Texture.TexCo.UV, Texture.MapTo.NOR) - elif type == 'D': - blender_material.setTexture(4, texture, Texture.TexCo.UV, Texture.MapTo.ALPHA) - blender_material.mode |= Material.Modes.ZTRANSP - blender_material.alpha = 0.0 - # Todo, unset deffuse material alpha if it has an alpha channel - - elif type == 'refl': - blender_material.setTexture(5, texture, Texture.TexCo.UV, Texture.MapTo.REF) - - - # Add an MTL with the same name as the obj if no MTLs are spesified. - temp_mtl= stripExt(stripPath(filepath))+ '.mtl' - - if sys.exists(DIR + temp_mtl) and temp_mtl not in material_libs: - material_libs.append( temp_mtl ) - del temp_mtl - - #Create new materials - for name in unique_materials: # .keys() - if name != None: - unique_materials[name]= bpy.data.materials.new(name) - unique_material_images[name]= None, False # assign None to all material images to start with, add to later. - - unique_materials[None]= None - unique_material_images[None]= None, False - - for libname in material_libs: - mtlpath= DIR + libname - if not sys.exists(mtlpath): - #print '\tError Missing MTL: "%s"' % mtlpath - pass - else: - #print '\t\tloading mtl: "%s"' % mtlpath - context_material= None - mtl= open(mtlpath, 'rU') - for line in mtl: #.xreadlines(): - if line.startswith('newmtl'): - context_material_name= line_value(line.split()) - if unique_materials.has_key(context_material_name): - context_material = unique_materials[ context_material_name ] - else: - context_material = None - - elif context_material: - # we need to make a material to assign properties to it. - line_split= line.split() - line_lower= line.lower().lstrip() - if line_lower.startswith('ka'): - context_material.setMirCol((float(line_split[1]), float(line_split[2]), float(line_split[3]))) - elif line_lower.startswith('kd'): - context_material.setRGBCol((float(line_split[1]), float(line_split[2]), float(line_split[3]))) - elif line_lower.startswith('ks'): - context_material.setSpecCol((float(line_split[1]), float(line_split[2]), float(line_split[3]))) - elif line_lower.startswith('ns'): - context_material.setHardness( int((float(line_split[1])*0.51)) ) - elif line_lower.startswith('ni'): # Refraction index - context_material.setIOR( max(1, min(float(line_split[1]), 3))) # Between 1 and 3 - elif line_lower.startswith('d') or line_lower.startswith('tr'): - context_material.setAlpha(float(line_split[1])) - context_material.mode |= Material.Modes.ZTRANSP - elif line_lower.startswith('map_ka'): - img_filepath= line_value(line.split()) - if img_filepath: - load_material_image(context_material, context_material_name, img_filepath, 'Ka') - elif line_lower.startswith('map_ks'): - img_filepath= line_value(line.split()) - if img_filepath: - load_material_image(context_material, context_material_name, img_filepath, 'Ks') - elif line_lower.startswith('map_kd'): - img_filepath= line_value(line.split()) - if img_filepath: - load_material_image(context_material, context_material_name, img_filepath, 'Kd') - elif line_lower.startswith('map_bump'): - img_filepath= line_value(line.split()) - if img_filepath: - load_material_image(context_material, context_material_name, img_filepath, 'Bump') - elif line_lower.startswith('map_d') or line_lower.startswith('map_tr'): # Alpha map - Dissolve - img_filepath= line_value(line.split()) - if img_filepath: - load_material_image(context_material, context_material_name, img_filepath, 'D') - - elif line_lower.startswith('refl'): # Reflectionmap - img_filepath= line_value(line.split()) - if img_filepath: - load_material_image(context_material, context_material_name, img_filepath, 'refl') - mtl.close() - - - - -def split_mesh(verts_loc, faces, unique_materials, filepath, SPLIT_OB_OR_GROUP, SPLIT_MATERIALS): - ''' - Takes vert_loc and faces, and seperates into multiple sets of - (verts_loc, faces, unique_materials, dataname) - This is done so objects do not overload the 16 material limit. - ''' - - filename = stripExt(stripPath(filepath)) - - if not SPLIT_OB_OR_GROUP and not SPLIT_MATERIALS: - # use the filename for the object name since we arnt chopping up the mesh. - return [(verts_loc, faces, unique_materials, filename)] - - - def key_to_name(key): - # if the key is a tuple, join it to make a string - if type(key) == tuple: - return '%s_%s' % key - elif not key: - return filename # assume its a string. make sure this is true if the splitting code is changed - else: - return key - - # Return a key that makes the faces unique. - if SPLIT_OB_OR_GROUP and not SPLIT_MATERIALS: - def face_key(face): - return face[4] # object - - elif not SPLIT_OB_OR_GROUP and SPLIT_MATERIALS: - def face_key(face): - return face[2] # material - - else: # Both - def face_key(face): - return face[4], face[2] # object,material - - - face_split_dict= {} - - oldkey= -1 # initialize to a value that will never match the key - - for face in faces: - - key= face_key(face) - - if oldkey != key: - # Check the key has changed. - try: - verts_split, faces_split, unique_materials_split, vert_remap= face_split_dict[key] - except KeyError: - faces_split= [] - verts_split= [] - unique_materials_split= {} - vert_remap= [-1]*len(verts_loc) - - face_split_dict[key]= (verts_split, faces_split, unique_materials_split, vert_remap) - - oldkey= key - - face_vert_loc_indicies= face[0] - - # Remap verts to new vert list and add where needed - for enum, i in enumerate(face_vert_loc_indicies): - if vert_remap[i] == -1: - new_index= len(verts_split) - vert_remap[i]= new_index # set the new remapped index so we only add once and can reference next time. - face_vert_loc_indicies[enum] = new_index # remap to the local index - verts_split.append( verts_loc[i] ) # add the vert to the local verts - - else: - face_vert_loc_indicies[enum] = vert_remap[i] # remap to the local index - - matname= face[2] - if matname and not unique_materials_split.has_key(matname): - unique_materials_split[matname] = unique_materials[matname] - - faces_split.append(face) - - - # remove one of the itemas and reorder - return [(value[0], value[1], value[2], key_to_name(key)) for key, value in face_split_dict.iteritems()] - - -def create_mesh(scn, new_objects, has_ngons, CREATE_FGONS, CREATE_EDGES, verts_loc, verts_tex, faces, unique_materials, unique_material_images, unique_smooth_groups, vertex_groups, dataname): - ''' - Takes all the data gathered and generates a mesh, adding the new object to new_objects - deals with fgons, sharp edges and assigning materials - ''' - if not has_ngons: - CREATE_FGONS= False - - if unique_smooth_groups: - sharp_edges= {} - smooth_group_users= dict([ (context_smooth_group, {}) for context_smooth_group in unique_smooth_groups.iterkeys() ]) - context_smooth_group_old= -1 - - # Split fgons into tri's - fgon_edges= {} # Used for storing fgon keys - if CREATE_EDGES: - edges= [] - - context_object= None - - # reverse loop through face indicies - for f_idx in xrange(len(faces)-1, -1, -1): - - face_vert_loc_indicies,\ - face_vert_tex_indicies,\ - context_material,\ - context_smooth_group,\ - context_object= faces[f_idx] - - len_face_vert_loc_indicies = len(face_vert_loc_indicies) - - if len_face_vert_loc_indicies==1: - faces.pop(f_idx)# cant add single vert faces - - elif not face_vert_tex_indicies or len_face_vert_loc_indicies == 2: # faces that have no texture coords are lines - if CREATE_EDGES: - # generators are better in python 2.4+ but can't be used in 2.3 - # edges.extend( (face_vert_loc_indicies[i], face_vert_loc_indicies[i+1]) for i in xrange(len_face_vert_loc_indicies-1) ) - edges.extend( [(face_vert_loc_indicies[i], face_vert_loc_indicies[i+1]) for i in xrange(len_face_vert_loc_indicies-1)] ) - - faces.pop(f_idx) - else: - - # Smooth Group - if unique_smooth_groups and context_smooth_group: - # Is a part of of a smooth group and is a face - if context_smooth_group_old is not context_smooth_group: - edge_dict= smooth_group_users[context_smooth_group] - context_smooth_group_old= context_smooth_group - - for i in xrange(len_face_vert_loc_indicies): - i1= face_vert_loc_indicies[i] - i2= face_vert_loc_indicies[i-1] - if i1>i2: i1,i2= i2,i1 - - try: - edge_dict[i1,i2]+= 1 - except KeyError: - edge_dict[i1,i2]= 1 - - # FGons into triangles - if has_ngons and len_face_vert_loc_indicies > 4: - - ngon_face_indices= BPyMesh.ngon(verts_loc, face_vert_loc_indicies) - faces.extend(\ - [(\ - [face_vert_loc_indicies[ngon[0]], face_vert_loc_indicies[ngon[1]], face_vert_loc_indicies[ngon[2]] ],\ - [face_vert_tex_indicies[ngon[0]], face_vert_tex_indicies[ngon[1]], face_vert_tex_indicies[ngon[2]] ],\ - context_material,\ - context_smooth_group,\ - context_object)\ - for ngon in ngon_face_indices]\ - ) - - # edges to make fgons - if CREATE_FGONS: - edge_users= {} - for ngon in ngon_face_indices: - for i in (0,1,2): - i1= face_vert_loc_indicies[ngon[i ]] - i2= face_vert_loc_indicies[ngon[i-1]] - if i1>i2: i1,i2= i2,i1 - - try: - edge_users[i1,i2]+=1 - except KeyError: - edge_users[i1,i2]= 1 - - for key, users in edge_users.iteritems(): - if users>1: - fgon_edges[key]= None - - # remove all after 3, means we dont have to pop this one. - faces.pop(f_idx) - - - # Build sharp edges - if unique_smooth_groups: - for edge_dict in smooth_group_users.itervalues(): - for key, users in edge_dict.iteritems(): - if users==1: # This edge is on the boundry of a group - sharp_edges[key]= None - - - # map the material names to an index - material_mapping= dict([(name, i) for i, name in enumerate(unique_materials)]) # enumerate over unique_materials keys() - - materials= [None] * len(unique_materials) - - for name, index in material_mapping.iteritems(): - materials[index]= unique_materials[name] - - me= bpy.data.meshes.new(dataname) - - me.materials= materials[0:16] # make sure the list isnt too big. - #me.verts.extend([(0,0,0)]) # dummy vert - me.verts.extend(verts_loc) - - face_mapping= me.faces.extend([f[0] for f in faces], indexList=True) - - if verts_tex and me.faces: - me.faceUV= 1 - # TEXMODE= Mesh.FaceModes['TEX'] - - context_material_old= -1 # avoid a dict lookup - mat= 0 # rare case it may be un-initialized. - me_faces= me.faces - ALPHA= Mesh.FaceTranspModes.ALPHA - - for i, face in enumerate(faces): - if len(face[0]) < 2: - pass #raise "bad face" - elif len(face[0])==2: - if CREATE_EDGES: - edges.append(face[0]) - else: - face_index_map= face_mapping[i] - if face_index_map!=None: # None means the face wasnt added - blender_face= me_faces[face_index_map] - - face_vert_loc_indicies,\ - face_vert_tex_indicies,\ - context_material,\ - context_smooth_group,\ - context_object= face - - - - if context_smooth_group: - blender_face.smooth= True - - if context_material: - if context_material_old is not context_material: - mat= material_mapping[context_material] - if mat>15: - mat= 15 - context_material_old= context_material - - blender_face.mat= mat - - - if verts_tex: - if context_material: - image, has_data= unique_material_images[context_material] - if image: # Can be none if the material dosnt have an image. - blender_face.image= image - if has_data and image.depth == 32: - blender_face.transp |= ALPHA - - # BUG - Evil eekadoodle problem where faces that have vert index 0 location at 3 or 4 are shuffled. - if len(face_vert_loc_indicies)==4: - if face_vert_loc_indicies[2]==0 or face_vert_loc_indicies[3]==0: - face_vert_tex_indicies= face_vert_tex_indicies[2], face_vert_tex_indicies[3], face_vert_tex_indicies[0], face_vert_tex_indicies[1] - else: # length of 3 - if face_vert_loc_indicies[2]==0: - face_vert_tex_indicies= face_vert_tex_indicies[1], face_vert_tex_indicies[2], face_vert_tex_indicies[0] - # END EEEKADOODLE FIX - - # assign material, uv's and image - for ii, uv in enumerate(blender_face.uv): - uv.x, uv.y= verts_tex[face_vert_tex_indicies[ii]] - del me_faces - del ALPHA - - # Add edge faces. - me_edges= me.edges - if CREATE_FGONS and fgon_edges: - FGON= Mesh.EdgeFlags.FGON - for ed in me.findEdges( fgon_edges.keys() ): - if ed!=None: - me_edges[ed].flag |= FGON - del FGON - - if unique_smooth_groups and sharp_edges: - SHARP= Mesh.EdgeFlags.SHARP - for ed in me.findEdges( sharp_edges.keys() ): - if ed!=None: - me_edges[ed].flag |= SHARP - del SHARP - - if CREATE_EDGES: - me_edges.extend( edges ) - - del me_edges - - me.calcNormals() - - ob= scn.objects.new(me) - new_objects.append(ob) - - # Create the vertex groups. No need to have the flag passed here since we test for the - # content of the vertex_groups. If the user selects to NOT have vertex groups saved then - # the following test will never run - for group_name, group_indicies in vertex_groups.iteritems(): - me.addVertGroup(group_name) - me.assignVertsToGroup(group_name, group_indicies,1.00, Mesh.AssignModes.REPLACE) - - -def create_nurbs(scn, context_nurbs, vert_loc, new_objects): - ''' - Add nurbs object to blender, only support one type at the moment - ''' - deg = context_nurbs.get('deg', (3,)) - curv_range = context_nurbs.get('curv_range', None) - curv_idx = context_nurbs.get('curv_idx', []) - parm_u = context_nurbs.get('parm_u', []) - parm_v = context_nurbs.get('parm_v', []) - name = context_nurbs.get('name', 'ObjNurb') - cstype = context_nurbs.get('cstype', None) - - if cstype == None: - print '\tWarning, cstype not found' - return - if cstype != 'bspline': - print '\tWarning, cstype is not supported (only bspline)' - return - if not curv_idx: - print '\tWarning, curv argument empty or not set' - return - if len(deg) > 1 or parm_v: - print '\tWarning, surfaces not supported' - return - - cu = bpy.data.curves.new(name, 'Curve') - cu.flag |= 1 # 3D curve - - nu = None - for pt in curv_idx: - - pt = vert_loc[pt] - pt = (pt[0], pt[1], pt[2], 1.0) - - if nu == None: - nu = cu.appendNurb(pt) - else: - nu.append(pt) - - nu.orderU = deg[0]+1 - - # get for endpoint flag from the weighting - if curv_range and len(parm_u) > deg[0]+1: - do_endpoints = True - for i in xrange(deg[0]+1): - - if abs(parm_u[i]-curv_range[0]) > 0.0001: - do_endpoints = False - break - - if abs(parm_u[-(i+1)]-curv_range[1]) > 0.0001: - do_endpoints = False - break - - else: - do_endpoints = False - - if do_endpoints: - nu.flagU |= 2 - - - # close - ''' - do_closed = False - if len(parm_u) > deg[0]+1: - for i in xrange(deg[0]+1): - #print curv_idx[i], curv_idx[-(i+1)] - - if curv_idx[i]==curv_idx[-(i+1)]: - do_closed = True - break - - if do_closed: - nu.flagU |= 1 - ''' - - ob = scn.objects.new(cu) - new_objects.append(ob) - - -def strip_slash(line_split): - if line_split[-1][-1]== '\\': - if len(line_split[-1])==1: - line_split.pop() # remove the \ item - else: - line_split[-1]= line_split[-1][:-1] # remove the \ from the end last number - return True - return False - - - -def get_float_func(filepath): - ''' - find the float function for this obj file - - weather to replace commas or not - ''' - file= open(filepath, 'rU') - for line in file: #.xreadlines(): - line = line.lstrip() - if line.startswith('v'): # vn vt v - if ',' in line: - return lambda f: float(f.replace(',', '.')) - elif '.' in line: - return float - - # incase all vert values were ints - return float - -def load_obj(filepath, - CLAMP_SIZE= 0.0, - CREATE_FGONS= True, - CREATE_SMOOTH_GROUPS= True, - CREATE_EDGES= True, - SPLIT_OBJECTS= True, - SPLIT_GROUPS= True, - SPLIT_MATERIALS= True, - ROTATE_X90= True, - IMAGE_SEARCH=True, - POLYGROUPS=False): - ''' - Called by the user interface or another script. - load_obj(path) - should give acceptable results. - This function passes the file and sends the data off - to be split into objects and then converted into mesh objects - ''' - print '\nimporting obj "%s"' % filepath - - if SPLIT_OBJECTS or SPLIT_GROUPS or SPLIT_MATERIALS: - POLYGROUPS = False - - time_main= sys.time() - - verts_loc= [] - verts_tex= [] - faces= [] # tuples of the faces - material_libs= [] # filanems to material libs this uses - vertex_groups = {} # when POLYGROUPS is true - - # Get the string to float conversion func for this file- is 'float' for almost all files. - float_func= get_float_func(filepath) - - # Context variables - context_material= None - context_smooth_group= None - context_object= None - context_vgroup = None - - # Nurbs - context_nurbs = {} - nurbs = [] - context_parm = '' # used by nurbs too but could be used elsewhere - - has_ngons= False - # has_smoothgroups= False - is explicit with len(unique_smooth_groups) being > 0 - - # Until we can use sets - unique_materials= {} - unique_material_images= {} - unique_smooth_groups= {} - # unique_obects= {} - no use for this variable since the objects are stored in the face. - - # when there are faces that end with \ - # it means they are multiline- - # since we use xreadline we cant skip to the next line - # so we need to know weather - context_multi_line= '' - - print '\tparsing obj file "%s"...' % filepath, - time_sub= sys.time() - - file= open(filepath, 'rU') - for line in file: #.xreadlines(): - line = line.lstrip() # rare cases there is white space at the start of the line - - if line.startswith('v '): - line_split= line.split() - # rotate X90: (x,-z,y) - verts_loc.append( (float_func(line_split[1]), -float_func(line_split[3]), float_func(line_split[2])) ) - - elif line.startswith('vn '): - pass - - elif line.startswith('vt '): - line_split= line.split() - verts_tex.append( (float_func(line_split[1]), float_func(line_split[2])) ) - - # Handel faces lines (as faces) and the second+ lines of fa multiline face here - # use 'f' not 'f ' because some objs (very rare have 'fo ' for faces) - elif line.startswith('f') or context_multi_line == 'f': - - if context_multi_line: - # use face_vert_loc_indicies and face_vert_tex_indicies previously defined and used the obj_face - line_split= line.split() - - else: - line_split= line[2:].split() - face_vert_loc_indicies= [] - face_vert_tex_indicies= [] - - # Instance a face - faces.append((\ - face_vert_loc_indicies,\ - face_vert_tex_indicies,\ - context_material,\ - context_smooth_group,\ - context_object\ - )) - - if strip_slash(line_split): - context_multi_line = 'f' - else: - context_multi_line = '' - - for v in line_split: - obj_vert= v.split('/') - - vert_loc_index= int(obj_vert[0])-1 - # Add the vertex to the current group - # *warning*, this wont work for files that have groups defined around verts - if POLYGROUPS and context_vgroup: - vertex_groups[context_vgroup].append(vert_loc_index) - - # Make relative negative vert indicies absolute - if vert_loc_index < 0: - vert_loc_index= len(verts_loc) + vert_loc_index + 1 - - face_vert_loc_indicies.append(vert_loc_index) - - if len(obj_vert)>1 and obj_vert[1]: - # formatting for faces with normals and textures us - # loc_index/tex_index/nor_index - - vert_tex_index= int(obj_vert[1])-1 - # Make relative negative vert indicies absolute - if vert_tex_index < 0: - vert_tex_index= len(verts_tex) + vert_tex_index + 1 - - face_vert_tex_indicies.append(vert_tex_index) - else: - # dummy - face_vert_tex_indicies.append(0) - - if len(face_vert_loc_indicies) > 4: - has_ngons= True - - elif CREATE_EDGES and (line.startswith('l ') or context_multi_line == 'l'): - # very similar to the face load function above with some parts removed - - if context_multi_line: - # use face_vert_loc_indicies and face_vert_tex_indicies previously defined and used the obj_face - line_split= line.split() - - else: - line_split= line[2:].split() - face_vert_loc_indicies= [] - face_vert_tex_indicies= [] - - # Instance a face - faces.append((\ - face_vert_loc_indicies,\ - face_vert_tex_indicies,\ - context_material,\ - context_smooth_group,\ - context_object\ - )) - - if strip_slash(line_split): - context_multi_line = 'l' - else: - context_multi_line = '' - - isline= line.startswith('l') - - for v in line_split: - vert_loc_index= int(v)-1 - - # Make relative negative vert indicies absolute - if vert_loc_index < 0: - vert_loc_index= len(verts_loc) + vert_loc_index + 1 - - face_vert_loc_indicies.append(vert_loc_index) - - elif line.startswith('s'): - if CREATE_SMOOTH_GROUPS: - context_smooth_group= line_value(line.split()) - if context_smooth_group=='off': - context_smooth_group= None - elif context_smooth_group: # is not None - unique_smooth_groups[context_smooth_group]= None - - elif line.startswith('o'): - if SPLIT_OBJECTS: - context_object= line_value(line.split()) - # unique_obects[context_object]= None - - elif line.startswith('g'): - if SPLIT_GROUPS: - context_object= line_value(line.split()) - # print 'context_object', context_object - # unique_obects[context_object]= None - elif POLYGROUPS: - context_vgroup = line_value(line.split()) - if context_vgroup and context_vgroup != '(null)': - vertex_groups.setdefault(context_vgroup, []) - else: - context_vgroup = None # dont assign a vgroup - - elif line.startswith('usemtl'): - context_material= line_value(line.split()) - unique_materials[context_material]= None - elif line.startswith('mtllib'): # usemap or usemat - material_libs.extend( line.split()[1:] ) # can have multiple mtllib filenames per line - - - # Nurbs support - elif line.startswith('cstype '): - context_nurbs['cstype']= line_value(line.split()) # 'rat bspline' / 'bspline' - elif line.startswith('curv ') or context_multi_line == 'curv': - line_split= line.split() - - curv_idx = context_nurbs['curv_idx'] = context_nurbs.get('curv_idx', []) # incase were multiline - - if not context_multi_line: - context_nurbs['curv_range'] = float_func(line_split[1]), float_func(line_split[2]) - line_split[0:3] = [] # remove first 3 items - - if strip_slash(line_split): - context_multi_line = 'curv' - else: - context_multi_line = '' - - - for i in line_split: - vert_loc_index = int(i)-1 - - if vert_loc_index < 0: - vert_loc_index= len(verts_loc) + vert_loc_index + 1 - - curv_idx.append(vert_loc_index) - - elif line.startswith('parm') or context_multi_line == 'parm': - line_split= line.split() - - if context_multi_line: - context_multi_line = '' - else: - context_parm = line_split[1] - line_split[0:2] = [] # remove first 2 - - if strip_slash(line_split): - context_multi_line = 'parm' - else: - context_multi_line = '' - - if context_parm.lower() == 'u': - context_nurbs.setdefault('parm_u', []).extend( [float_func(f) for f in line_split] ) - elif context_parm.lower() == 'v': # surfaces not suported yet - context_nurbs.setdefault('parm_v', []).extend( [float_func(f) for f in line_split] ) - # else: # may want to support other parm's ? - - elif line.startswith('deg '): - context_nurbs['deg']= [int(i) for i in line.split()[1:]] - elif line.startswith('end'): - # Add the nurbs curve - if context_object: - context_nurbs['name'] = context_object - nurbs.append(context_nurbs) - context_nurbs = {} - context_parm = '' - - ''' # How to use usemap? depricated? - elif line.startswith('usema'): # usemap or usemat - context_image= line_value(line.split()) - ''' - - file.close() - time_new= sys.time() - print '%.4f sec' % (time_new-time_sub) - time_sub= time_new - - - print '\tloading materials and images...', - create_materials(filepath, material_libs, unique_materials, unique_material_images, IMAGE_SEARCH) - - time_new= sys.time() - print '%.4f sec' % (time_new-time_sub) - time_sub= time_new - - if not ROTATE_X90: - verts_loc[:] = [(v[0], v[2], -v[1]) for v in verts_loc] - - # deselect all - scn = bpy.data.scenes.active - scn.objects.selected = [] - new_objects= [] # put new objects here - - print '\tbuilding geometry...\n\tverts:%i faces:%i materials: %i smoothgroups:%i ...' % ( len(verts_loc), len(faces), len(unique_materials), len(unique_smooth_groups) ), - # Split the mesh by objects/materials, may - if SPLIT_OBJECTS or SPLIT_GROUPS: SPLIT_OB_OR_GROUP = True - else: SPLIT_OB_OR_GROUP = False - - for verts_loc_split, faces_split, unique_materials_split, dataname in split_mesh(verts_loc, faces, unique_materials, filepath, SPLIT_OB_OR_GROUP, SPLIT_MATERIALS): - # Create meshes from the data, warning 'vertex_groups' wont support splitting - create_mesh(scn, new_objects, has_ngons, CREATE_FGONS, CREATE_EDGES, verts_loc_split, verts_tex, faces_split, unique_materials_split, unique_material_images, unique_smooth_groups, vertex_groups, dataname) - - # nurbs support - for context_nurbs in nurbs: - create_nurbs(scn, context_nurbs, verts_loc, new_objects) - - - axis_min= [ 1000000000]*3 - axis_max= [-1000000000]*3 - - if CLAMP_SIZE: - # Get all object bounds - for ob in new_objects: - for v in ob.getBoundBox(): - for axis, value in enumerate(v): - if axis_min[axis] > value: axis_min[axis]= value - if axis_max[axis] < value: axis_max[axis]= value - - # Scale objects - max_axis= max(axis_max[0]-axis_min[0], axis_max[1]-axis_min[1], axis_max[2]-axis_min[2]) - scale= 1.0 - - while CLAMP_SIZE < max_axis * scale: - scale= scale/10.0 - - for ob in new_objects: - ob.setSize(scale, scale, scale) - - # Better rotate the vert locations - #if not ROTATE_X90: - # for ob in new_objects: - # ob.RotX = -1.570796326794896558 - - time_new= sys.time() - - print '%.4f sec' % (time_new-time_sub) - print 'finished importing: "%s" in %.4f sec.' % (filepath, (time_new-time_main)) - - -DEBUG= True - - -def load_obj_ui(filepath, BATCH_LOAD= False): - if BPyMessages.Error_NoFile(filepath): - return - - global CREATE_SMOOTH_GROUPS, CREATE_FGONS, CREATE_EDGES, SPLIT_OBJECTS, SPLIT_GROUPS, SPLIT_MATERIALS, CLAMP_SIZE, IMAGE_SEARCH, POLYGROUPS, KEEP_VERT_ORDER, ROTATE_X90 - - CREATE_SMOOTH_GROUPS= Draw.Create(0) - CREATE_FGONS= Draw.Create(1) - CREATE_EDGES= Draw.Create(1) - SPLIT_OBJECTS= Draw.Create(0) - SPLIT_GROUPS= Draw.Create(0) - SPLIT_MATERIALS= Draw.Create(0) - CLAMP_SIZE= Draw.Create(10.0) - IMAGE_SEARCH= Draw.Create(1) - POLYGROUPS= Draw.Create(0) - KEEP_VERT_ORDER= Draw.Create(1) - ROTATE_X90= Draw.Create(1) - - - # Get USER Options - # Note, Works but not pretty, instead use a more complicated GUI - ''' - pup_block= [\ - 'Import...',\ - ('Smooth Groups', CREATE_SMOOTH_GROUPS, 'Surround smooth groups by sharp edges'),\ - ('Create FGons', CREATE_FGONS, 'Import faces with more then 4 verts as fgons.'),\ - ('Lines', CREATE_EDGES, 'Import lines and faces with 2 verts as edges'),\ - 'Separate objects from obj...',\ - ('Object', SPLIT_OBJECTS, 'Import OBJ Objects into Blender Objects'),\ - ('Group', SPLIT_GROUPS, 'Import OBJ Groups into Blender Objects'),\ - ('Material', SPLIT_MATERIALS, 'Import each material into a seperate mesh (Avoids > 16 per mesh error)'),\ - 'Options...',\ - ('Keep Vert Order', KEEP_VERT_ORDER, 'Keep vert and face order, disables some other options.'),\ - ('Clamp Scale:', CLAMP_SIZE, 0.0, 1000.0, 'Clamp the size to this maximum (Zero to Disable)'),\ - ('Image Search', IMAGE_SEARCH, 'Search subdirs for any assosiated images (Warning, may be slow)'),\ - ] - - if not Draw.PupBlock('Import OBJ...', pup_block): - return - - if KEEP_VERT_ORDER.val: - SPLIT_OBJECTS.val = False - SPLIT_GROUPS.val = False - SPLIT_MATERIALS.val = False - ''' - - - - # BEGIN ALTERNATIVE UI ******************* - if True: - - EVENT_NONE = 0 - EVENT_EXIT = 1 - EVENT_REDRAW = 2 - EVENT_IMPORT = 3 - - GLOBALS = {} - GLOBALS['EVENT'] = EVENT_REDRAW - #GLOBALS['MOUSE'] = Window.GetMouseCoords() - GLOBALS['MOUSE'] = [i/2 for i in Window.GetScreenSize()] - - def obj_ui_set_event(e,v): - GLOBALS['EVENT'] = e - - def do_split(e,v): - global SPLIT_OBJECTS, SPLIT_GROUPS, SPLIT_MATERIALS, KEEP_VERT_ORDER, POLYGROUPS - if SPLIT_OBJECTS.val or SPLIT_GROUPS.val or SPLIT_MATERIALS.val: - KEEP_VERT_ORDER.val = 0 - POLYGROUPS.val = 0 - else: - KEEP_VERT_ORDER.val = 1 - - def do_vertorder(e,v): - global SPLIT_OBJECTS, SPLIT_GROUPS, SPLIT_MATERIALS, KEEP_VERT_ORDER - if KEEP_VERT_ORDER.val: - SPLIT_OBJECTS.val = SPLIT_GROUPS.val = SPLIT_MATERIALS.val = 0 - else: - if not (SPLIT_OBJECTS.val or SPLIT_GROUPS.val or SPLIT_MATERIALS.val): - KEEP_VERT_ORDER.val = 1 - - def do_polygroups(e,v): - global SPLIT_OBJECTS, SPLIT_GROUPS, SPLIT_MATERIALS, KEEP_VERT_ORDER, POLYGROUPS - if POLYGROUPS.val: - SPLIT_OBJECTS.val = SPLIT_GROUPS.val = SPLIT_MATERIALS.val = 0 - - def do_help(e,v): - url = __url__[0] - print 'Trying to open web browser with documentation at this address...' - print '\t' + url - - try: - import webbrowser - webbrowser.open(url) - except: - print '...could not open a browser window.' - - def obj_ui(): - ui_x, ui_y = GLOBALS['MOUSE'] - - # Center based on overall pup size - ui_x -= 165 - ui_y -= 90 - - global CREATE_SMOOTH_GROUPS, CREATE_FGONS, CREATE_EDGES, SPLIT_OBJECTS, SPLIT_GROUPS, SPLIT_MATERIALS, CLAMP_SIZE, IMAGE_SEARCH, POLYGROUPS, KEEP_VERT_ORDER, ROTATE_X90 - - Draw.Label('Import...', ui_x+9, ui_y+159, 220, 21) - Draw.BeginAlign() - CREATE_SMOOTH_GROUPS = Draw.Toggle('Smooth Groups', EVENT_NONE, ui_x+9, ui_y+139, 110, 20, CREATE_SMOOTH_GROUPS.val, 'Surround smooth groups by sharp edges') - CREATE_FGONS = Draw.Toggle('NGons as FGons', EVENT_NONE, ui_x+119, ui_y+139, 110, 20, CREATE_FGONS.val, 'Import faces with more then 4 verts as fgons') - CREATE_EDGES = Draw.Toggle('Lines as Edges', EVENT_NONE, ui_x+229, ui_y+139, 110, 20, CREATE_EDGES.val, 'Import lines and faces with 2 verts as edges') - Draw.EndAlign() - - Draw.Label('Separate objects by OBJ...', ui_x+9, ui_y+110, 220, 20) - Draw.BeginAlign() - SPLIT_OBJECTS = Draw.Toggle('Object', EVENT_REDRAW, ui_x+9, ui_y+89, 55, 21, SPLIT_OBJECTS.val, 'Import OBJ Objects into Blender Objects', do_split) - SPLIT_GROUPS = Draw.Toggle('Group', EVENT_REDRAW, ui_x+64, ui_y+89, 55, 21, SPLIT_GROUPS.val, 'Import OBJ Groups into Blender Objects', do_split) - SPLIT_MATERIALS = Draw.Toggle('Material', EVENT_REDRAW, ui_x+119, ui_y+89, 60, 21, SPLIT_MATERIALS.val, 'Import each material into a seperate mesh (Avoids > 16 per mesh error)', do_split) - Draw.EndAlign() - - # Only used for user feedback - KEEP_VERT_ORDER = Draw.Toggle('Keep Vert Order', EVENT_REDRAW, ui_x+184, ui_y+89, 113, 21, KEEP_VERT_ORDER.val, 'Keep vert and face order, disables split options, enable for morph targets', do_vertorder) - - ROTATE_X90 = Draw.Toggle('-X90', EVENT_REDRAW, ui_x+302, ui_y+89, 38, 21, ROTATE_X90.val, 'Rotate X 90.') - - Draw.Label('Options...', ui_x+9, ui_y+60, 211, 20) - CLAMP_SIZE = Draw.Number('Clamp Scale: ', EVENT_NONE, ui_x+9, ui_y+39, 130, 21, CLAMP_SIZE.val, 0.0, 1000.0, 'Clamp the size to this maximum (Zero to Disable)') - POLYGROUPS = Draw.Toggle('Poly Groups', EVENT_REDRAW, ui_x+144, ui_y+39, 90, 21, POLYGROUPS.val, 'Import OBJ groups as vertex groups.', do_polygroups) - IMAGE_SEARCH = Draw.Toggle('Image Search', EVENT_NONE, ui_x+239, ui_y+39, 100, 21, IMAGE_SEARCH.val, 'Search subdirs for any assosiated images (Warning, may be slow)') - Draw.BeginAlign() - Draw.PushButton('Online Help', EVENT_REDRAW, ui_x+9, ui_y+9, 110, 21, 'Load the wiki page for this script', do_help) - Draw.PushButton('Cancel', EVENT_EXIT, ui_x+119, ui_y+9, 110, 21, '', obj_ui_set_event) - Draw.PushButton('Import', EVENT_IMPORT, ui_x+229, ui_y+9, 110, 21, 'Import with these settings', obj_ui_set_event) - Draw.EndAlign() - - - # hack so the toggle buttons redraw. this is not nice at all - while GLOBALS['EVENT'] not in (EVENT_EXIT, EVENT_IMPORT): - Draw.UIBlock(obj_ui, 0) - - if GLOBALS['EVENT'] != EVENT_IMPORT: - return - - # END ALTERNATIVE UI ********************* - - - - - - - - Window.WaitCursor(1) - - if BATCH_LOAD: # load the dir - try: - files= [ f for f in os.listdir(filepath) if f.lower().endswith('.obj') ] - except: - Window.WaitCursor(0) - Draw.PupMenu('Error%t|Could not open path ' + filepath) - return - - if not files: - Window.WaitCursor(0) - Draw.PupMenu('Error%t|No files at path ' + filepath) - return - - for f in files: - scn= bpy.data.scenes.new( stripExt(f) ) - scn.makeCurrent() - - load_obj(sys.join(filepath, f),\ - CLAMP_SIZE.val,\ - CREATE_FGONS.val,\ - CREATE_SMOOTH_GROUPS.val,\ - CREATE_EDGES.val,\ - SPLIT_OBJECTS.val,\ - SPLIT_GROUPS.val,\ - SPLIT_MATERIALS.val,\ - ROTATE_X90.val,\ - IMAGE_SEARCH.val,\ - POLYGROUPS.val - ) - - else: # Normal load - load_obj(filepath,\ - CLAMP_SIZE.val,\ - CREATE_FGONS.val,\ - CREATE_SMOOTH_GROUPS.val,\ - CREATE_EDGES.val,\ - SPLIT_OBJECTS.val,\ - SPLIT_GROUPS.val,\ - SPLIT_MATERIALS.val,\ - ROTATE_X90.val,\ - IMAGE_SEARCH.val,\ - POLYGROUPS.val - ) - - Window.WaitCursor(0) - - -def load_obj_ui_batch(file): - load_obj_ui(file, True) - -DEBUG= False - -if __name__=='__main__' and not DEBUG: - if os and Window.GetKeyQualifiers() & Window.Qual.SHIFT: - Window.FileSelector(load_obj_ui_batch, 'Import OBJ Dir', '') - else: - Window.FileSelector(load_obj_ui, 'Import a Wavefront OBJ', '*.obj') - - # For testing compatibility -''' -else: - # DEBUG ONLY - TIME= sys.time() - DIR = '/fe/obj' - import os - print 'Searching for files' - def fileList(path): - for dirpath, dirnames, filenames in os.walk(path): - for filename in filenames: - yield os.path.join(dirpath, filename) - - files = [f for f in fileList(DIR) if f.lower().endswith('.obj')] - files.sort() - - for i, obj_file in enumerate(files): - if 0 < i < 20: - print 'Importing', obj_file, '\nNUMBER', i, 'of', len(files) - newScn= bpy.data.scenes.new(os.path.basename(obj_file)) - newScn.makeCurrent() - load_obj(obj_file, False, IMAGE_SEARCH=0) - - print 'TOTAL TIME: %.6f' % (sys.time() - TIME) -''' -#load_obj('/test.obj') -#load_obj('/fe/obj/mba1.obj') diff --git a/release/scripts/import_web3d.py b/release/scripts/import_web3d.py deleted file mode 100644 index a5547506dc7..00000000000 --- a/release/scripts/import_web3d.py +++ /dev/null @@ -1,2594 +0,0 @@ -#!BPY -""" -Name: 'X3D & VRML97 (.x3d / wrl)...' -Blender: 248 -Group: 'Import' -Tooltip: 'Load an X3D or VRML97 file' -""" - -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# (C) Copyright 2008 Paravizion -# Written by Campbell Barton aka Ideasman42 -# -# 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 ***** -# -------------------------------------------------------------------------- - -__author__ = "Campbell Barton" -__url__ = ['www.blender.org', 'blenderartists.org', 'http://wiki.blender.org/index.php/Scripts/Manual/Import/X3D_VRML97'] -__version__ = "0.1" - -__bpydoc__ = """\ -This script is an importer for the X3D and VRML97 file formats. -""" - -DEBUG = False - -# This should work without a blender at all -try: - from Blender.sys import exists -except: - from os.path import exists - -def baseName(path): - return path.split('/')[-1].split('\\')[-1] - -def dirName(path): - return path[:-len(baseName(path))] - -def imageConvertCompat(path): - - try: import os - except: return path - if os.sep=='\\': return path # assime win32 has quicktime, dont convert - - if path.lower().endswith('.gif'): - path_to = path[:-3] + 'png' - - ''' - if exists(path_to): - return path_to - ''' - # print '\n'+path+'\n'+path_to+'\n' - os.system('convert "%s" "%s"' % (path, path_to)) # for now just hope we have image magick - - if exists(path_to): - return path_to - - return path - -# notes -# transform are relative -# order dosnt matter for loc/size/rot -# right handed rotation -# angles are in radians -# rotation first defines axis then ammount in radians - - - -# =============================== VRML Spesific - - -def vrmlFormat(data): - ''' - Keep this as a valid vrml file, but format in a way we can predict. - ''' - # Strip all commends - # not in strings - warning multiline strings are ignored. - def strip_comment(l): - #l = ' '.join(l.split()) - l = l.strip() - - if l.startswith('#'): - return '' - - i = l.find('#') - - if i==-1: - return l - - # Most cases accounted for! if we have a comment at the end of the line do this... - #j = l.find('url "') - j = l.find('"') - - if j == -1: # simple no strings - return l[:i].strip() - - q = False - for i,c in enumerate(l): - if c == '"': - q = not q # invert - - elif c == '#': - if q==False: - return l[:i-1] - - return l - - data = '\n'.join([strip_comment(l) for l in data.split('\n') ]) # remove all whitespace - - EXTRACT_STRINGS = True # only needed when strings or filesnames containe ,[]{} chars :/ - - if EXTRACT_STRINGS: - - # We need this so we can detect URL's - data = '\n'.join([' '.join(l.split()) for l in data.split('\n')]) # remove all whitespace - - string_ls = [] - - #search = 'url "' - search = '"' - - ok = True - last_i = 0 - while ok: - ok = False - i = data.find(search, last_i) - if i != -1: - - start = i + len(search) # first char after end of search - end = data.find('"', start) - if end != -1: - item = data[start:end] - string_ls.append( item ) - data = data[:start] + data[end:] - ok = True # keep looking - - last_i = (end - len(item)) + 1 - # print last_i, item, '|' + data[last_i] + '|' - - # done with messy extracting strings part - - - # Bad, dont take strings into account - ''' - data = data.replace('#', '\n#') - data = '\n'.join([ll for l in data.split('\n') for ll in (l.strip(),) if not ll.startswith('#')]) # remove all whitespace - ''' - data = data.replace('{', '\n{\n') - data = data.replace('}', '\n}\n') - data = data.replace('[', '\n[\n') - data = data.replace(']', '\n]\n') - data = data.replace(',', ' , ') # make sure comma's seperate - - if EXTRACT_STRINGS: - # add strings back in - - search = '"' # fill in these empty strings - - ok = True - last_i = 0 - while ok: - ok = False - i = data.find(search + '"', last_i) - # print i - if i != -1: - start = i + len(search) # first char after end of search - item = string_ls.pop(0) - # print item - data = data[:start] + item + data[start:] - - last_i = start + len(item) + 1 - - ok = True - - - # More annoying obscure cases where USE or DEF are placed on a newline - # data = data.replace('\nDEF ', ' DEF ') - # data = data.replace('\nUSE ', ' USE ') - - data = '\n'.join([' '.join(l.split()) for l in data.split('\n')]) # remove all whitespace - - # Better to parse the file accounting for multiline arrays - ''' - data = data.replace(',\n', ' , ') # remove line endings with commas - data = data.replace(']', '\n]\n') # very very annoying - but some comma's are at the end of the list, must run this again. - ''' - - return [l for l in data.split('\n') if l] - -NODE_NORMAL = 1 # {} -NODE_ARRAY = 2 # [] -NODE_REFERENCE = 3 # USE foobar -# NODE_PROTO = 4 # - -lines = [] - -def getNodePreText(i, words): - # print lines[i] - use_node = False - while len(words) < 5: - - if i>=len(lines): - break - ''' - elif lines[i].startswith('PROTO'): - return NODE_PROTO, i+1 - ''' - elif lines[i]=='{': - # words.append(lines[i]) # no need - # print "OK" - return NODE_NORMAL, i+1 - elif lines[i].count('"') % 2 != 0: # odd number of quotes? - part of a string. - # print 'ISSTRING' - break - else: - new_words = lines[i].split() - if 'USE' in new_words: - use_node = True - - words.extend(new_words) - i += 1 - - # Check for USE node - no { - # USE #id - should always be on the same line. - if use_node: - # print 'LINE', i, words[:words.index('USE')+2] - words[:] = words[:words.index('USE')+2] - if lines[i] == '{' and lines[i+1] == '}': - # USE sometimes has {} after it anyway - i+=2 - return NODE_REFERENCE, i - - # print "error value!!!", words - return 0, -1 - -def is_nodeline(i, words): - - if not lines[i][0].isalpha(): - return 0, 0 - - #if lines[i].startswith('field'): - # return 0, 0 - - # Is this a prototype?? - if lines[i].startswith('PROTO'): - words[:] = lines[i].split() - return NODE_NORMAL, i+1 # TODO - assumes the next line is a '[\n', skip that - if lines[i].startswith('EXTERNPROTO'): - words[:] = lines[i].split() - return NODE_ARRAY, i+1 # TODO - assumes the next line is a '[\n', skip that - - ''' - proto_type, new_i = is_protoline(i, words, proto_field_defs) - if new_i != -1: - return proto_type, new_i - ''' - - # Simple "var [" type - if lines[i+1] == '[': - if lines[i].count('"') % 2 == 0: - words[:] = lines[i].split() - return NODE_ARRAY, i+2 - - node_type, new_i = getNodePreText(i, words) - - if not node_type: - if DEBUG: print "not node_type", lines[i] - return 0, 0 - - # Ok, we have a { after some values - # Check the values are not fields - for i, val in enumerate(words): - if i != 0 and words[i-1] in ('DEF', 'USE'): - # ignore anything after DEF, it is a ID and can contain any chars. - pass - elif val[0].isalpha() and val not in ('TRUE', 'FALSE'): - pass - else: - # There is a number in one of the values, therefor we are not a node. - return 0, 0 - - #if node_type==NODE_REFERENCE: - # print words, "REF_!!!!!!!" - return node_type, new_i - -def is_numline(i): - ''' - Does this line start with a number? - ''' - - # Works but too slow. - ''' - l = lines[i] - for w in l.split(): - if w==',': - pass - else: - try: - float(w) - return True - - except: - return False - - return False - ''' - - l = lines[i] - - line_start = 0 - - if l.startswith(', '): - line_start += 2 - - line_end = len(l)-1 - line_end_new = l.find(' ', line_start) # comma's always have a space before them - - if line_end_new != -1: - line_end = line_end_new - - try: - float(l[line_start:line_end]) # works for a float or int - return True - except: - return False - - -class vrmlNode(object): - __slots__ = 'id', 'fields', 'proto_node', 'proto_field_defs', 'proto_fields', 'node_type', 'parent', 'children', 'parent', 'array_data', 'reference', 'lineno', 'filename', 'blendObject', 'DEF_NAMESPACE', 'ROUTE_IPO_NAMESPACE', 'PROTO_NAMESPACE', 'x3dNode' - def __init__(self, parent, node_type, lineno): - self.id = None - self.node_type = node_type - self.parent = parent - self.blendObject = None - self.x3dNode = None # for x3d import only - if parent: - parent.children.append(self) - - self.lineno = lineno - - # This is only set from the root nodes. - # Having a filename also denotes a root node - self.filename = None - self.proto_node = None # proto field definition eg: "field SFColor seatColor .6 .6 .1" - - # Store in the root node because each inline file needs its own root node and its own namespace - self.DEF_NAMESPACE = None - self.ROUTE_IPO_NAMESPACE = None - ''' - self.FIELD_NAMESPACE = None - ''' - - - self.PROTO_NAMESPACE = None - - self.reference = None - - if node_type==NODE_REFERENCE: - # For references, only the parent and ID are needed - # the reference its self is assigned on parsing - return - - self.fields = [] # fields have no order, in some cases rool level values are not unique so dont use a dict - - self.proto_field_defs = [] # proto field definition eg: "field SFColor seatColor .6 .6 .1" - self.proto_fields = [] # proto field usage "diffuseColor IS seatColor" - self.children = [] - self.array_data = [] # use for arrays of data - should only be for NODE_ARRAY types - - - # Only available from the root node - ''' - def getFieldDict(self): - if self.FIELD_NAMESPACE != None: - return self.FIELD_NAMESPACE - else: - return self.parent.getFieldDict() - ''' - def getProtoDict(self): - if self.PROTO_NAMESPACE != None: - return self.PROTO_NAMESPACE - else: - return self.parent.getProtoDict() - - def getDefDict(self): - if self.DEF_NAMESPACE != None: - return self.DEF_NAMESPACE - else: - return self.parent.getDefDict() - - def getRouteIpoDict(self): - if self.ROUTE_IPO_NAMESPACE != None: - return self.ROUTE_IPO_NAMESPACE - else: - return self.parent.getRouteIpoDict() - - def setRoot(self, filename): - self.filename = filename - # self.FIELD_NAMESPACE = {} - self.DEF_NAMESPACE = {} - self.ROUTE_IPO_NAMESPACE = {} - self.PROTO_NAMESPACE = {} - - def isRoot(self): - if self.filename == None: - return False - else: - return True - - def getFilename(self): - if self.filename: - return self.filename - elif self.parent: - return self.parent.getFilename() - else: - return None - - def getRealNode(self): - if self.reference: - return self.reference - else: - return self - - def getSpec(self): - self_real = self.getRealNode() - try: - return self_real.id[-1] # its possible this node has no spec - except: - return None - - def findSpecRecursive(self, spec): - self_real = self.getRealNode() - if spec == self_real.getSpec(): - return self - - for child in self_real.children: - if child.findSpecRecursive(spec): - return child - - return None - - def getPrefix(self): - if self.id: - return self.id[0] - return None - - def getSpecialTypeName(self, typename): - self_real = self.getRealNode() - try: return self_real.id[ list(self_real.id).index(typename)+1 ] - except: return None - - - def getDefName(self): - return self.getSpecialTypeName('DEF') - - def getProtoName(self): - return self.getSpecialTypeName('PROTO') - - def getExternprotoName(self): - return self.getSpecialTypeName('EXTERNPROTO') - - def getChildrenBySpec(self, node_spec): # spec could be Transform, Shape, Appearance - self_real = self.getRealNode() - # using getSpec functions allows us to use the spec of USE children that dont have their spec in their ID - if type(node_spec) == str: - return [child for child in self_real.children if child.getSpec()==node_spec] - else: - # Check inside a list of optional types - return [child for child in self_real.children if child.getSpec() in node_spec] - - def getChildBySpec(self, node_spec): # spec could be Transform, Shape, Appearance - # Use in cases where there is only ever 1 child of this type - ls = self.getChildrenBySpec(node_spec) - if ls: return ls[0] - else: return None - - def getChildrenByName(self, node_name): # type could be geometry, children, appearance - self_real = self.getRealNode() - return [child for child in self_real.children if child.id if child.id[0]==node_name] - - def getChildByName(self, node_name): - self_real = self.getRealNode() - for child in self_real.children: - if child.id and child.id[0]==node_name: # and child.id[-1]==node_spec: - return child - - def getSerialized(self, results, ancestry): - ''' Return this node and all its children in a flat list ''' - ancestry = ancestry[:] # always use a copy - - # self_real = self.getRealNode() - - results.append((self, tuple(ancestry))) - ancestry.append(self) - for child in self.getRealNode().children: - if child not in ancestry: - # We dont want to load proto's, they are only references - # We could enforce this elsewhere - - # Only add this in a very special case - # where the parent of this object is not the real parent - # - In this case we have added the proto as a child to a node instancing it. - # This is a bit arbitary, but its how Proto's are done with this importer. - if child.getProtoName() == None and child.getExternprotoName() == None: - child.getSerialized(results, ancestry) - else: - - if DEBUG: print 'getSerialized() is proto:', child.getProtoName(), child.getExternprotoName(), self.getSpec() - - self_spec = self.getSpec() - - if child.getProtoName() == self_spec or child.getExternprotoName() == self_spec: - if DEBUG: "FoundProto!" - child.getSerialized(results, ancestry) - - - - return results - - def searchNodeTypeID(self, node_spec, results): - self_real = self.getRealNode() - # print self.lineno, self.id - if self_real.id and self_real.id[-1]==node_spec: # use last element, could also be only element - results.append(self_real) - for child in self_real.children: - child.searchNodeTypeID(node_spec, results) - return results - - def getFieldName(self, field, ancestry, AS_CHILD=False): - self_real = self.getRealNode() # incase we're an instance - - for f in self_real.fields: - # print f - if f and f[0] == field: - # print '\tfound field', f - - if len(f)>=3 and f[1] == 'IS': # eg: 'diffuseColor IS legColor' - field_id = f[2] - - # print "\n\n\n\n\n\nFOND IS!!!" - f_proto_lookup = None - f_proto_child_lookup = None - i = len(ancestry) - while i: - i -= 1 - node = ancestry[i] - node = node.getRealNode() - - # proto settings are stored in "self.proto_node" - if node.proto_node: - # Get the default value from the proto, this can be overwridden by the proto instace - # 'field SFColor legColor .8 .4 .7' - if AS_CHILD: - for child in node.proto_node.children: - #if child.id and len(child.id) >= 3 and child.id[2]==field_id: - if child.id and ('point' in child.id or 'points' in child.id): - f_proto_child_lookup = child - - else: - for f_def in node.proto_node.proto_field_defs: - if len(f_def) >= 4: - if f_def[0]=='field' and f_def[2]==field_id: - f_proto_lookup = f_def[3:] - - # Node instance, Will be 1 up from the proto-node in the ancestry list. but NOT its parent. - # This is the setting as defined by the instance, including this setting is optional, - # and will override the default PROTO value - # eg: 'legColor 1 0 0' - if AS_CHILD: - for child in node.children: - if child.id and child.id[0]==field_id: - f_proto_child_lookup = child - else: - for f_def in node.fields: - if len(f_def) >= 2: - if f_def[0]==field_id: - if DEBUG: print "getFieldName(), found proto", f_def - f_proto_lookup = f_def[1:] - - - if AS_CHILD: - if f_proto_child_lookup: - if DEBUG: - print "getFieldName() - AS_CHILD=True, child found" - print f_proto_child_lookup - return f_proto_child_lookup - else: - return f_proto_lookup - else: - if AS_CHILD: - return None - else: - # Not using a proto - return f[1:] - - # print '\tfield not found', field - - - # See if this is a proto name - if AS_CHILD: - child_array = None - for child in self_real.children: - if child.id and len(child.id) == 1 and child.id[0] == field: - return child - - return None - - def getFieldAsInt(self, field, default, ancestry): - self_real = self.getRealNode() # incase we're an instance - - f = self_real.getFieldName(field, ancestry) - if f==None: return default - if ',' in f: f = f[:f.index(',')] # strip after the comma - - if len(f) != 1: - print '\t"%s" wrong length for int conversion for field "%s"' % (f, field) - return default - - try: - return int(f[0]) - except: - print '\tvalue "%s" could not be used as an int for field "%s"' % (f[0], field) - return default - - def getFieldAsFloat(self, field, default, ancestry): - self_real = self.getRealNode() # incase we're an instance - - f = self_real.getFieldName(field, ancestry) - if f==None: return default - if ',' in f: f = f[:f.index(',')] # strip after the comma - - if len(f) != 1: - print '\t"%s" wrong length for float conversion for field "%s"' % (f, field) - return default - - try: - return float(f[0]) - except: - print '\tvalue "%s" could not be used as a float for field "%s"' % (f[0], field) - return default - - def getFieldAsFloatTuple(self, field, default, ancestry): - self_real = self.getRealNode() # incase we're an instance - - f = self_real.getFieldName(field, ancestry) - if f==None: return default - # if ',' in f: f = f[:f.index(',')] # strip after the comma - - if len(f) < 1: - print '"%s" wrong length for float tuple conversion for field "%s"' % (f, field) - return default - - ret = [] - for v in f: - if v != ',': - try: ret.append(float(v)) - except: break # quit of first non float, perhaps its a new field name on the same line? - if so we are going to ignore it :/ TODO - # print ret - - if ret: - return ret - if not ret: - print '\tvalue "%s" could not be used as a float tuple for field "%s"' % (f, field) - return default - - def getFieldAsBool(self, field, default, ancestry): - self_real = self.getRealNode() # incase we're an instance - - f = self_real.getFieldName(field, ancestry) - if f==None: return default - if ',' in f: f = f[:f.index(',')] # strip after the comma - - if len(f) != 1: - print '\t"%s" wrong length for bool conversion for field "%s"' % (f, field) - return default - - if f[0].upper()=='"TRUE"' or f[0].upper()=='TRUE': - return True - elif f[0].upper()=='"FALSE"' or f[0].upper()=='FALSE': - return False - else: - print '\t"%s" could not be used as a bool for field "%s"' % (f[1], field) - return default - - def getFieldAsString(self, field, default, ancestry): - self_real = self.getRealNode() # incase we're an instance - - f = self_real.getFieldName(field, ancestry) - if f==None: return default - if len(f) < 1: - print '\t"%s" wrong length for string conversion for field "%s"' % (f, field) - return default - - if len(f) > 1: - # String may contain spaces - st = ' '.join(f) - else: - st = f[0] - - # X3D HACK - if self.x3dNode: - return st - - if st[0]=='"' and st[-1]=='"': - return st[1:-1] - else: - print '\tvalue "%s" could not be used as a string for field "%s"' % (f[0], field) - return default - - def getFieldAsArray(self, field, group, ancestry): - ''' - For this parser arrays are children - ''' - self_real = self.getRealNode() # incase we're an instance - - child_array = self_real.getFieldName(field, ancestry, True) - - #if type(child_array)==list: # happens occasionaly - # array_data = child_array - - if child_array==None: - - # For x3d, should work ok with vrml too - # for x3d arrays are fields, vrml they are nodes, annoying but not tooo bad. - data_split = self.getFieldName(field, ancestry) - if not data_split: - return [] - array_data = ' '.join(data_split) - if array_data == None: - return [] - - array_data = array_data.replace(',', ' ') - data_split = array_data.split() - try: - array_data = [int(val) for val in data_split] - except: - try: - array_data = [float(val) for val in data_split] - except: - print '\tWarning, could not parse array data from field' - array_data = [] - else: - # print child_array - # Normal vrml - array_data = child_array.array_data - - - # print 'array_data', array_data - - if group==-1 or len(array_data)==0: - return array_data - - # We want a flat list - flat = True - for item in array_data: - if type(item) == list: - flat = False - break - - # make a flat array - if flat: - flat_array = array_data # we are alredy flat. - else: - flat_array = [] - - def extend_flat(ls): - for item in ls: - if type(item)==list: extend_flat(item) - else: flat_array.append(item) - - extend_flat(array_data) - - - # We requested a flat array - if group == 0: - return flat_array - - new_array = [] - sub_array = [] - - for item in flat_array: - sub_array.append(item) - if len(sub_array)==group: - new_array.append(sub_array) - sub_array = [] - - if sub_array: - print '\twarning, array was not aligned to requested grouping', group, 'remaining value', sub_array - - return new_array - - def getFieldAsStringArray(self, field, ancestry): - ''' - Get a list of strings - ''' - self_real = self.getRealNode() # incase we're an instance - - child_array = None - for child in self_real.children: - if child.id and len(child.id) == 1 and child.id[0] == field: - child_array = child - break - if not child_array: - return [] - - # each string gets its own list, remove ""'s - try: - new_array = [f[0][1:-1] for f in child_array.fields] - except: - print '\twarning, string array could not be made' - new_array = [] - - return new_array - - - def getLevel(self): - # Ignore self_real - level = 0 - p = self.parent - while p: - level +=1 - p = p.parent - if not p: break - - return level - - def __repr__(self): - level = self.getLevel() - ind = ' ' * level - if self.node_type==NODE_REFERENCE: - brackets = '' - elif self.node_type==NODE_NORMAL: - brackets = '{}' - else: - brackets = '[]' - - if brackets: - text = ind + brackets[0] + '\n' - else: - text = '' - - text += ind + 'ID: ' + str(self.id) + ' ' + str(level) + (' lineno %d\n' % self.lineno) - - if self.node_type==NODE_REFERENCE: - text += ind + "(reference node)\n" - return text - - if self.proto_node: - text += ind + 'PROTO NODE...\n' - text += str(self.proto_node) - text += ind + 'PROTO NODE_DONE\n' - - text += ind + 'FIELDS:' + str(len(self.fields)) + '\n' - - for i,item in enumerate(self.fields): - text += ind + 'FIELD:\n' - text += ind + str(item) +'\n' - - text += ind + 'PROTO_FIELD_DEFS:' + str(len(self.proto_field_defs)) + '\n' - - for i,item in enumerate(self.proto_field_defs): - text += ind + 'PROTO_FIELD:\n' - text += ind + str(item) +'\n' - - text += ind + 'ARRAY: ' + str(len(self.array_data)) + ' ' + str(self.array_data) + '\n' - #text += ind + 'ARRAY: ' + str(len(self.array_data)) + '[...] \n' - - text += ind + 'CHILDREN: ' + str(len(self.children)) + '\n' - for i, child in enumerate(self.children): - text += ind + ('CHILD%d:\n' % i) - text += str(child) - - text += '\n' + ind + brackets[1] - - return text - - def parse(self, i, IS_PROTO_DATA=False): - new_i = self.__parse(i, IS_PROTO_DATA) - - # print self.id, self.getFilename() - - # Check if this node was an inline or externproto - - url_ls = [] - - if self.node_type == NODE_NORMAL and self.getSpec() == 'Inline': - ancestry = [] # Warning! - PROTO's using this wont work at all. - url = self.getFieldAsString('url', None, ancestry) - if url: - url_ls = [(url, None)] - del ancestry - - elif self.getExternprotoName(): - # externproto - url_ls = [] - for f in self.fields: - - if type(f)==str: - f = [f] - - for ff in f: - for f_split in ff.split('"'): - # print f_split - # "someextern.vrml#SomeID" - if '#' in f_split: - - f_split, f_split_id = f_split.split('#') # there should only be 1 # anyway - - url_ls.append( (f_split, f_split_id) ) - else: - url_ls.append( (f_split, None) ) - - - # Was either an Inline or an EXTERNPROTO - if url_ls: - - # print url_ls - - for url, extern_key in url_ls: - print url - urls = [] - urls.append( url ) - urls.append( BPySys.caseInsensitivePath(urls[-1]) ) - - urls.append( dirName(self.getFilename()) + url ) - urls.append( BPySys.caseInsensitivePath(urls[-1]) ) - - urls.append( dirName(self.getFilename()) + baseName(url) ) - urls.append( BPySys.caseInsensitivePath(urls[-1]) ) - - try: - url = [url for url in urls if exists(url)][0] - url_found = True - except: - url_found = False - - if not url_found: - print '\tWarning: Inline URL could not be found:', url - else: - if url==self.getFilename(): - print '\tWarning: cant Inline yourself recursively:', url - else: - - try: - data = gzipOpen(url) - except: - print '\tWarning: cant open the file:', url - data = None - - if data: - # Tricky - inline another VRML - print '\tLoading Inline:"%s"...' % url - - # Watch it! - backup lines - lines_old = lines[:] - - - lines[:] = vrmlFormat( data ) - - lines.insert(0, '{') - lines.insert(0, 'root_node____') - lines.append('}') - ''' - ff = open('/tmp/test.txt', 'w') - ff.writelines([l+'\n' for l in lines]) - ''' - - child = vrmlNode(self, NODE_NORMAL, -1) - child.setRoot(url) # initialized dicts - child.parse(0) - - # if self.getExternprotoName(): - if self.getExternprotoName(): - if not extern_key: # if none is spesified - use the name - extern_key = self.getSpec() - - if extern_key: - - self.children.remove(child) - child.parent = None - - extern_child = child.findSpecRecursive(extern_key) - - if extern_child: - self.children.append(extern_child) - extern_child.parent = self - - if DEBUG: print "\tEXTERNPROTO ID found!:", extern_key - else: - print "\tEXTERNPROTO ID not found!:", extern_key - - # Watch it! - restore lines - lines[:] = lines_old - - return new_i - - def __parse(self, i, IS_PROTO_DATA=False): - ''' - print 'parsing at', i, - print i, self.id, self.lineno - ''' - l = lines[i] - - if l=='[': - # An anonymous list - self.id = None - i+=1 - else: - words = [] - - node_type, new_i = is_nodeline(i, words) - if not node_type: # fail for parsing new node. - print "Failed to parse new node" - raise ValueError - - if self.node_type==NODE_REFERENCE: - # Only assign the reference and quit - key = words[words.index('USE')+1] - self.id = (words[0],) - - self.reference = self.getDefDict()[key] - return new_i - - self.id = tuple(words) - - # fill in DEF/USE - key = self.getDefName() - if key != None: - self.getDefDict()[ key ] = self - - key = self.getProtoName() - if not key: key = self.getExternprotoName() - - proto_dict = self.getProtoDict() - if key != None: - proto_dict[ key ] = self - - # Parse the proto nodes fields - self.proto_node = vrmlNode(self, NODE_ARRAY, new_i) - new_i = self.proto_node.parse(new_i) - - self.children.remove(self.proto_node) - - # print self.proto_node - - new_i += 1 # skip past the { - - - else: # If we're a proto instance, add the proto node as our child. - spec = self.getSpec() - try: - self.children.append( proto_dict[spec] ) - #pass - except: - pass - - del spec - - del proto_dict, key - - i = new_i - - # print self.id - ok = True - while ok: - if i>=len(lines): - return len(lines)-1 - - l = lines[i] - # print '\tDEBUG:', i, self.node_type, l - if l=='': - i+=1 - continue - - if l=='}': - if self.node_type != NODE_NORMAL: # also ends proto nodes, we may want a type for these too. - print 'wrong node ending, expected an } ' + str(i) + ' ' + str(self.node_type) - if DEBUG: - raise ValueError - ### print "returning", i - return i+1 - if l==']': - if self.node_type != NODE_ARRAY: - print 'wrong node ending, expected a ] ' + str(i) + ' ' + str(self.node_type) - if DEBUG: - raise ValueError - ### print "returning", i - return i+1 - - node_type, new_i = is_nodeline(i, []) - if node_type: # check text\n{ - child = vrmlNode(self, node_type, i) - i = child.parse(i) - - elif l=='[': # some files have these anonymous lists - child = vrmlNode(self, NODE_ARRAY, i) - i = child.parse(i) - - elif is_numline(i): - l_split = l.split(',') - - values = None - # See if each item is a float? - - for num_type in (int, float): - try: - values = [num_type(v) for v in l_split ] - break - except: - pass - - - try: - values = [[num_type(v) for v in segment.split()] for segment in l_split ] - break - except: - pass - - if values == None: # dont parse - values = l_split - - # This should not extend over multiple lines however it is possible - # print self.array_data - if values: - self.array_data.extend( values ) - i+=1 - else: - words = l.split() - if len(words) > 2 and words[1] == 'USE': - vrmlNode(self, NODE_REFERENCE, i) - else: - - # print "FIELD", i, l - # - #words = l.split() - ### print '\t\ttag', i - # this is a tag/ - # print words, i, l - value = l - # print i - # javastrips can exist as values. - quote_count = l.count('"') - if quote_count % 2: # odd number? - # print 'MULTILINE' - while 1: - i+=1 - l = lines[i] - quote_count = l.count('"') - if quote_count % 2: # odd number? - value += '\n'+ l[:l.rfind('"')] - break # assume - else: - value += '\n'+ l - - value_all = value.split() - - def iskey(k): - if k[0] != '"' and k[0].isalpha() and k.upper() not in ('TRUE', 'FALSE'): - return True - return False - - def split_fields(value): - ''' - key 0.0 otherkey 1,2,3 opt1 opt1 0.0 - -> [key 0.0], [otherkey 1,2,3], [opt1 opt1 0.0] - ''' - field_list = [] - field_context = [] - - for j in xrange(len(value)): - if iskey(value[j]): - if field_context: - # this IS a key but the previous value was not a key, ot it was a defined field. - if (not iskey(field_context[-1])) or ((len(field_context)==3 and field_context[1]=='IS')): - field_list.append(field_context) - - field_context = [value[j]] - else: - # The last item was not a value, multiple keys are needed in some cases. - field_context.append(value[j]) - else: - # Is empty, just add this on - field_context.append(value[j]) - else: - # Add a value to the list - field_context.append(value[j]) - - if field_context: - field_list.append(field_context) - - return field_list - - - for value in split_fields(value_all): - # Split - - if value[0]=='field': - # field SFFloat creaseAngle 4 - self.proto_field_defs.append(value) - else: - self.fields.append(value) - i+=1 - -def gzipOpen(path): - try: import gzip - except: gzip = None - - data = None - if gzip: - try: data = gzip.open(path, 'r').read() - except: pass - else: - print '\tNote, gzip module could not be imported, compressed files will fail to load' - - if data==None: - try: data = open(path, 'rU').read() - except: pass - - return data - -def vrml_parse(path): - ''' - Sets up the root node and returns it so load_web3d() can deal with the blender side of things. - Return root (vrmlNode, '') or (None, 'Error String') - ''' - data = gzipOpen(path) - - if data==None: - return None, 'Failed to open file: ' + path - - # Stripped above - lines[:] = vrmlFormat( data ) - - lines.insert(0, '{') - lines.insert(0, 'dymmy_node') - lines.append('}') - # Use for testing our parsed output, so we can check on line numbers. - - ''' - ff = open('/tmp/test.txt', 'w') - ff.writelines([l+'\n' for l in lines]) - ff.close() - ''' - - # Now evaluate it - node_type, new_i = is_nodeline(0, []) - if not node_type: - return None, 'Error: VRML file has no starting Node' - - # Trick to make sure we get all root nodes. - lines.insert(0, '{') - lines.insert(0, 'root_node____') # important the name starts with an ascii char - lines.append('}') - - root = vrmlNode(None, NODE_NORMAL, -1) - root.setRoot(path) # we need to set the root so we have a namespace and know the path incase of inlineing - - # Parse recursively - root.parse(0) - - # This prints a load of text - if DEBUG: - print root - - return root, '' - - -# ====================== END VRML - - - -# ====================== X3d Support - -# Sane as vrml but replace the parser -class x3dNode(vrmlNode): - def __init__(self, parent, node_type, x3dNode): - vrmlNode.__init__(self, parent, node_type, -1) - self.x3dNode = x3dNode - - def parse(self, IS_PROTO_DATA=False): - # print self.x3dNode.tagName - - define = self.x3dNode.getAttributeNode('DEF') - if define: - self.getDefDict()[define.value] = self - else: - use = self.x3dNode.getAttributeNode('USE') - if use: - try: - self.reference = self.getDefDict()[use.value] - self.node_type = NODE_REFERENCE - except: - print '\tWarning: reference', use.value, 'not found' - self.parent.children.remove(self) - - return - - for x3dChildNode in self.x3dNode.childNodes: - if x3dChildNode.nodeType in (x3dChildNode.TEXT_NODE, x3dChildNode.COMMENT_NODE, x3dChildNode.CDATA_SECTION_NODE): - continue - - node_type = NODE_NORMAL - # print x3dChildNode, dir(x3dChildNode) - if x3dChildNode.getAttributeNode('USE'): - node_type = NODE_REFERENCE - - child = x3dNode(self, node_type, x3dChildNode) - child.parse() - - # TODO - x3d Inline - - def getSpec(self): - return self.x3dNode.tagName # should match vrml spec - - def getDefName(self): - data = self.x3dNode.getAttributeNode('DEF') - if data: data.value - return None - - # Other funcs operate from vrml, but this means we can wrap XML fields, still use nice utility funcs - # getFieldAsArray getFieldAsBool etc - def getFieldName(self, field, ancestry, AS_CHILD=False): - # ancestry and AS_CHILD are ignored, only used for VRML now - - self_real = self.getRealNode() # incase we're an instance - field_xml = self.x3dNode.getAttributeNode(field) - if field_xml: - value = field_xml.value - - # We may want to edit. for x3d spesific stuff - # Sucks a bit to return the field name in the list but vrml excepts this :/ - return value.split() - else: - return None - -def x3d_parse(path): - ''' - Sets up the root node and returns it so load_web3d() can deal with the blender side of things. - Return root (x3dNode, '') or (None, 'Error String') - ''' - - try: - import xml.dom.minidom - except: - return None, 'Error, import XML parsing module (xml.dom.minidom) failed, install python' - - ''' - try: doc = xml.dom.minidom.parse(path) - except: return None, 'Could not parse this X3D file, XML error' - ''' - - # Could add a try/except here, but a console error is more useful. - data = gzipOpen(path) - - if data==None: - return None, 'Failed to open file: ' + path - - doc = xml.dom.minidom.parseString(data) - - - try: - x3dnode = doc.getElementsByTagName('X3D')[0] - except: - return None, 'Not a valid x3d document, cannot import' - - root = x3dNode(None, NODE_NORMAL, x3dnode) - root.setRoot(path) # so images and Inline's we load have a relative path - root.parse() - - return root, '' - - - -## f = open('/_Cylinder.wrl', 'r') -# f = open('/fe/wrl/Vrml/EGS/TOUCHSN.WRL', 'r') -# vrml_parse('/fe/wrl/Vrml/EGS/TOUCHSN.WRL') -#vrml_parse('/fe/wrl/Vrml/EGS/SCRIPT.WRL') -''' - -import os -files = os.popen('find /fe/wrl -iname "*.wrl"').readlines() -files.sort() -tot = len(files) -for i, f in enumerate(files): - #if i < 801: - # continue - - f = f.strip() - print f, i, tot - vrml_parse(f) -''' - -# NO BLENDER CODE ABOVE THIS LINE. -# ----------------------------------------------------------------------------------- -import bpy -import BPyImage -import BPySys -reload(BPySys) -reload(BPyImage) -import Blender -from Blender import Texture, Material, Mathutils, Mesh, Types, Window -from Blender.Mathutils import TranslationMatrix -from Blender.Mathutils import RotationMatrix -from Blender.Mathutils import Vector -from Blender.Mathutils import Matrix - -RAD_TO_DEG = 57.29578 - -GLOBALS = {'CIRCLE_DETAIL':16} - -def translateRotation(rot): - ''' axis, angle ''' - return RotationMatrix(rot[3]*RAD_TO_DEG, 4, 'r', Vector(rot[:3])) - -def translateScale(sca): - mat = Matrix() # 4x4 default - mat[0][0] = sca[0] - mat[1][1] = sca[1] - mat[2][2] = sca[2] - return mat - -def translateTransform(node, ancestry): - cent = node.getFieldAsFloatTuple('center', None, ancestry) # (0.0, 0.0, 0.0) - rot = node.getFieldAsFloatTuple('rotation', None, ancestry) # (0.0, 0.0, 1.0, 0.0) - sca = node.getFieldAsFloatTuple('scale', None, ancestry) # (1.0, 1.0, 1.0) - scaori = node.getFieldAsFloatTuple('scaleOrientation', None, ancestry) # (0.0, 0.0, 1.0, 0.0) - tx = node.getFieldAsFloatTuple('translation', None, ancestry) # (0.0, 0.0, 0.0) - - if cent: - cent_mat = TranslationMatrix(Vector(cent)).resize4x4() - cent_imat = cent_mat.copy().invert() - else: - cent_mat = cent_imat = None - - if rot: rot_mat = translateRotation(rot) - else: rot_mat = None - - if sca: sca_mat = translateScale(sca) - else: sca_mat = None - - if scaori: - scaori_mat = translateRotation(scaori) - scaori_imat = scaori_mat.copy().invert() - else: - scaori_mat = scaori_imat = None - - if tx: tx_mat = TranslationMatrix(Vector(tx)).resize4x4() - else: tx_mat = None - - new_mat = Matrix() - - mats = [tx_mat, cent_mat, rot_mat, scaori_mat, sca_mat, scaori_imat, cent_imat] - for mtx in mats: - if mtx: - new_mat = mtx * new_mat - - return new_mat - -def translateTexTransform(node, ancestry): - cent = node.getFieldAsFloatTuple('center', None, ancestry) # (0.0, 0.0) - rot = node.getFieldAsFloat('rotation', None, ancestry) # 0.0 - sca = node.getFieldAsFloatTuple('scale', None, ancestry) # (1.0, 1.0) - tx = node.getFieldAsFloatTuple('translation', None, ancestry) # (0.0, 0.0) - - - if cent: - # cent is at a corner by default - cent_mat = TranslationMatrix(Vector(cent).resize3D()).resize4x4() - cent_imat = cent_mat.copy().invert() - else: - cent_mat = cent_imat = None - - if rot: rot_mat = RotationMatrix(rot*RAD_TO_DEG, 4, 'z') # translateRotation(rot) - else: rot_mat = None - - if sca: sca_mat = translateScale((sca[0], sca[1], 0.0)) - else: sca_mat = None - - if tx: tx_mat = TranslationMatrix(Vector(tx).resize3D()).resize4x4() - else: tx_mat = None - - new_mat = Matrix() - - # as specified in VRML97 docs - mats = [cent_imat, sca_mat, rot_mat, cent_mat, tx_mat] - - for mtx in mats: - if mtx: - new_mat = mtx * new_mat - - return new_mat - - - -def getFinalMatrix(node, mtx, ancestry): - - transform_nodes = [node_tx for node_tx in ancestry if node_tx.getSpec() == 'Transform'] - if node.getSpec()=='Transform': - transform_nodes.append(node) - transform_nodes.reverse() - - if mtx==None: - mtx = Matrix() - - for node_tx in transform_nodes: - mat = translateTransform(node_tx, ancestry) - mtx = mtx * mat - - return mtx - -def importMesh_IndexedFaceSet(geom, bpyima, ancestry): - # print geom.lineno, geom.id, vrmlNode.DEF_NAMESPACE.keys() - - ccw = geom.getFieldAsBool('ccw', True, ancestry) - ifs_colorPerVertex = geom.getFieldAsBool('colorPerVertex', True, ancestry) # per vertex or per face - ifs_normalPerVertex = geom.getFieldAsBool('normalPerVertex', True, ancestry) - - # This is odd how point is inside Coordinate - - # VRML not x3d - #coord = geom.getChildByName('coord') # 'Coordinate' - - coord = geom.getChildBySpec('Coordinate') # works for x3d and vrml - - if coord: ifs_points = coord.getFieldAsArray('point', 3, ancestry) - else: coord = [] - - if not coord: - print '\tWarnint: IndexedFaceSet has no points' - return None, ccw - - ifs_faces = geom.getFieldAsArray('coordIndex', 0, ancestry) - - coords_tex = None - if ifs_faces: # In rare cases this causes problems - no faces but UVs??? - - # WORKS - VRML ONLY - # coords_tex = geom.getChildByName('texCoord') - coords_tex = geom.getChildBySpec('TextureCoordinate') - - if coords_tex: - ifs_texpoints = coords_tex.getFieldAsArray('point', 2, ancestry) - ifs_texfaces = geom.getFieldAsArray('texCoordIndex', 0, ancestry) - - if not ifs_texpoints: - # IF we have no coords, then dont bother - coords_tex = None - - - # WORKS - VRML ONLY - # vcolor = geom.getChildByName('color') - vcolor = geom.getChildBySpec('Color') - vcolor_spot = None # spot color when we dont have an array of colors - if vcolor: - # float to char - ifs_vcol = [(0,0,0)] # EEKADOODLE - vertex start at 1 - ifs_vcol.extend([[int(c*256) for c in col] for col in vcolor.getFieldAsArray('color', 3, ancestry)]) - ifs_color_index = geom.getFieldAsArray('colorIndex', 0, ancestry) - - if not ifs_vcol: - vcolor_spot = [int(c*256) for c in vcolor.getFieldAsFloatTuple('color', [], ancestry)] - - # Convert faces into somthing blender can use - edges = [] - - # All lists are aligned! - faces = [] - faces_uv = [] # if ifs_texfaces is empty then the faces_uv will match faces exactly. - faces_orig_index = [] # for ngons, we need to know our original index - - if coords_tex and ifs_texfaces: - do_uvmap = True - else: - do_uvmap = False - - # current_face = [0] # pointer anyone - - def add_face(face, fuvs, orig_index): - l = len(face) - if l==3 or l==4: - faces.append(face) - # faces_orig_index.append(current_face[0]) - if do_uvmap: - faces_uv.append(fuvs) - - faces_orig_index.append(orig_index) - elif l==2: edges.append(face) - elif l>4: - for i in xrange(2, len(face)): - faces.append([face[0], face[i-1], face[i]]) - if do_uvmap: - faces_uv.append([fuvs[0], fuvs[i-1], fuvs[i]]) - faces_orig_index.append(orig_index) - else: - # faces with 1 verts? pfft! - # still will affect index ordering - pass - - face = [] - fuvs = [] - orig_index = 0 - for i, fi in enumerate(ifs_faces): - # ifs_texfaces and ifs_faces should be aligned - if fi != -1: - # face.append(int(fi)) # in rare cases this is a float - # EEKADOODLE!!! - # Annoyance where faces that have a zero index vert get rotated. This will then mess up UVs and VColors - face.append(int(fi)+1) # in rare cases this is a float, +1 because of stupid EEKADOODLE :/ - - if do_uvmap: - if i >= len(ifs_texfaces): - print '\tWarning: UV Texface index out of range' - fuvs.append(ifs_texfaces[0]) - else: - fuvs.append(ifs_texfaces[i]) - else: - add_face(face, fuvs, orig_index) - face = [] - if do_uvmap: - fuvs = [] - orig_index += 1 - - add_face(face, fuvs, orig_index) - del add_face # dont need this func anymore - - bpymesh = bpy.data.meshes.new() - - bpymesh.verts.extend([(0,0,0)]) # EEKADOODLE - bpymesh.verts.extend(ifs_points) - - # print len(ifs_points), faces, edges, ngons - - try: - bpymesh.faces.extend(faces, smooth=True, ignoreDups=True) - except KeyError: - print "one or more vert indicies out of range. corrupt file?" - #for f in faces: - # bpymesh.faces.extend(faces, smooth=True) - - bpymesh.calcNormals() - - if len(bpymesh.faces) != len(faces): - print '\tWarning: adding faces did not work! file is invalid, not adding UVs or vcolors' - return bpymesh, ccw - - # Apply UVs if we have them - if not do_uvmap: - faces_uv = faces # fallback, we didnt need a uvmap in the first place, fallback to the face/vert mapping. - if coords_tex: - #print ifs_texpoints - # print geom - bpymesh.faceUV = True - for i,f in enumerate(bpymesh.faces): - f.image = bpyima - fuv = faces_uv[i] # uv indicies - for j,uv in enumerate(f.uv): - # print fuv, j, len(ifs_texpoints) - try: - uv[:] = ifs_texpoints[fuv[j]] - except: - print '\tWarning: UV Index out of range' - uv[:] = ifs_texpoints[0] - - elif bpyima and len(bpymesh.faces): - # Oh Bugger! - we cant really use blenders ORCO for for texture space since texspace dosnt rotate. - # we have to create VRML's coords as UVs instead. - - # VRML docs - ''' - If the texCoord field is NULL, a default texture coordinate mapping is calculated using the local - coordinate system bounding box of the shape. The longest dimension of the bounding box defines the S coordinates, - and the next longest defines the T coordinates. If two or all three dimensions of the bounding box are equal, - ties shall be broken by choosing the X, Y, or Z dimension in that order of preference. - The value of the S coordinate ranges from 0 to 1, from one end of the bounding box to the other. - The T coordinate ranges between 0 and the ratio of the second greatest dimension of the bounding box to the greatest dimension. - ''' - - # Note, S,T == U,V - # U gets longest, V gets second longest - xmin, ymin, zmin = ifs_points[0] - xmax, ymax, zmax = ifs_points[0] - for co in ifs_points: - x,y,z = co - if x < xmin: xmin = x - if y < ymin: ymin = y - if z < zmin: zmin = z - - if x > xmax: xmax = x - if y > ymax: ymax = y - if z > zmax: zmax = z - - xlen = xmax - xmin - ylen = ymax - ymin - zlen = zmax - zmin - - depth_min = xmin, ymin, zmin - depth_list = [xlen, ylen, zlen] - depth_sort = depth_list[:] - depth_sort.sort() - - depth_idx = [depth_list.index(val) for val in depth_sort] - - axis_u = depth_idx[-1] - axis_v = depth_idx[-2] # second longest - - # Hack, swap these !!! TODO - Why swap??? - it seems to work correctly but should not. - # axis_u,axis_v = axis_v,axis_u - - min_u = depth_min[axis_u] - min_v = depth_min[axis_v] - depth_u = depth_list[axis_u] - depth_v = depth_list[axis_v] - - depth_list[axis_u] - - if axis_u == axis_v: - # This should be safe because when 2 axies have the same length, the lower index will be used. - axis_v += 1 - - bpymesh.faceUV = True - - # HACK !!! - seems to be compatible with Cosmo though. - depth_v = depth_u = max(depth_v, depth_u) - - for f in bpymesh.faces: - f.image = bpyima - fuv = f.uv - - for i,v in enumerate(f): - co = v.co - fuv[i][:] = (co[axis_u]-min_u) / depth_u, (co[axis_v]-min_v) / depth_v - - # Add vcote - if vcolor: - # print ifs_vcol - bpymesh.vertexColors = True - - for f in bpymesh.faces: - fcol = f.col - if ifs_colorPerVertex: - fv = f.verts - for i,c in enumerate(fcol): - color_index = fv[i].index # color index is vert index - if ifs_color_index: - try: - color_index = ifs_color_index[color_index] - except: - print '\tWarning: per vertex color index out of range' - continue - - if color_index < len(ifs_vcol): - c.r, c.g, c.b = ifs_vcol[color_index] - else: - #print '\tWarning: per face color index out of range' - pass - else: - if vcolor_spot: # use 1 color, when ifs_vcol is [] - for c in fcol: - c.r, c.g, c.b = vcolor_spot - else: - color_index = faces_orig_index[f.index] # color index is face index - #print color_index, ifs_color_index - if ifs_color_index: - if color_index <= len(ifs_color_index): - print '\tWarning: per face color index out of range' - color_index = 0 - else: - color_index = ifs_color_index[color_index] - - - col = ifs_vcol[color_index] - for i,c in enumerate(fcol): - try: - c.r, c.g, c.b = col - except: - pass # incase its not between 0 and 255 - - bpymesh.verts.delete([0,]) # EEKADOODLE - - return bpymesh, ccw - -def importMesh_IndexedLineSet(geom, ancestry): - # VRML not x3d - #coord = geom.getChildByName('coord') # 'Coordinate' - coord = geom.getChildBySpec('Coordinate') # works for x3d and vrml - if coord: points = coord.getFieldAsArray('point', 3, ancestry) - else: points = [] - - if not points: - print '\tWarning: IndexedLineSet had no points' - return None - - ils_lines = geom.getFieldAsArray('coordIndex', 0, ancestry) - - lines = [] - line = [] - - for il in ils_lines: - if il==-1: - lines.append(line) - line = [] - else: - line.append(int(il)) - lines.append(line) - - # vcolor = geom.getChildByName('color') # blender dosnt have per vertex color - - bpycurve = bpy.data.curves.new('IndexedCurve', 'Curve') - bpycurve.setFlag(1) - - w=t=1 - - curve_index = 0 - - for line in lines: - if not line: - continue - co = points[line[0]] - bpycurve.appendNurb([co[0], co[1], co[2], w, t]) - bpycurve[curve_index].type= 0 # Poly Line - - for il in line[1:]: - co = points[il] - bpycurve.appendPoint(curve_index, [co[0], co[1], co[2], w]) - - - curve_index += 1 - - return bpycurve - - -def importMesh_PointSet(geom, ancestry): - # VRML not x3d - #coord = geom.getChildByName('coord') # 'Coordinate' - coord = geom.getChildBySpec('Coordinate') # works for x3d and vrml - if coord: points = coord.getFieldAsArray('point', 3, ancestry) - else: points = [] - - # vcolor = geom.getChildByName('color') # blender dosnt have per vertex color - - bpymesh = bpy.data.meshes.new() - bpymesh.verts.extend(points) - bpymesh.calcNormals() # will just be dummy normals - return bpymesh - -GLOBALS['CIRCLE_DETAIL'] = 12 - -MATRIX_Z_TO_Y = RotationMatrix(90, 4, 'x') - -def importMesh_Sphere(geom, ancestry): - # bpymesh = bpy.data.meshes.new() - diameter = geom.getFieldAsFloat('radius', 0.5, ancestry) * 2 # * 2 for the diameter - bpymesh = Mesh.Primitives.UVsphere(GLOBALS['CIRCLE_DETAIL'], GLOBALS['CIRCLE_DETAIL'], diameter) - bpymesh.transform(MATRIX_Z_TO_Y) - return bpymesh - -def importMesh_Cylinder(geom, ancestry): - # bpymesh = bpy.data.meshes.new() - diameter = geom.getFieldAsFloat('radius', 1.0, ancestry) * 2 # * 2 for the diameter - height = geom.getFieldAsFloat('height', 2, ancestry) - bpymesh = Mesh.Primitives.Cylinder(GLOBALS['CIRCLE_DETAIL'], diameter, height) - bpymesh.transform(MATRIX_Z_TO_Y) - - # Warning - Rely in the order Blender adds verts - # not nice design but wont change soon. - - bottom = geom.getFieldAsBool('bottom', True, ancestry) - side = geom.getFieldAsBool('side', True, ancestry) - top = geom.getFieldAsBool('top', True, ancestry) - - if not top: # last vert is top center of tri fan. - bpymesh.verts.delete([(GLOBALS['CIRCLE_DETAIL']+GLOBALS['CIRCLE_DETAIL'])+1]) - - if not bottom: # second last vert is bottom of triangle fan - bpymesh.verts.delete([GLOBALS['CIRCLE_DETAIL']+GLOBALS['CIRCLE_DETAIL']]) - - if not side: - # remove all quads - bpymesh.faces.delete(1, [f for f in bpymesh.faces if len(f)==4]) - - return bpymesh - -def importMesh_Cone(geom, ancestry): - # bpymesh = bpy.data.meshes.new() - diameter = geom.getFieldAsFloat('bottomRadius', 1.0, ancestry) * 2 # * 2 for the diameter - height = geom.getFieldAsFloat('height', 2, ancestry) - bpymesh = Mesh.Primitives.Cone(GLOBALS['CIRCLE_DETAIL'], diameter, height) - bpymesh.transform(MATRIX_Z_TO_Y) - - # Warning - Rely in the order Blender adds verts - # not nice design but wont change soon. - - bottom = geom.getFieldAsBool('bottom', True, ancestry) - side = geom.getFieldAsBool('side', True, ancestry) - - if not bottom: # last vert is on the bottom - bpymesh.verts.delete([GLOBALS['CIRCLE_DETAIL']+1]) - if not side: # second last vert is on the pointy bit of the cone - bpymesh.verts.delete([GLOBALS['CIRCLE_DETAIL']]) - - return bpymesh - -def importMesh_Box(geom, ancestry): - # bpymesh = bpy.data.meshes.new() - - size = geom.getFieldAsFloatTuple('size', (2.0, 2.0, 2.0), ancestry) - bpymesh = Mesh.Primitives.Cube(1.0) - - # Scale the box to the size set - scale_mat = Matrix([size[0],0,0], [0, size[1], 0], [0, 0, size[2]]) - bpymesh.transform(scale_mat.resize4x4()) - - return bpymesh - -def importShape(node, ancestry): - vrmlname = node.getDefName() - if not vrmlname: vrmlname = 'Shape' - - # works 100% in vrml, but not x3d - #appr = node.getChildByName('appearance') # , 'Appearance' - #geom = node.getChildByName('geometry') # , 'IndexedFaceSet' - - # Works in vrml and x3d - appr = node.getChildBySpec('Appearance') - geom = node.getChildBySpec(['IndexedFaceSet', 'IndexedLineSet', 'PointSet', 'Sphere', 'Box', 'Cylinder', 'Cone']) - - # For now only import IndexedFaceSet's - if geom: - bpymat = None - bpyima = None - texmtx = None - - depth = 0 # so we can set alpha face flag later - - if appr: - - #mat = appr.getChildByName('material') # 'Material' - #ima = appr.getChildByName('texture') # , 'ImageTexture' - #if ima and ima.getSpec() != 'ImageTexture': - # print '\tWarning: texture type "%s" is not supported' % ima.getSpec() - # ima = None - # textx = appr.getChildByName('textureTransform') - - mat = appr.getChildBySpec('Material') - ima = appr.getChildBySpec('ImageTexture') - - textx = appr.getChildBySpec('TextureTransform') - - if textx: - texmtx = translateTexTransform(textx, ancestry) - - - - # print mat, ima - if mat or ima: - - if not mat: - mat = ima # This is a bit dumb, but just means we use default values for all - - # all values between 0.0 and 1.0, defaults from VRML docs - bpymat = bpy.data.materials.new() - bpymat.amb = mat.getFieldAsFloat('ambientIntensity', 0.2, ancestry) - bpymat.rgbCol = mat.getFieldAsFloatTuple('diffuseColor', [0.8, 0.8, 0.8], ancestry) - - # NOTE - blender dosnt support emmisive color - # Store in mirror color and approximate with emit. - emit = mat.getFieldAsFloatTuple('emissiveColor', [0.0, 0.0, 0.0], ancestry) - bpymat.mirCol = emit - bpymat.emit = (emit[0]+emit[1]+emit[2])/3.0 - - bpymat.hard = int(1+(510*mat.getFieldAsFloat('shininess', 0.2, ancestry))) # 0-1 -> 1-511 - bpymat.specCol = mat.getFieldAsFloatTuple('specularColor', [0.0, 0.0, 0.0], ancestry) - bpymat.alpha = 1.0 - mat.getFieldAsFloat('transparency', 0.0, ancestry) - if bpymat.alpha < 0.999: - bpymat.mode |= Material.Modes.ZTRANSP - - - if ima: - - ima_url = ima.getFieldAsString('url', None, ancestry) - - if ima_url==None: - try: ima_url = ima.getFieldAsStringArray('url', ancestry)[0] # in some cases we get a list of images. - except: ima_url = None - - if ima_url==None: - print "\twarning, image with no URL, this is odd" - else: - bpyima= BPyImage.comprehensiveImageLoad(ima_url, dirName(node.getFilename()), PLACE_HOLDER= False, RECURSIVE= False, CONVERT_CALLBACK= imageConvertCompat) - if bpyima: - texture= bpy.data.textures.new() - texture.setType('Image') - texture.image = bpyima - - # Adds textures for materials (rendering) - try: depth = bpyima.depth - except: depth = -1 - - if depth == 32: - # Image has alpha - bpymat.setTexture(0, texture, Texture.TexCo.UV, Texture.MapTo.COL | Texture.MapTo.ALPHA) - texture.setImageFlags('MipMap', 'InterPol', 'UseAlpha') - bpymat.mode |= Material.Modes.ZTRANSP - bpymat.alpha = 0.0 - else: - bpymat.setTexture(0, texture, Texture.TexCo.UV, Texture.MapTo.COL) - - ima_repS = ima.getFieldAsBool('repeatS', True, ancestry) - ima_repT = ima.getFieldAsBool('repeatT', True, ancestry) - - # To make this work properly we'd need to scale the UV's too, better to ignore th - # texture.repeat = max(1, ima_repS * 512), max(1, ima_repT * 512) - - if not ima_repS: bpyima.clampX = True - if not ima_repT: bpyima.clampY = True - - bpydata = None - geom_spec = geom.getSpec() - ccw = True - if geom_spec == 'IndexedFaceSet': - bpydata, ccw = importMesh_IndexedFaceSet(geom, bpyima, ancestry) - elif geom_spec == 'IndexedLineSet': - bpydata = importMesh_IndexedLineSet(geom, ancestry) - elif geom_spec == 'PointSet': - bpydata = importMesh_PointSet(geom, ancestry) - elif geom_spec == 'Sphere': - bpydata = importMesh_Sphere(geom, ancestry) - elif geom_spec == 'Box': - bpydata = importMesh_Box(geom, ancestry) - elif geom_spec == 'Cylinder': - bpydata = importMesh_Cylinder(geom, ancestry) - elif geom_spec == 'Cone': - bpydata = importMesh_Cone(geom, ancestry) - else: - print '\tWarning: unsupported type "%s"' % geom_spec - return - - if bpydata: - vrmlname = vrmlname + geom_spec - - bpydata.name = vrmlname - - bpyob = node.blendObject = bpy.data.scenes.active.objects.new(bpydata) - - if type(bpydata) == Types.MeshType: - is_solid = geom.getFieldAsBool('solid', True, ancestry) - creaseAngle = geom.getFieldAsFloat('creaseAngle', None, ancestry) - - if creaseAngle != None: - bpydata.maxSmoothAngle = 1+int(min(79, creaseAngle * RAD_TO_DEG)) - bpydata.mode |= Mesh.Modes.AUTOSMOOTH - - # Only ever 1 material per shape - if bpymat: bpydata.materials = [bpymat] - - if bpydata.faceUV: - - if depth==32: # set the faces alpha flag? - transp = Mesh.FaceTranspModes.ALPHA - for f in bpydata.faces: - f.transp = transp - - if texmtx: - # Apply texture transform? - uv_copy = Vector() - for f in bpydata.faces: - for uv in f.uv: - uv_copy.x = uv.x - uv_copy.y = uv.y - - uv.x, uv.y = (uv_copy * texmtx)[0:2] - # Done transforming the texture - - - # Must be here and not in IndexedFaceSet because it needs an object for the flip func. Messy :/ - if not ccw: bpydata.flipNormals() - - - # else could be a curve for example - - - - # Can transform data or object, better the object so we can instance the data - #bpymesh.transform(getFinalMatrix(node)) - bpyob.setMatrix( getFinalMatrix(node, None, ancestry) ) - - -def importLamp_PointLight(node, ancestry): - vrmlname = node.getDefName() - if not vrmlname: vrmlname = 'PointLight' - - # ambientIntensity = node.getFieldAsFloat('ambientIntensity', 0.0, ancestry) # TODO - # attenuation = node.getFieldAsFloatTuple('attenuation', (1.0, 0.0, 0.0), ancestry) # TODO - color = node.getFieldAsFloatTuple('color', (1.0, 1.0, 1.0), ancestry) - intensity = node.getFieldAsFloat('intensity', 1.0, ancestry) # max is documented to be 1.0 but some files have higher. - location = node.getFieldAsFloatTuple('location', (0.0, 0.0, 0.0), ancestry) - # is_on = node.getFieldAsBool('on', True, ancestry) # TODO - radius = node.getFieldAsFloat('radius', 100.0, ancestry) - - bpylamp = bpy.data.lamps.new() - bpylamp.setType('Lamp') - bpylamp.energy = intensity - bpylamp.dist = radius - bpylamp.col = color - - mtx = TranslationMatrix(Vector(location)) - - return bpylamp, mtx - -def importLamp_DirectionalLight(node, ancestry): - vrmlname = node.getDefName() - if not vrmlname: vrmlname = 'DirectLight' - - # ambientIntensity = node.getFieldAsFloat('ambientIntensity', 0.0) # TODO - color = node.getFieldAsFloatTuple('color', (1.0, 1.0, 1.0), ancestry) - direction = node.getFieldAsFloatTuple('direction', (0.0, 0.0, -1.0), ancestry) - intensity = node.getFieldAsFloat('intensity', 1.0, ancestry) # max is documented to be 1.0 but some files have higher. - # is_on = node.getFieldAsBool('on', True, ancestry) # TODO - - bpylamp = bpy.data.lamps.new(vrmlname) - bpylamp.setType('Sun') - bpylamp.energy = intensity - bpylamp.col = color - - # lamps have their direction as -z, yup - mtx = Vector(direction).toTrackQuat('-z', 'y').toMatrix().resize4x4() - - return bpylamp, mtx - -# looks like default values for beamWidth and cutOffAngle were swapped in VRML docs. - -def importLamp_SpotLight(node, ancestry): - vrmlname = node.getDefName() - if not vrmlname: vrmlname = 'SpotLight' - - # ambientIntensity = geom.getFieldAsFloat('ambientIntensity', 0.0, ancestry) # TODO - # attenuation = geom.getFieldAsFloatTuple('attenuation', (1.0, 0.0, 0.0), ancestry) # TODO - beamWidth = node.getFieldAsFloat('beamWidth', 1.570796, ancestry) * RAD_TO_DEG # max is documented to be 1.0 but some files have higher. - color = node.getFieldAsFloatTuple('color', (1.0, 1.0, 1.0), ancestry) - cutOffAngle = node.getFieldAsFloat('cutOffAngle', 0.785398, ancestry) * RAD_TO_DEG # max is documented to be 1.0 but some files have higher. - direction = node.getFieldAsFloatTuple('direction', (0.0, 0.0, -1.0), ancestry) - intensity = node.getFieldAsFloat('intensity', 1.0, ancestry) # max is documented to be 1.0 but some files have higher. - location = node.getFieldAsFloatTuple('location', (0.0, 0.0, 0.0), ancestry) - # is_on = node.getFieldAsBool('on', True, ancestry) # TODO - radius = node.getFieldAsFloat('radius', 100.0, ancestry) - - bpylamp = bpy.data.lamps.new(vrmlname) - bpylamp.setType('Spot') - bpylamp.energy = intensity - bpylamp.dist = radius - bpylamp.col = color - bpylamp.spotSize = cutOffAngle - if beamWidth > cutOffAngle: - bpylamp.spotBlend = 0.0 - else: - if cutOffAngle==0.0: #@#$%^&*(!!! - this should never happen - bpylamp.spotBlend = 0.5 - else: - bpylamp.spotBlend = beamWidth / cutOffAngle - - # Convert - - # lamps have their direction as -z, y==up - mtx = Vector(direction).toTrackQuat('-z', 'y').toMatrix().resize4x4() * TranslationMatrix(Vector(location)) - - return bpylamp, mtx - - -def importLamp(node, spec, ancestry): - if spec=='PointLight': - bpylamp,mtx = importLamp_PointLight(node, ancestry) - elif spec=='DirectionalLight': - bpylamp,mtx = importLamp_DirectionalLight(node, ancestry) - elif spec=='SpotLight': - bpylamp,mtx = importLamp_SpotLight(node, ancestry) - else: - print "Error, not a lamp" - raise ValueError - - bpyob = node.blendObject = bpy.data.scenes.active.objects.new(bpylamp) - bpyob.setMatrix( getFinalMatrix(node, mtx, ancestry) ) - - -def importViewpoint(node, ancestry): - name = node.getDefName() - if not name: name = 'Viewpoint' - - fieldOfView = node.getFieldAsFloat('fieldOfView', 0.785398, ancestry) * RAD_TO_DEG # max is documented to be 1.0 but some files have higher. - # jump = node.getFieldAsBool('jump', True, ancestry) - orientation = node.getFieldAsFloatTuple('orientation', (0.0, 0.0, 1.0, 0.0), ancestry) - position = node.getFieldAsFloatTuple('position', (0.0, 0.0, 0.0), ancestry) - description = node.getFieldAsString('description', '', ancestry) - - bpycam = bpy.data.cameras.new(name) - - bpycam.angle = fieldOfView - - mtx = translateRotation(orientation) * TranslationMatrix(Vector(position)) - - - bpyob = node.blendObject = bpy.data.scenes.active.objects.new(bpycam) - bpyob.setMatrix( getFinalMatrix(node, mtx, ancestry) ) - - -def importTransform(node, ancestry): - name = node.getDefName() - if not name: name = 'Transform' - - bpyob = node.blendObject = bpy.data.scenes.active.objects.new('Empty', name) # , name) - bpyob.setMatrix( getFinalMatrix(node, None, ancestry) ) - - # so they are not too annoying - bpyob.emptyShape= Blender.Object.EmptyShapes.AXES - bpyob.drawSize= 0.2 - - -#def importTimeSensor(node): - - -def translatePositionInterpolator(node, ipo, ancestry): - key = node.getFieldAsArray('key', 0, ancestry) - keyValue = node.getFieldAsArray('keyValue', 3, ancestry) - - try: - loc_x = ipo.addCurve('LocX') - loc_y = ipo.addCurve('LocY') - loc_z = ipo.addCurve('LocZ') - except ValueError: - return - - loc_x.interpolation = loc_y.interpolation = loc_z.interpolation = Blender.IpoCurve.InterpTypes.LINEAR - - for i, time in enumerate(key): - try: x,y,z = keyValue[i] - except: continue - - loc_x.append((time,x)) - loc_y.append((time,y)) - loc_z.append((time,z)) - -def translateOrientationInterpolator(node, ipo, ancestry): - key = node.getFieldAsArray('key', 0, ancestry) - keyValue = node.getFieldAsArray('keyValue', 4, ancestry) - - try: - rot_x = ipo.addCurve('RotX') - rot_y = ipo.addCurve('RotY') - rot_z = ipo.addCurve('RotZ') - except ValueError: - return - - rot_x.interpolation = rot_y.interpolation = rot_z.interpolation = Blender.IpoCurve.InterpTypes.LINEAR - - for i, time in enumerate(key): - try: x,y,z,w = keyValue[i] - except: continue - - mtx = translateRotation((x,y,z,w)) - eul = mtx.toEuler() - rot_x.append((time,eul.x/10.0)) - rot_y.append((time,eul.y/10.0)) - rot_z.append((time,eul.z/10.0)) - -# Untested! -def translateScalarInterpolator(node, ipo, ancestry): - key = node.getFieldAsArray('key', 0, ancestry) - keyValue = node.getFieldAsArray('keyValue', 4, ancestry) - - try: - sca_x = ipo.addCurve('ScaleX') - sca_y = ipo.addCurve('ScaleY') - sca_z = ipo.addCurve('ScaleZ') - except ValueError: - return - - sca_x.interpolation = sca_y.interpolation = sca_z.interpolation = Blender.IpoCurve.InterpTypes.LINEAR - - for i, time in enumerate(key): - try: x,y,z = keyValue[i] - except: continue - sca_x.append((time,x/10.0)) - sca_y.append((time,y/10.0)) - sca_z.append((time,z/10.0)) - -def translateTimeSensor(node, ipo, ancestry): - ''' - Apply a time sensor to an IPO, VRML has many combinations of loop/start/stop/cycle times - to give different results, for now just do the basics - ''' - - time_cu = ipo.addCurve('Time') - time_cu.interpolation = Blender.IpoCurve.InterpTypes.LINEAR - - cycleInterval = node.getFieldAsFloat('cycleInterval', None, ancestry) - - startTime = node.getFieldAsFloat('startTime', 0.0, ancestry) - stopTime = node.getFieldAsFloat('stopTime', 250.0, ancestry) - - if cycleInterval != None: - stopTime = startTime+cycleInterval - - loop = node.getFieldAsBool('loop', False, ancestry) - - time_cu.append((1+startTime, 0.0)) - time_cu.append((1+stopTime, 1.0/10.0))# anoying, the UI uses /10 - - - if loop: - time_cu.extend = Blender.IpoCurve.ExtendTypes.CYCLIC # or - EXTRAP, CYCLIC_EXTRAP, CONST, - - -def importRoute(node, ancestry): - ''' - Animation route only at the moment - ''' - - if not hasattr(node, 'fields'): - return - - routeIpoDict = node.getRouteIpoDict() - - def getIpo(id): - try: ipo = routeIpoDict[id] - except: ipo = routeIpoDict[id] = bpy.data.ipos.new('web3d_ipo', 'Object') - return ipo - - # for getting definitions - defDict = node.getDefDict() - ''' - Handles routing nodes to eachother - -ROUTE vpPI.value_changed TO champFly001.set_position -ROUTE vpOI.value_changed TO champFly001.set_orientation -ROUTE vpTs.fraction_changed TO vpPI.set_fraction -ROUTE vpTs.fraction_changed TO vpOI.set_fraction -ROUTE champFly001.bindTime TO vpTs.set_startTime - ''' - - #from_id, from_type = node.id[1].split('.') - #to_id, to_type = node.id[3].split('.') - - #value_changed - set_position_node = None - set_orientation_node = None - time_node = None - - for field in node.fields: - if field and field[0]=='ROUTE': - try: - from_id, from_type = field[1].split('.') - to_id, to_type = field[3].split('.') - except: - print "Warning, invalid ROUTE", field - continue - - if from_type == 'value_changed': - if to_type == 'set_position': - ipo = getIpo(to_id) - set_data_from_node = defDict[from_id] - translatePositionInterpolator(set_data_from_node, ipo, ancestry) - - if to_type in ('set_orientation', 'rotation'): - ipo = getIpo(to_id) - set_data_from_node = defDict[from_id] - translateOrientationInterpolator(set_data_from_node, ipo, ancestry) - - if to_type == 'set_scale': - ipo = getIpo(to_id) - set_data_from_node = defDict[from_id] - translateScalarInterpolator(set_data_from_node, ipo, ancestry) - - elif from_type =='bindTime': - ipo = getIpo(from_id) - time_node = defDict[to_id] - translateTimeSensor(time_node, ipo, ancestry) - - - - -def load_web3d(path, PREF_FLAT=False, PREF_CIRCLE_DIV=16, HELPER_FUNC = None): - - # Used when adding blender primitives - GLOBALS['CIRCLE_DETAIL'] = PREF_CIRCLE_DIV - - #root_node = vrml_parse('/_Cylinder.wrl') - if path.lower().endswith('.x3d'): - root_node, msg = x3d_parse(path) - else: - root_node, msg = vrml_parse(path) - - if not root_node: - if Blender.mode == 'background': - print msg - else: - Blender.Draw.PupMenu(msg) - return - - - # fill with tuples - (node, [parents-parent, parent]) - all_nodes = root_node.getSerialized([], []) - - for node, ancestry in all_nodes: - #if 'castle.wrl' not in node.getFilename(): - # continue - - spec = node.getSpec() - ''' - prefix = node.getPrefix() - if prefix=='PROTO': - pass - else - ''' - if HELPER_FUNC and HELPER_FUNC(node, ancestry): - # Note, include this function so the VRML/X3D importer can be extended - # by an external script. - gets first pick - pass - if spec=='Shape': - importShape(node, ancestry) - elif spec in ('PointLight', 'DirectionalLight', 'SpotLight'): - importLamp(node, spec, ancestry) - elif spec=='Viewpoint': - importViewpoint(node, ancestry) - elif spec=='Transform': - # Only use transform nodes when we are not importing a flat object hierarchy - if PREF_FLAT==False: - importTransform(node, ancestry) - ''' - # These are delt with later within importRoute - elif spec=='PositionInterpolator': - ipo = bpy.data.ipos.new('web3d_ipo', 'Object') - translatePositionInterpolator(node, ipo) - ''' - - - - # After we import all nodes, route events - anim paths - for node, ancestry in all_nodes: - importRoute(node, ancestry) - - for node, ancestry in all_nodes: - if node.isRoot(): - # we know that all nodes referenced from will be in - # routeIpoDict so no need to run node.getDefDict() for every node. - routeIpoDict = node.getRouteIpoDict() - defDict = node.getDefDict() - - for key, ipo in routeIpoDict.iteritems(): - - # Assign anim curves - node = defDict[key] - if node.blendObject==None: # Add an object if we need one for animation - node.blendObject = bpy.data.scenes.active.objects.new('Empty', 'AnimOb') # , name) - - node.blendObject.setIpo(ipo) - - - - # Add in hierarchy - if PREF_FLAT==False: - child_dict = {} - for node, ancestry in all_nodes: - if node.blendObject: - blendObject = None - - # Get the last parent - i = len(ancestry) - while i: - i-=1 - blendObject = ancestry[i].blendObject - if blendObject: - break - - if blendObject: - # Parent Slow, - 1 liner but works - # blendObject.makeParent([node.blendObject], 0, 1) - - # Parent FAST - try: child_dict[blendObject].append(node.blendObject) - except: child_dict[blendObject] = [node.blendObject] - - # Parent FAST - for parent, children in child_dict.iteritems(): - parent.makeParent(children, 0, 1) - - # update deps - bpy.data.scenes.active.update(1) - del child_dict - - -def load_ui(path): - Draw = Blender.Draw - PREF_HIERARCHY= Draw.Create(0) - PREF_CIRCLE_DIV= Draw.Create(16) - - # Get USER Options - pup_block= [\ - 'Import...',\ - ('Hierarchy', PREF_HIERARCHY, 'Import transform nodes as empties to create a parent/child hierarchy'),\ - ('Circle Div:', PREF_CIRCLE_DIV, 3, 128, 'Number of divisions to use for circular primitives') - ] - - if not Draw.PupBlock('Import X3D/VRML...', pup_block): - return - - Window.WaitCursor(1) - - load_web3d(path,\ - (not PREF_HIERARCHY.val),\ - PREF_CIRCLE_DIV.val,\ - ) - - Window.WaitCursor(0) - - -if __name__ == '__main__': - Window.FileSelector(load_ui, 'Import X3D/VRML97') - - -# Testing stuff - -# load_web3d('/test.x3d') -# load_web3d('/_Cylinder.x3d') - -# Testing below -# load_web3d('m:\\root\\Desktop\\_Cylinder.wrl') -# load_web3d('/_Cylinder.wrl') -# load_web3d('/fe/wrl/Vrml/EGS/BCKGD.WRL') - -# load_web3d('/fe/wrl/Vrml/EGS/GRNDPLNE.WRL') -# load_web3d('/fe/wrl/Vrml/EGS/INDEXFST.WRL') -# load_web3d('/fe/wrl/panel1c.wrl') -# load_web3d('/test.wrl') -# load_web3d('/fe/wrl/dulcimer.wrl') -# load_web3d('/fe/wrl/rccad/Ju-52.wrl') # Face index out of range -# load_web3d('/fe/wrl/16lat.wrl') # spotlight -# load_web3d('/fe/wrl/Vrml/EGS/FOG.WRL') # spotlight -# load_web3d('/fe/wrl/Vrml/EGS/LOD.WRL') # vcolor per face - -# load_web3d('/fe/wrl/new/daybreak_final.wrl') # no faces in mesh, face duplicate error -# load_web3d('/fe/wrl/new/earth.wrl') -# load_web3d('/fe/wrl/new/hendrix.ei.dtu.dk/vrml/talairach/fourd/TalaDruryRight.wrl') # define/use fields -# load_web3d('/fe/wrl/new/imac.wrl') # extrusion and define/use fields, face index is a float somehow -# load_web3d('/fe/wrl/new/www.igs.net/~mascott/vrml/vrml2/mcastle.wrl') -# load_web3d('/fe/wrl/new/www.igs.net/~mascott/vrml/vrml2/tower.wrl') -# load_web3d('/fe/wrl/new/www.igs.net/~mascott/vrml/vrml2/temple.wrl') -# load_web3d('/fe/wrl/brain.wrl') # field define test 'a IS b' -# load_web3d('/fe/wrl/new/coaster.wrl') # fields that are confusing to read. - -# X3D - -# load_web3d('/fe/x3d/www.web3d.org/x3d/content/examples/Basic/StudentProjects/PlayRoom.x3d') # invalid UVs - - - -def test(): - import os - - files = os.popen('find /fe/wrl -iname "*.wrl"').readlines() - # files = os.popen('find /fe/x3d -iname "*.x3d"').readlines() - # files = os.popen('find /fe/x3d/X3dExamplesSavage -iname "*.x3d"').readlines() - - files.sort() - tot = len(files) - for i, f in enumerate(files): - if i < 124 or i > 1000000: - continue - - #if i != 1068: - # continue - - #if i != 12686: - # continue - - f = f.strip() - print f, i, tot - sce = bpy.data.scenes.new(str(i) + '_' + f.split('/')[-1]) - bpy.data.scenes.active = sce - # Window. - load_web3d(f, PREF_FLAT=True) - -# test() diff --git a/release/io/engine_render_pov.py b/release/scripts/io/engine_render_pov.py index f0247ce532a..f0247ce532a 100644 --- a/release/io/engine_render_pov.py +++ b/release/scripts/io/engine_render_pov.py diff --git a/release/io/export_3ds.py b/release/scripts/io/export_3ds.py index 19c12146769..19c12146769 100644 --- a/release/io/export_3ds.py +++ b/release/scripts/io/export_3ds.py diff --git a/release/io/export_fbx.py b/release/scripts/io/export_fbx.py index aa65473b8d6..aa65473b8d6 100644 --- a/release/io/export_fbx.py +++ b/release/scripts/io/export_fbx.py diff --git a/release/io/export_obj.py b/release/scripts/io/export_obj.py index e2ac78798bd..e2ac78798bd 100644 --- a/release/io/export_obj.py +++ b/release/scripts/io/export_obj.py diff --git a/release/io/export_ply.py b/release/scripts/io/export_ply.py index 8e79c3741bb..8e79c3741bb 100644 --- a/release/io/export_ply.py +++ b/release/scripts/io/export_ply.py diff --git a/release/io/export_x3d.py b/release/scripts/io/export_x3d.py index f23ccf8d2dc..f23ccf8d2dc 100644 --- a/release/io/export_x3d.py +++ b/release/scripts/io/export_x3d.py diff --git a/release/io/import_3ds.py b/release/scripts/io/import_3ds.py index 99825471764..99825471764 100644 --- a/release/io/import_3ds.py +++ b/release/scripts/io/import_3ds.py diff --git a/release/io/import_obj.py b/release/scripts/io/import_obj.py index 9a00dc1cc2a..9a00dc1cc2a 100644 --- a/release/io/import_obj.py +++ b/release/scripts/io/import_obj.py diff --git a/release/io/netrender/__init__.py b/release/scripts/io/netrender/__init__.py index 4a1dd2238e3..4a1dd2238e3 100644 --- a/release/io/netrender/__init__.py +++ b/release/scripts/io/netrender/__init__.py diff --git a/release/io/netrender/balancing.py b/release/scripts/io/netrender/balancing.py index 637dd5ff92e..637dd5ff92e 100644 --- a/release/io/netrender/balancing.py +++ b/release/scripts/io/netrender/balancing.py diff --git a/release/io/netrender/client.py b/release/scripts/io/netrender/client.py index 65b2937867f..65b2937867f 100644 --- a/release/io/netrender/client.py +++ b/release/scripts/io/netrender/client.py diff --git a/release/io/netrender/master.py b/release/scripts/io/netrender/master.py index a3e186a9cfd..a3e186a9cfd 100644 --- a/release/io/netrender/master.py +++ b/release/scripts/io/netrender/master.py diff --git a/release/io/netrender/master_html.py b/release/scripts/io/netrender/master_html.py index 6a956a70e9f..6a956a70e9f 100644 --- a/release/io/netrender/master_html.py +++ b/release/scripts/io/netrender/master_html.py diff --git a/release/io/netrender/model.py b/release/scripts/io/netrender/model.py index be97f8d0a81..be97f8d0a81 100644 --- a/release/io/netrender/model.py +++ b/release/scripts/io/netrender/model.py diff --git a/release/io/netrender/operators.py b/release/scripts/io/netrender/operators.py index 42d1f6a0b86..42d1f6a0b86 100644 --- a/release/io/netrender/operators.py +++ b/release/scripts/io/netrender/operators.py diff --git a/release/io/netrender/slave.py b/release/scripts/io/netrender/slave.py index 657e31001e0..657e31001e0 100644 --- a/release/io/netrender/slave.py +++ b/release/scripts/io/netrender/slave.py diff --git a/release/io/netrender/ui.py b/release/scripts/io/netrender/ui.py index 7681d4865e9..7681d4865e9 100644 --- a/release/io/netrender/ui.py +++ b/release/scripts/io/netrender/ui.py diff --git a/release/io/netrender/utils.py b/release/scripts/io/netrender/utils.py index 06393a738a0..06393a738a0 100644 --- a/release/io/netrender/utils.py +++ b/release/scripts/io/netrender/utils.py diff --git a/release/scripts/lightwave_export.py b/release/scripts/lightwave_export.py deleted file mode 100644 index bbfb9649c69..00000000000 --- a/release/scripts/lightwave_export.py +++ /dev/null @@ -1,707 +0,0 @@ -#!BPY - -""" -Name: 'LightWave (.lwo)...' -Blender: 243 -Group: 'Export' -Tooltip: 'Export selected meshes to LightWave File Format (.lwo)' -""" - -__author__ = "Anthony D'Agostino (Scorpius)" -__url__ = ("blender", "blenderartists.org", -"Author's homepage, http://www.redrival.com/scorpius") -__version__ = "Part of IOSuite 0.5" - -__bpydoc__ = """\ -This script exports meshes to LightWave file format. - -LightWave is a full-featured commercial modeling and rendering -application. The lwo file format is composed of 'chunks,' is well -defined, and easy to read and write. It is similar in structure to the -trueSpace cob format. - -Usage:<br> - Select meshes to be exported and run this script from "File->Export" menu. - -Supported:<br> - UV Coordinates, Meshes, Materials, Material Indices, Specular -Highlights, and Vertex Colors. For added functionality, each object is -placed on its own layer. Someone added the CLIP chunk and imagename support. - -Missing:<br> - Not too much, I hope! :). - -Known issues:<br> - Empty objects crash has been fixed. - -Notes:<br> - For compatibility reasons, it also reads lwo files in the old LW -v5.5 format. -""" - -# $Id$ -# -# +---------------------------------------------------------+ -# | Copyright (c) 2002 Anthony D'Agostino | -# | http://www.redrival.com/scorpius | -# | scorpius@netzero.com | -# | April 21, 2002 | -# | Read and write LightWave Object File Format (*.lwo) | -# +---------------------------------------------------------+ - -# ***** 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 ***** - -import Blender -import BPyMesh -try: import struct -except: struct = None -try: import cStringIO -except: cStringIO = None -try: import operator -except: operator = None - -VCOL_NAME = "\251 Per-Face Vertex Colors" -DEFAULT_NAME = "\251 Blender Default" -# ============================== -# === Write LightWave Format === -# ============================== -def write(filename): - start = Blender.sys.time() - file = open(filename, "wb") - - scn = Blender.Scene.GetCurrent() - objects = list(scn.objects.context) - - if not objects: - Blender.Draw.PupMenu('Error%t|No Objects selected') - return - - try: objects.sort( key = lambda a: a.name ) - except: objects.sort(lambda a,b: cmp(a.name, b.name)) - - text = generate_text() - desc = generate_desc() - icon = "" #generate_icon() - - meshes = [] - mesh_object_name_lookup = {} # for name lookups only - - for obj in objects: - mesh = BPyMesh.getMeshFromObject(obj, None, True, False, scn) - if mesh: - mesh.transform(obj.matrixWorld) - meshes.append(mesh) - mesh_object_name_lookup[mesh] = obj.name - del obj - - material_names = get_used_material_names(meshes) - tags = generate_tags(material_names) - surfs = generate_surfs(material_names) - chunks = [text, desc, icon, tags] - - meshdata = cStringIO.StringIO() - - layer_index = 0 - - for mesh in meshes: - layr = generate_layr(mesh_object_name_lookup[mesh], layer_index) - pnts = generate_pnts(mesh) - bbox = generate_bbox(mesh) - pols = generate_pols(mesh) - ptag = generate_ptag(mesh, material_names) - clip = generate_clip(mesh, material_names) - - if mesh.faceUV: - vmad_uv = generate_vmad_uv(mesh) # per face - - if mesh.vertexColors: - #if meshtools.average_vcols: - # vmap_vc = generate_vmap_vc(mesh) # per vert - #else: - vmad_vc = generate_vmad_vc(mesh) # per face - - write_chunk(meshdata, "LAYR", layr); chunks.append(layr) - write_chunk(meshdata, "PNTS", pnts); chunks.append(pnts) - write_chunk(meshdata, "BBOX", bbox); chunks.append(bbox) - write_chunk(meshdata, "POLS", pols); chunks.append(pols) - write_chunk(meshdata, "PTAG", ptag); chunks.append(ptag) - - if mesh.vertexColors: - #if meshtools.average_vcols: - # write_chunk(meshdata, "VMAP", vmap_vc) - # chunks.append(vmap_vc) - #else: - write_chunk(meshdata, "VMAD", vmad_vc) - chunks.append(vmad_vc) - - if mesh.faceUV: - write_chunk(meshdata, "VMAD", vmad_uv) - chunks.append(vmad_uv) - write_chunk(meshdata, "CLIP", clip) - chunks.append(clip) - - layer_index += 1 - mesh.verts = None # save some ram - - del mesh_object_name_lookup - - for surf in surfs: - chunks.append(surf) - - write_header(file, chunks) - write_chunk(file, "ICON", icon) - write_chunk(file, "TEXT", text) - write_chunk(file, "DESC", desc) - write_chunk(file, "TAGS", tags) - file.write(meshdata.getvalue()); meshdata.close() - for surf in surfs: - write_chunk(file, "SURF", surf) - write_chunk(file, "DATE", "August 19, 2005") - - Blender.Window.DrawProgressBar(1.0, "") # clear progressbar - file.close() - print '\a\r', - print "Successfully exported %s in %.3f seconds" % (filename.split('\\')[-1].split('/')[-1], Blender.sys.time() - start) - - -# ======================================= -# === Generate Null-Terminated String === -# ======================================= -def generate_nstring(string): - if len(string)%2 == 0: # even - string += "\0\0" - else: # odd - string += "\0" - return string - -# =============================== -# === Get Used Material Names === -# =============================== -def get_used_material_names(meshes): - matnames = {} - for mesh in meshes: - if (not mesh.materials) and mesh.vertexColors: - # vcols only - matnames[VCOL_NAME] = None - - elif mesh.materials and (not mesh.vertexColors): - # materials only - for material in mesh.materials: - if material: - matnames[material.name] = None - elif (not mesh.materials) and (not mesh.vertexColors): - # neither - matnames[DEFAULT_NAME] = None - else: - # both - for material in mesh.materials: - if material: - matnames[material.name] = None - return matnames.keys() - -# ========================================= -# === Generate Tag Strings (TAGS Chunk) === -# ========================================= -def generate_tags(material_names): - if material_names: - material_names = map(generate_nstring, material_names) - tags_data = reduce(operator.add, material_names) - else: - tags_data = generate_nstring(''); - return tags_data - -# ======================== -# === Generate Surface === -# ======================== -def generate_surface(name): - #if name.find("\251 Per-") == 0: - # return generate_vcol_surf(mesh) - if name == DEFAULT_NAME: - return generate_default_surf() - else: - return generate_surf(name) - -# ====================== -# === Generate Surfs === -# ====================== -def generate_surfs(material_names): - return map(generate_surface, material_names) - -# =================================== -# === Generate Layer (LAYR Chunk) === -# =================================== -def generate_layr(name, idx): - data = cStringIO.StringIO() - data.write(struct.pack(">h", idx)) # layer number - data.write(struct.pack(">h", 0)) # flags - data.write(struct.pack(">fff", 0, 0, 0)) # pivot - data.write(generate_nstring(name)) # name - return data.getvalue() - -# =================================== -# === Generate Verts (PNTS Chunk) === -# =================================== -def generate_pnts(mesh): - data = cStringIO.StringIO() - for i, v in enumerate(mesh.verts): - if not i%100: - Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Writing Verts") - x, y, z = v.co - data.write(struct.pack(">fff", x, z, y)) - return data.getvalue() - -# ========================================== -# === Generate Bounding Box (BBOX Chunk) === -# ========================================== -def generate_bbox(mesh): - data = cStringIO.StringIO() - # need to transform verts here - if mesh.verts: - nv = [v.co for v in mesh.verts] - xx = [ co[0] for co in nv ] - yy = [ co[1] for co in nv ] - zz = [ co[2] for co in nv ] - else: - xx = yy = zz = [0.0,] - - data.write(struct.pack(">6f", min(xx), min(zz), min(yy), max(xx), max(zz), max(yy))) - return data.getvalue() - -# ======================================== -# === Average All Vertex Colors (Fast) === -# ======================================== -''' -def average_vertexcolors(mesh): - vertexcolors = {} - vcolor_add = lambda u, v: [u[0]+v[0], u[1]+v[1], u[2]+v[2], u[3]+v[3]] - vcolor_div = lambda u, s: [u[0]/s, u[1]/s, u[2]/s, u[3]/s] - for i, f in enumerate(mesh.faces): # get all vcolors that share this vertex - if not i%100: - Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Finding Shared VColors") - col = f.col - for j in xrange(len(f)): - index = f[j].index - color = col[j] - r,g,b = color.r, color.g, color.b - vertexcolors.setdefault(index, []).append([r,g,b,255]) - i = 0 - for index, value in vertexcolors.iteritems(): # average them - if not i%100: - Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Averaging Vertex Colors") - vcolor = [0,0,0,0] # rgba - for v in value: - vcolor = vcolor_add(vcolor, v) - shared = len(value) - value[:] = vcolor_div(vcolor, shared) - i+=1 - return vertexcolors -''' - -# ==================================================== -# === Generate Per-Vert Vertex Colors (VMAP Chunk) === -# ==================================================== -# Blender now has all vcols per face -""" -def generate_vmap_vc(mesh): - data = cStringIO.StringIO() - data.write("RGB ") # type - data.write(struct.pack(">H", 3)) # dimension - data.write(generate_nstring("Blender's Vertex Colors")) # name - vertexcolors = average_vertexcolors(mesh) - for i in xrange(len(vertexcolors)): - try: r, g, b, a = vertexcolors[i] # has a face user - except: r, g, b, a = 255,255,255,255 - data.write(struct.pack(">H", i)) # vertex index - data.write(struct.pack(">fff", r/255.0, g/255.0, b/255.0)) - return data.getvalue() -""" - -# ==================================================== -# === Generate Per-Face Vertex Colors (VMAD Chunk) === -# ==================================================== -def generate_vmad_vc(mesh): - data = cStringIO.StringIO() - data.write("RGB ") # type - data.write(struct.pack(">H", 3)) # dimension - data.write(generate_nstring("Blender's Vertex Colors")) # name - for i, f in enumerate(mesh.faces): - if not i%100: - Blender.Window.DrawProgressBar(float(i)/len(mesh.faces), "Writing Vertex Colors") - col = f.col - f_v = f.v - for j in xrange(len(f)-1, -1, -1): # Reverse order - r,g,b, dummy = tuple(col[j]) - data.write(struct.pack(">H", f_v[j].index)) # vertex index - data.write(struct.pack(">H", i)) # face index - data.write(struct.pack(">fff", r/255.0, g/255.0, b/255.0)) - return data.getvalue() - -# ================================================ -# === Generate Per-Face UV Coords (VMAD Chunk) === -# ================================================ -def generate_vmad_uv(mesh): - layers = mesh.getUVLayerNames() - org_uv = mesh.activeUVLayer - for l in layers: - mesh.activeUVLayer = l - data = cStringIO.StringIO() - data.write("TXUV") # type - data.write(struct.pack(">H", 2)) # dimension - data.write(generate_nstring(l)) # name - for i, f in enumerate(mesh.faces): - if not i%100: - Blender.Window.DrawProgressBar(float(i)/len(mesh.faces), "Writing UV Coordinates") - - uv = f.uv - f_v = f.v - for j in xrange(len(f)-1, -1, -1): # Reverse order - U,V = uv[j] - v = f_v[j].index - data.write(struct.pack(">H", v)) # vertex index - data.write(struct.pack(">H", i)) # face index - data.write(struct.pack(">ff", U, V)) - - mesh.activeUVLayer = org_uv - return data.getvalue() - -# ====================================== -# === Generate Variable-Length Index === -# ====================================== -def generate_vx(index): - if index < 0xFF00: - value = struct.pack(">H", index) # 2-byte index - else: - value = struct.pack(">L", index | 0xFF000000) # 4-byte index - return value - -# =================================== -# === Generate Faces (POLS Chunk) === -# =================================== -def generate_pols(mesh): - data = cStringIO.StringIO() - data.write("FACE") # polygon type - for i,f in enumerate(mesh.faces): - if not i%100: - Blender.Window.DrawProgressBar(float(i)/len(mesh.faces), "Writing Faces") - data.write(struct.pack(">H", len(f))) # numfaceverts - numfaceverts = len(f) - f_v = f.v - for j in xrange(numfaceverts-1, -1, -1): # Reverse order - data.write(generate_vx(f_v[j].index)) - return data.getvalue() - -# ================================================= -# === Generate Polygon Tag Mapping (PTAG Chunk) === -# ================================================= -def generate_ptag(mesh, material_names): - - def surf_indicies(mat): - try: - if mat: - return material_names.index(mat.name) - except: - pass - - return 0 - - - data = cStringIO.StringIO() - data.write("SURF") # polygon tag type - mesh_materials = mesh.materials - mesh_surfindicies = [surf_indicies(mat) for mat in mesh_materials] - - try: VCOL_NAME_SURF_INDEX = material_names.index(VCOL_NAME) - except: VCOL_NAME_SURF_INDEX = 0 - - try: DEFAULT_NAME_SURF_INDEX = material_names.index(DEFAULT_NAME) - except: DEFAULT_NAME_SURF_INDEX = 0 - len_mat = len(mesh_materials) - for i, f in enumerate(mesh.faces): # numfaces - f_mat = f.mat - if f_mat >= len_mat: f_mat = 0 # Rare annoying eror - - - if not i%100: - Blender.Window.DrawProgressBar(float(i)/len(mesh.faces), "Writing Surface Indices") - - data.write(generate_vx(i)) - if (not mesh_materials) and mesh.vertexColors: # vcols only - surfidx = VCOL_NAME_SURF_INDEX - elif mesh_materials and not mesh.vertexColors: # materials only - surfidx = mesh_surfindicies[f_mat] - elif (not mesh_materials) and (not mesh.vertexColors): # neither - surfidx = DEFAULT_NAME_SURF_INDEX - else: # both - surfidx = mesh_surfindicies[f_mat] - - data.write(struct.pack(">H", surfidx)) # surface index - return data.getvalue() - -# =================================================== -# === Generate VC Surface Definition (SURF Chunk) === -# =================================================== -def generate_vcol_surf(mesh): - data = cStringIO.StringIO() - if mesh.vertexColors: - surface_name = generate_nstring(VCOL_NAME) - data.write(surface_name) - data.write("\0\0") - - data.write("COLR") - data.write(struct.pack(">H", 14)) - data.write(struct.pack(">fffH", 1, 1, 1, 0)) - - data.write("DIFF") - data.write(struct.pack(">H", 6)) - data.write(struct.pack(">fH", 0.0, 0)) - - data.write("LUMI") - data.write(struct.pack(">H", 6)) - data.write(struct.pack(">fH", 1.0, 0)) - - data.write("VCOL") - data.write(struct.pack(">H", 34)) - data.write(struct.pack(">fH4s", 1.0, 0, "RGB ")) # intensity, envelope, type - data.write(generate_nstring("Blender's Vertex Colors")) # name - - data.write("CMNT") # material comment - comment = "Vertex Colors: Exported from Blender\256 243" - comment = generate_nstring(comment) - data.write(struct.pack(">H", len(comment))) - data.write(comment) - return data.getvalue() - -# ================================================ -# === Generate Surface Definition (SURF Chunk) === -# ================================================ -def generate_surf(material_name): - data = cStringIO.StringIO() - data.write(generate_nstring(material_name)) - data.write("\0\0") - - try: - material = Blender.Material.Get(material_name) - R,G,B = material.R, material.G, material.B - ref = material.ref - emit = material.emit - spec = material.spec - hard = material.hard - - except: - material = None - - R=G=B = 1.0 - ref = 1.0 - emit = 0.0 - spec = 0.2 - hard = 0.0 - - - data.write("COLR") - data.write(struct.pack(">H", 14)) - data.write(struct.pack(">fffH", R, G, B, 0)) - - data.write("DIFF") - data.write(struct.pack(">H", 6)) - data.write(struct.pack(">fH", ref, 0)) - - data.write("LUMI") - data.write(struct.pack(">H", 6)) - data.write(struct.pack(">fH", emit, 0)) - - data.write("SPEC") - data.write(struct.pack(">H", 6)) - data.write(struct.pack(">fH", spec, 0)) - - data.write("GLOS") - data.write(struct.pack(">H", 6)) - gloss = hard / (255/2.0) - gloss = round(gloss, 1) - data.write(struct.pack(">fH", gloss, 0)) - - data.write("CMNT") # material comment - comment = material_name + ": Exported from Blender\256 243" - comment = generate_nstring(comment) - data.write(struct.pack(">H", len(comment))) - data.write(comment) - - # Check if the material contains any image maps - if material: - mtextures = material.getTextures() # Get a list of textures linked to the material - for mtex in mtextures: - if (mtex) and (mtex.tex.type == Blender.Texture.Types.IMAGE): # Check if the texture is of type "IMAGE" - data.write("BLOK") # Surface BLOK header - data.write(struct.pack(">H", 104)) # Hardcoded and ugly! Will only handle 1 image per material - - # IMAP subchunk (image map sub header) - data.write("IMAP") - data_tmp = cStringIO.StringIO() - data_tmp.write(struct.pack(">H", 0)) # Hardcoded - not sure what it represents - data_tmp.write("CHAN") - data_tmp.write(struct.pack(">H", 4)) - data_tmp.write("COLR") - data_tmp.write("OPAC") # Hardcoded texture layer opacity - data_tmp.write(struct.pack(">H", 8)) - data_tmp.write(struct.pack(">H", 0)) - data_tmp.write(struct.pack(">f", 1.0)) - data_tmp.write(struct.pack(">H", 0)) - data_tmp.write("ENAB") - data_tmp.write(struct.pack(">HH", 2, 1)) # 1 = texture layer enabled - data_tmp.write("NEGA") - data_tmp.write(struct.pack(">HH", 2, 0)) # Disable negative image (1 = invert RGB values) - data_tmp.write("AXIS") - data_tmp.write(struct.pack(">HH", 2, 1)) - data.write(struct.pack(">H", len(data_tmp.getvalue()))) - data.write(data_tmp.getvalue()) - - # IMAG subchunk - data.write("IMAG") - data.write(struct.pack(">HH", 2, 1)) - data.write("PROJ") - data.write(struct.pack(">HH", 2, 5)) # UV projection - - data.write("VMAP") - uvname = generate_nstring("Blender's UV Coordinates") - data.write(struct.pack(">H", len(uvname))) - data.write(uvname) - - return data.getvalue() - -# ============================================= -# === Generate Default Surface (SURF Chunk) === -# ============================================= -def generate_default_surf(): - data = cStringIO.StringIO() - material_name = DEFAULT_NAME - data.write(generate_nstring(material_name)) - data.write("\0\0") - - data.write("COLR") - data.write(struct.pack(">H", 14)) - data.write(struct.pack(">fffH", 1, 1, 1, 0)) - - data.write("DIFF") - data.write(struct.pack(">H", 6)) - data.write(struct.pack(">fH", 0.8, 0)) - - data.write("LUMI") - data.write(struct.pack(">H", 6)) - data.write(struct.pack(">fH", 0, 0)) - - data.write("SPEC") - data.write(struct.pack(">H", 6)) - data.write(struct.pack(">fH", 0.5, 0)) - - data.write("GLOS") - data.write(struct.pack(">H", 6)) - gloss = 50 / (255/2.0) - gloss = round(gloss, 1) - data.write(struct.pack(">fH", gloss, 0)) - - data.write("CMNT") # material comment - comment = material_name + ": Exported from Blender\256 243" - - # vals = map(chr, xrange(164,255,1)) - # keys = xrange(164,255,1) - # keys = map(lambda x: `x`, keys) - # comment = map(None, keys, vals) - # comment = reduce(operator.add, comment) - # comment = reduce(operator.add, comment) - - comment = generate_nstring(comment) - data.write(struct.pack(">H", len(comment))) - data.write(comment) - return data.getvalue() - -# ============================================ -# === Generate Object Comment (TEXT Chunk) === -# ============================================ -def generate_text(): - comment = "Lightwave Export Script for Blender by Anthony D'Agostino" - return generate_nstring(comment) - -# ============================================== -# === Generate Description Line (DESC Chunk) === -# ============================================== -def generate_desc(): - comment = "Copyright 2002 Scorpius Entertainment" - return generate_nstring(comment) - -# ================================================== -# === Generate Thumbnail Icon Image (ICON Chunk) === -# ================================================== -def generate_icon(): - data = cStringIO.StringIO() - file = open("f:/obj/radiosity/lwo2_icon.tga", "rb") # 60x60 uncompressed TGA - file.read(18) - icon_data = file.read(3600) # ? - file.close() - data.write(struct.pack(">HH", 0, 60)) - data.write(icon_data) - #print len(icon_data) - return data.getvalue() - -# =============================================== -# === Generate CLIP chunk with STIL subchunks === -# =============================================== -def generate_clip(mesh, material_names): - data = cStringIO.StringIO() - clipid = 1 - for i, material in enumerate(mesh.materials): # Run through list of materials used by mesh - if material: - mtextures = material.getTextures() # Get a list of textures linked to the material - for mtex in mtextures: - if (mtex) and (mtex.tex.type == Blender.Texture.Types.IMAGE): # Check if the texture is of type "IMAGE" - pathname = mtex.tex.image.filename # If full path is needed use filename in place of name - pathname = pathname[0:2] + pathname.replace("\\", "/")[3:] # Convert to Modo standard path - imagename = generate_nstring(pathname) - data.write(struct.pack(">L", clipid)) # CLIP sequence/id - data.write("STIL") # STIL image - data.write(struct.pack(">H", len(imagename))) # Size of image name - data.write(imagename) - clipid += 1 - return data.getvalue() - -# =================== -# === Write Chunk === -# =================== -def write_chunk(file, name, data): - file.write(name) - file.write(struct.pack(">L", len(data))) - file.write(data) - -# ============================= -# === Write LWO File Header === -# ============================= -def write_header(file, chunks): - chunk_sizes = map(len, chunks) - chunk_sizes = reduce(operator.add, chunk_sizes) - form_size = chunk_sizes + len(chunks)*8 + len("FORM") - file.write("FORM") - file.write(struct.pack(">L", form_size)) - file.write("LWO2") - -def fs_callback(filename): - if not filename.lower().endswith('.lwo'): filename += '.lwo' - write(filename) - -if struct and cStringIO and operator: - Blender.Window.FileSelector(fs_callback, "Export LWO", Blender.sys.makename(ext='.lwo')) -else: - Blender.Draw.PupMenu("Error%t|This script requires a full python installation") diff --git a/release/scripts/lightwave_import.py b/release/scripts/lightwave_import.py deleted file mode 100644 index 6d02467cef8..00000000000 --- a/release/scripts/lightwave_import.py +++ /dev/null @@ -1,1705 +0,0 @@ -#!BPY -""" -Name: 'LightWave (.lwo)...' -Blender: 239 -Group: 'Import' -Tooltip: 'Import LightWave Object File Format' -""" - -__author__ = ["Alessandro Pirovano, Anthony D'Agostino (Scorpius)", "Campbell Barton (ideasman42)", "ZanQdo"] -__url__ = ("www.blender.org", "blenderartist.org", -"Anthony's homepage, http://www.redrival.com/scorpius", "Alessandro's homepage, http://uaraus.altervista.org") - -importername = "lwo_import 0.4.0" - -# +---------------------------------------------------------+ -# | Save your work before and after use. | -# | Please report any useful comment to: | -# | uaraus-dem@yahoo.it | -# | Thanks | -# +---------------------------------------------------------+ -# +---------------------------------------------------------+ -# | Copyright (c) 2002 Anthony D'Agostino | -# | http://www.redrival.com/scorpius | -# | scorpius@netzero.com | -# | April 21, 2002 | -# | Import Export Suite v0.5 | -# +---------------------------------------------------------+ -# | Read and write LightWave Object File Format (*.lwo) | -# +---------------------------------------------------------+ -# +---------------------------------------------------------+ -# | Alessandro Pirovano tweaked starting on March 2005 | -# | http://uaraus.altervista.org | -# +---------------------------------------------------------+ -# +---------------------------------------------------------- -# | 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 -# +---------------------------------------------------------- -# +---------------------------------------------------------+ -# | Release log: | -# | 0.4.0 : Updated for blender 2.44 | -# | ZanQdo - made the mesh import the right way up | -# | Ideasman42 - Updated functions for the bew API | -# | as well as removing the text object class | -# | 0.2.2 : This code works with Blender 2.42 RC3 | -# | Added a new PolyFill function for BPYMesh's | -# | ngon() to use, checked compatibility | -# | lightwaves ngons are imported as fgons | -# | Checked compatibility against 1711 lwo files | -# | 0.2.1 : This code works with Blender 2.40 RC1 | -# | modified material mode assignment to deal with | -# | Python API modification | -# | Changed script license to GNU GPL | -# | 0.2.0: This code works with Blender 2.40a2 or up | -# | Major rewrite to deal with large meshes | -# | - 2 pass file parsing | -# | - lower memory foot###if DEBUG: print | -# | (as long as python gc allows) | -# | 2.40a2 - Removed subsurf settings patches=poly | -# | 2.40a2 - Edge generation instead of 2vert faces | -# | 0.1.16: fixed (try 2) texture offset calculations | -# | added hint on axis mapping | -# | added hint on texture blending mode | -# | added hint on texture transparency setting | -# | search images in original directory first | -# | fixed texture order application | -# | 0.1.15: added release log | -# | fixed texture offset calculations (non-UV) | -# | fixed reverting vertex order in face generation | -# | associate texture on game-engine settings | -# | vector math definitely based on mathutils | -# | search images in "Images" and "../Images" dir | -# | revised logging facility | -# | fixed subsurf texture and material mappings | -# | 0.1.14: patched missing mod_vector (not definitive) | -# | 0.1.13: first public release | -# +---------------------------------------------------------+ - -#blender related import -import Blender -import bpy - -# use for comprehensiveImageLoad -import BPyImage - -# Use this ngon function -import BPyMesh - -import BPyMessages - -#python specific modules import -try: - import struct, chunk, cStringIO -except: - struct= chunk= cStringIO= None - -# python 2.3 has no reversed() iterator. this will only work on lists and tuples -try: - reversed -except: - def reversed(l): return l[::-1] - -### # Debuggin disabled in release. -### # do a search replace to enabe debug prints -### DEBUG = False - -# =========================================================== -# === Utility Preamble ====================================== -# =========================================================== - -textname = None -#uncomment the following line to enable logging facility to the named text object -#textname = "lwo_log" - -TXMTX = Blender.Mathutils.Matrix(\ -[1, 0, 0, 0],\ -[0, 0, 1, 0],\ -[0, 1, 0, 0],\ -[0, 0, 0, 1]) - -# =========================================================== -# === Make sure it is a string ... deal with strange chars == -# =========================================================== -def safestring(st): - myst = "" - for ll in xrange(len(st)): - if st[ll] < " ": - myst += "#" - else: - myst += st[ll] - return myst - -# =========================================================== -# === Main read functions =================================== -# =========================================================== - -# ============================= -# === Read LightWave Format === -# ============================= -def read(filename): - if BPyMessages.Error_NoFile(filename): - return - - print "This is: %s" % importername - print "Importing file:", filename - bpy.data.scenes.active.objects.selected = [] - - start = Blender.sys.time() - file = open(filename, "rb") - - editmode = Blender.Window.EditMode() # are we in edit mode? If so ... - if editmode: Blender.Window.EditMode(0) # leave edit mode before getting the mesh # === LWO header === - - try: - form_id, form_size, form_type = struct.unpack(">4s1L4s", file.read(12)) - except: - Blender.Draw.PupMenu('Error%t|This is not a lightwave file') - return - - if (form_type == "LWOB"): - read_lwob(file, filename) - elif (form_type == "LWO2"): - read_lwo2(file, filename) - else: - print "Can't read a file with the form_type: %s" % form_type - return - - Blender.Window.DrawProgressBar(1.0, "") # clear progressbar - file.close() - end = Blender.sys.time() - seconds = " in %.2f %s" % (end-start, "seconds") - if form_type == "LWO2": fmt = " (v6.0 Format)" - if form_type == "LWOB": fmt = " (v5.5 Format)" - print "Successfully imported " + filename.split('\\')[-1].split('/')[-1] + fmt + seconds - - if editmode: Blender.Window.EditMode(1) # optional, just being nice - Blender.Redraw() - -# enddef read - - -# ================================= -# === Read LightWave 5.5 format === -# ================================= -def read_lwob(file, filename): - #This function is directly derived from the LWO2 import routine - #dropping all the material analysis parts - - ###if DEBUG: print "LightWave 5.5 format" - - dir_part = Blender.sys.dirname(filename) - fname_part = Blender.sys.basename(filename) - #ask_weird = 1 - - #first initialization of data structures - defaultname = Blender.sys.splitext(fname_part)[0] - tag_list = [] #tag list: global for the whole file? - surf_list = [] #surf list: global for the whole file? - clip_list = [] #clip list: global for the whole file? - object_index = 0 - object_list = None - objspec_list = None - - #add default material for orphaned faces, if any - surf_list.append({'NAME': "_Orphans", 'g_MAT': bpy.data.materials.new("_Orphans")}) - - #pass 2: effectively generate objects - ###if DEBUG: print "Pass 1: dry import" - file.seek(0) - objspec_list = ["imported", {}, [], [], {}, {}, 0, {}, {}] - # === LWO header === - form_id, form_size, form_type = struct.unpack(">4s1L4s", file.read(12)) - if (form_type != "LWOB"): - ###if DEBUG: print "??? Inconsistent file type: %s" % form_type - return - while 1: - try: - lwochunk = chunk.Chunk(file) - except EOFError: - break - ###if DEBUG: print ' ', - if lwochunk.chunkname == "LAYR": - ###if DEBUG: print "---- LAYR", - objname = read_layr(lwochunk) - ###if DEBUG: print objname - if objspec_list != None: #create the object - create_objects(clip_list, objspec_list, surf_list) - update_material(clip_list, objspec_list, surf_list) #give it all the object - objspec_list = [objname, {}, [], [], {}, {}, 0, {}, {}] - object_index += 1 - elif lwochunk.chunkname == "PNTS": # Verts - ###if DEBUG: print "---- PNTS", - verts = read_verts(lwochunk) - objspec_list[2] = verts - elif lwochunk.chunkname == "POLS": # Faces v5.5 - ###if DEBUG: print "-------- POLS(5.5)" - faces = read_faces_5(lwochunk) - flag = 0 - #flag is 0 for regular polygon, 1 for patches (= subsurf), 2 for anything else to be ignored - if flag<2: - if objspec_list[3] != []: - #create immediately the object - create_objects(clip_list, objspec_list, surf_list) - update_material(clip_list, objspec_list, surf_list) #give it all the object - #update with new data - objspec_list = [objspec_list[0], #update name - {}, #init - objspec_list[2], #same vertexes - faces, #give it the new faces - {}, #no need to copy - filled at runtime - {}, #polygon tagging will follow - flag, #patch flag - objspec_list[7], #same uvcoords - {}] #no vmad mapping - object_index += 1 - #end if already has a face list - objspec_list[3] = faces - objname = objspec_list[0] - if objname == None: - objname = defaultname - #end if processing a valid poly type - else: # Misc Chunks - ###if DEBUG: print "---- %s: skipping (definitely!)" % lwochunk.chunkname - lwochunk.skip() - #uncomment here to log data structure as it is built - # ###if DEBUG: print object_list - #last object read - create_objects(clip_list, objspec_list, surf_list) - update_material(clip_list, objspec_list, surf_list) #give it all the object - objspec_list = None - surf_list = None - clip_list = None - - - ###if DEBUG: print "\nFound %d objects:" % object_index - -# enddef read_lwob - - -# ============================= -# === Read LightWave Format === -# ============================= -def read_lwo2(file, filename, typ="LWO2"): - - ###if DEBUG: print "LightWave 6 (and above) format" - - dir_part = Blender.sys.dirname(filename) - fname_part = Blender.sys.basename(filename) - ask_weird = 1 - - #first initialization of data structures - defaultname = Blender.sys.splitext(fname_part)[0] - tag_list = [] #tag list: global for the whole file? - surf_list = [] #surf list: global for the whole file? - clip_list = [] #clip list: global for the whole file? - object_index = 0 - object_list = None - objspec_list = None - # init value is: object_list = [[None, {}, [], [], {}, {}, 0, {}, {}]] - #0 - objname #original name - #1 - obj_dict = {TAG} #objects created - #2 - verts = [] #object vertexes - #3 - faces = [] #object faces (associations poly -> vertexes) - #4 - obj_dim_dict = {TAG} #tuples size and pos in local object coords - used for NON-UV mappings - #5 - polytag_dict = {TAG} #tag to polygons mapping - #6 - patch_flag #0 = surf; 1 = patch (subdivision surface) - it was the image list - #7 - uvcoords_dict = {name} #uvmap coordinates (mixed mode per vertex/per face) - #8 - facesuv_dict = {name} #vmad only coordinates associations poly & vertex -> uv tuples - - #pass 1: look in advance for materials - ###if DEBUG: print "Starting Pass 1: hold on tight" - while 1: - try: - lwochunk = chunk.Chunk(file) - except EOFError: - break - ###if DEBUG: print ' ', - if lwochunk.chunkname == "TAGS": # Tags - ###if DEBUG: print "---- TAGS" - tag_list.extend(read_tags(lwochunk)) - elif lwochunk.chunkname == "SURF": # surfaces - ###if DEBUG: print "---- SURF" - surf_list.append(read_surfs(lwochunk, surf_list, tag_list)) - elif lwochunk.chunkname == "CLIP": # texture images - ###if DEBUG: print "---- CLIP" - clip_list.append(read_clip(lwochunk, dir_part)) - ###if DEBUG: print "read total %s clips up to now" % len(clip_list) - else: # Misc Chunks - if ask_weird: - ckname = safestring(lwochunk.chunkname) - if "#" in ckname: - choice = Blender.Draw.PupMenu("WARNING: file could be corrupted.%t|Import anyway|Give up") - if choice != 1: - ###if DEBUG: print "---- %s: Maybe file corrupted. Terminated by user" % lwochunk.chunkname - return - ask_weird = 0 - ###if DEBUG: print "---- %s: skipping (maybe later)" % lwochunk.chunkname - lwochunk.skip() - - #add default material for orphaned faces, if any - surf_list.append({'NAME': "_Orphans", 'g_MAT': bpy.data.materials.new("_Orphans")}) - - #pass 2: effectively generate objects - ###if DEBUG: print "Pass 2: now for the hard part" - file.seek(0) - # === LWO header === - form_id, form_size, form_type = struct.unpack(">4s1L4s", file.read(12)) - if (form_type != "LWO2"): - ###if DEBUG: print "??? Inconsistent file type: %s" % form_type - return - while 1: - try: - lwochunk = chunk.Chunk(file) - except EOFError: - break - ###if DEBUG: print ' ', - if lwochunk.chunkname == "LAYR": - ###if DEBUG: print "---- LAYR" - objname = read_layr(lwochunk) - ###if DEBUG: print objname - if objspec_list != None: #create the object - create_objects(clip_list, objspec_list, surf_list) - update_material(clip_list, objspec_list, surf_list) #give it all the object - objspec_list = [objname, {}, [], [], {}, {}, 0, {}, {}] - object_index += 1 - elif lwochunk.chunkname == "PNTS": # Verts - ###if DEBUG: print "---- PNTS" - verts = read_verts(lwochunk) - objspec_list[2] = verts - elif lwochunk.chunkname == "VMAP": # MAPS (UV) - ###if DEBUG: print "---- VMAP" - #objspec_list[7] = read_vmap(objspec_list[7], len(objspec_list[2]), lwochunk) - read_vmap(objspec_list[7], len(objspec_list[2]), lwochunk) - elif lwochunk.chunkname == "VMAD": # MAPS (UV) per-face - ###if DEBUG: print "---- VMAD" - #objspec_list[7], objspec_list[8] = read_vmad(objspec_list[7], objspec_list[8], len(objspec_list[3]), len(objspec_list[2]), lwochunk) - read_vmad(objspec_list[7], objspec_list[8], len(objspec_list[3]), len(objspec_list[2]), lwochunk) - elif lwochunk.chunkname == "POLS": # Faces v6.0 - ###if DEBUG: print "-------- POLS(6)" - faces, flag = read_faces_6(lwochunk) - #flag is 0 for regular polygon, 1 for patches (= subsurf), 2 for anything else to be ignored - if flag<2: - if objspec_list[3] != []: - #create immediately the object - create_objects(clip_list, objspec_list, surf_list) - update_material(clip_list, objspec_list, surf_list) #give it all the object - #update with new data - objspec_list = [objspec_list[0], #update name - {}, #init - objspec_list[2], #same vertexes - faces, #give it the new faces - {}, #no need to copy - filled at runtime - {}, #polygon tagging will follow - flag, #patch flag - objspec_list[7], #same uvcoords - {}] #no vmad mapping - object_index += 1 - #end if already has a face list - objspec_list[3] = faces - objname = objspec_list[0] - if objname == None: - objname = defaultname - #end if processing a valid poly type - elif lwochunk.chunkname == "PTAG": # PTags - ###if DEBUG: print "---- PTAG" - polytag_dict = read_ptags(lwochunk, tag_list) - for kk, polytag_dict_val in polytag_dict.iteritems(): objspec_list[5][kk] = polytag_dict_val - else: # Misc Chunks - ###if DEBUG: print "---- %s: skipping (definitely!)" % lwochunk.chunkname - lwochunk.skip() - #uncomment here to log data structure as it is built - - #last object read - create_objects(clip_list, objspec_list, surf_list) - update_material(clip_list, objspec_list, surf_list) #give it all the object - objspec_list = None - surf_list = None - clip_list = None - - ###if DEBUG: print "\nFound %d objects:" % object_index -# enddef read_lwo2 - - - - - - -# =========================================================== -# === File reading routines ================================= -# =========================================================== -# ================== -# === Read Verts === -# ================== -def read_verts(lwochunk): - #data = cStringIO.StringIO(lwochunk.read()) - numverts = lwochunk.chunksize/12 - return [struct.unpack(">fff", lwochunk.read(12)) for i in xrange(numverts)] -# enddef read_verts - - -# ================= -# === Read Name === -# ================= -# modified to deal with odd lenght strings -def read_name(file): - name = "" - while 1: - char = file.read(1) - if char == "\0": break - else: name += char - len_name = len(name) + 1 #count the trailing zero - if len_name%2==1: - char = file.read(1) #remove zero padding to even lenght - len_name += 1 - return name, len_name - - -# ================== -# === Read Layer === -# ================== -def read_layr(lwochunk): - data = cStringIO.StringIO(lwochunk.read()) - idx, flags = struct.unpack(">hh", data.read(4)) - pivot = struct.unpack(">fff", data.read(12)) - layer_name, discard = read_name(data) - if not layer_name: layer_name = "NoName" - return layer_name -# enddef read_layr - - -# ====================== -# === Read Faces 5.5 === -# ====================== -def read_faces_5(lwochunk): - data = cStringIO.StringIO(lwochunk.read()) - faces = [] - i = 0 - while i < lwochunk.chunksize: - #if not i%1000 and my_meshtools.show_progress: - # Blender.Window.DrawProgressBar(float(i)/lwochunk.chunksize, "Reading Faces") - - numfaceverts, = struct.unpack(">H", data.read(2)) - facev = [struct.unpack(">H", data.read(2))[0] for j in xrange(numfaceverts)] - facev.reverse() - faces.append(facev) - surfaceindex, = struct.unpack(">H", data.read(2)) - if surfaceindex < 0: - ###if DEBUG: print "***Error. Referencing uncorrect surface index" - return - i += (4+numfaceverts*2) - return faces - - -# ================================== -# === Read Variable-Length Index === -# ================================== -def read_vx(data): - byte1, = struct.unpack(">B", data.read(1)) - if byte1 != 0xFF: # 2-byte index - byte2, = struct.unpack(">B", data.read(1)) - index = byte1*256 + byte2 - index_size = 2 - else: # 4-byte index - byte2, byte3, byte4 = struct.unpack(">3B", data.read(3)) - index = byte2*65536 + byte3*256 + byte4 - index_size = 4 - return index, index_size - - -# ====================== -# === Read uvmapping === -# ====================== -def read_vmap(uvcoords_dict, maxvertnum, lwochunk): - - if maxvertnum == 0: - ###if DEBUG: print "Found VMAP but no vertexes to map!" - return uvcoords_dict - data = cStringIO.StringIO(lwochunk.read()) - map_type = data.read(4) - if map_type != "TXUV": - ###if DEBUG: print "Reading VMAP: No Texture UV map Were Found. Map Type: %s" % map_type - return uvcoords_dict - dimension, = struct.unpack(">H", data.read(2)) - name, i = read_name(data) #i initialized with string lenght + zeros - ###if DEBUG: print "TXUV %d %s" % (dimension, name) - #note if there is already a VMAD it will be lost - #it is assumed that VMAD will follow the corresponding VMAP - Vector = Blender.Mathutils.Vector - try: #if uvcoords_dict.has_key(name): - my_uv_dict = uvcoords_dict[name] #update existing - except: #else: - my_uv_dict = {} #start a brand new: this could be made more smart - while (i < lwochunk.chunksize - 6): #4+2 header bytes already read - vertnum, vnum_size = read_vx(data) - uv = struct.unpack(">ff", data.read(8)) - if vertnum >= maxvertnum: - ###if DEBUG: print "Hem: more uvmap than vertexes? ignoring uv data for vertex %d" % vertnum - pass - else: - my_uv_dict[vertnum] = Vector(uv) - i += 8 + vnum_size - #end loop on uv pairs - uvcoords_dict[name] = my_uv_dict - #this is a per-vertex mapping AND the uv tuple is vertex-ordered, so faces_uv is the same as faces - #return uvcoords_dict - return - -# ======================== -# === Read uvmapping 2 === -# ======================== -def read_vmad(uvcoords_dict, facesuv_dict, maxfacenum, maxvertnum, lwochunk): - if maxvertnum == 0 or maxfacenum == 0: - ###if DEBUG: print "Found VMAD but no vertexes to map!" - return uvcoords_dict, facesuv_dict - data = cStringIO.StringIO(lwochunk.read()) - map_type = data.read(4) - if map_type != "TXUV": - ###if DEBUG: print "Reading VMAD: No Texture UV map Were Found. Map Type: %s" % map_type - return uvcoords_dict, facesuv_dict - dimension, = struct.unpack(">H", data.read(2)) - name, i = read_name(data) #i initialized with string lenght + zeros - ###if DEBUG: print "TXUV %d %s" % (dimension, name) - try: #if uvcoords_dict.has_key(name): - my_uv_dict = uvcoords_dict[name] #update existing - except: #else: - my_uv_dict = {} #start a brand new: this could be made more smart - my_facesuv_list = [] - newindex = maxvertnum + 10 #why +10? Why not? - #end variable initialization - Vector = Blender.Mathutils.Vector - while (i < lwochunk.chunksize - 6): #4+2 header bytes already read - vertnum, vnum_size = read_vx(data) - i += vnum_size - polynum, vnum_size = read_vx(data) - i += vnum_size - uv = struct.unpack(">ff", data.read(8)) - if polynum >= maxfacenum or vertnum >= maxvertnum: - ###if DEBUG: print "Hem: more uvmap than vertexes? ignorig uv data for vertex %d" % vertnum - pass - else: - my_uv_dict[newindex] = Vector(uv) - my_facesuv_list.append([polynum, vertnum, newindex]) - newindex += 1 - i += 8 - #end loop on uv pairs - uvcoords_dict[name] = my_uv_dict - facesuv_dict[name] = my_facesuv_list - ###if DEBUG: print "updated %d vertexes data" % (newindex-maxvertnum-10) - return - - -# ================= -# === Read tags === -# ================= -def read_tags(lwochunk): - data = cStringIO.StringIO(lwochunk.read()) - tag_list = [] - current_tag = "" - i = 0 - while i < lwochunk.chunksize: - char = data.read(1) - if char == "\0": - tag_list.append(current_tag) - if (len(current_tag) % 2 == 0): char = data.read(1) - current_tag = "" - else: - current_tag += char - i += 1 - ###if DEBUG: print "read %d tags, list follows: %s" % (len(tag_list), tag_list) - return tag_list - - -# ================== -# === Read Ptags === -# ================== -def read_ptags(lwochunk, tag_list): - data = cStringIO.StringIO(lwochunk.read()) - polygon_type = data.read(4) - if polygon_type != "SURF": - ###if DEBUG: print "No Surf Were Found. Polygon Type: %s" % polygon_type - return {} - ptag_dict = {} - i = 0 - while(i < lwochunk.chunksize-4): #4 bytes polygon type already read - #if not i%1000 and my_meshtools.show_progress: - # Blender.Window.DrawProgressBar(float(i)/lwochunk.chunksize, "Reading PTAGS") - poln, poln_size = read_vx(data) - i += poln_size - tag_index, = struct.unpack(">H", data.read(2)) - if tag_index > (len(tag_list)): - ###if DEBUG: print "Reading PTAG: Surf belonging to undefined TAG: %d. Skipping" % tag_index - return {} - i += 2 - tag_key = tag_list[tag_index] - try: - ptag_dict[tag_list[tag_index]].append(poln) - except: #if not(ptag_dict.has_key(tag_key)): - ptag_dict[tag_list[tag_index]] = [poln] - - ###if DEBUG: for i, ptag_dict_val in ptag_dict.iteritems(): print "read %d polygons belonging to TAG %s" % (len(ptag_dict_val ), i) - return ptag_dict - - - -# ================== -# === Read Clips === -# ================== -def read_clip(lwochunk, dir_part): -# img, IMG, g_IMG refers to blender image objects -# ima, IMAG, g_IMAG refers to clip dictionary 'ID' entries: refer to blok and surf - clip_dict = {} - data = cStringIO.StringIO(lwochunk.read()) - data_str = data.read(4) - if len(data_str) < 4: # can be zero also??? :/ - # Should not happen but lw can import so we should too - return - - image_index, = struct.unpack(">L", data_str) - clip_dict['ID'] = image_index - i = 4 - while(i < lwochunk.chunksize): - subchunkname, = struct.unpack("4s", data.read(4)) - subchunklen, = struct.unpack(">H", data.read(2)) - if subchunkname == "STIL": - ###if DEBUG: print "-------- STIL" - clip_name, k = read_name(data) - #now split text independently from platform - #depend on the system where image was saved. NOT the one where the script is run - no_sep = "\\" - if Blender.sys.sep == no_sep: no_sep ="/" - if (no_sep in clip_name): - clip_name = clip_name.replace(no_sep, Blender.sys.sep) - short_name = Blender.sys.basename(clip_name) - if clip_name == "" or short_name == "": - ###if DEBUG: print "Reading CLIP: Empty clip name not allowed. Skipping" - discard = data.read(subchunklen-k) - clip_dict['NAME'] = clip_name - clip_dict['BASENAME'] = short_name - elif subchunkname == "XREF": #cross reference another image - ###if DEBUG: print "-------- XREF" - image_index, = struct.unpack(">L", data.read(4)) - clip_name, k = read_name(data) - clip_dict['NAME'] = clip_name - clip_dict['XREF'] = image_index - elif subchunkname == "NEGA": #negate texture effect - ###if DEBUG: print "-------- NEGA" - n, = struct.unpack(">H", data.read(2)) - clip_dict['NEGA'] = n - else: # Misc Chunks - ###if DEBUG: print "-------- CLIP:%s: skipping" % subchunkname - discard = data.read(subchunklen) - i = i + 6 + subchunklen - #end loop on surf chunks - ###if DEBUG: print "read image:%s" % clip_dict - if 'XREF' in clip_dict: # has_key - ###if DEBUG: print "Cross-reference: no image pre-allocated." - return clip_dict - #look for images - #img = load_image("",clip_dict['NAME']) - NAME= BASENAME= None - - try: - NAME= clip_dict['NAME'] - BASENAME= clip_dict['BASENAME'] - except: - clip_dict['g_IMG'] = None - return - # ###if DEBUG: print 'test', NAME, BASENAME - img = BPyImage.comprehensiveImageLoad(NAME, dir_part, PLACE_HOLDER= False, RECURSIVE=False) - if not img: - ###if DEBUG: print "***No image %s found: trying LWO file subdir" % NAME - img = BPyImage.comprehensiveImageLoad(BASENAME, dir_part, PLACE_HOLDER= False, RECURSIVE=False) - - ###if DEBUG: if not img: print "***No image %s found: giving up" % BASENAME - #lucky we are: we have an image - ###if DEBUG: print "Image pre-allocated." - clip_dict['g_IMG'] = img - - return clip_dict - - -# =========================== -# === Read Surfaces Block === -# =========================== -def read_surfblok(subchunkdata): - lenght = len(subchunkdata) - my_dict = {} - my_uvname = "" - data = cStringIO.StringIO(subchunkdata) - ############################################################## - # blok header sub-chunk - ############################################################## - subchunkname, = struct.unpack("4s", data.read(4)) - subchunklen, = struct.unpack(">h", data.read(2)) - accumulate_i = subchunklen + 6 - if subchunkname != 'IMAP': - ###if DEBUG: print "---------- SURF: BLOK: %s: block aborting" % subchunkname - return {}, "" - ###if DEBUG: print "---------- IMAP" - ordinal, i = read_name(data) - my_dict['ORD'] = ordinal - #my_dict['g_ORD'] = -1 - my_dict['ENAB'] = True - while(i < subchunklen): # ---------left 6------------------------- loop on header parameters - sub2chunkname, = struct.unpack("4s", data.read(4)) - sub2chunklen, = struct.unpack(">h", data.read(2)) - i = i + 6 + sub2chunklen - if sub2chunkname == "CHAN": - ###if DEBUG: print "------------ CHAN" - sub2chunkname, = struct.unpack("4s", data.read(4)) - my_dict['CHAN'] = sub2chunkname - sub2chunklen -= 4 - elif sub2chunkname == "ENAB": #only present if is to be disabled - ###if DEBUG: print "------------ ENAB" - ena, = struct.unpack(">h", data.read(2)) - my_dict['ENAB'] = ena - sub2chunklen -= 2 - elif sub2chunkname == "NEGA": #only present if is to be enabled - ###if DEBUG: print "------------ NEGA" - ena, = struct.unpack(">h", data.read(2)) - if ena == 1: - my_dict['NEGA'] = ena - sub2chunklen -= 2 - elif sub2chunkname == "OPAC": #only present if is to be disabled - ###if DEBUG: print "------------ OPAC" - opa, = struct.unpack(">h", data.read(2)) - s, = struct.unpack(">f", data.read(4)) - envelope, env_size = read_vx(data) - my_dict['OPAC'] = opa - my_dict['OPACVAL'] = s - sub2chunklen -= 6 - elif sub2chunkname == "AXIS": - ###if DEBUG: print "------------ AXIS" - ena, = struct.unpack(">h", data.read(2)) - my_dict['DISPLAXIS'] = ena - sub2chunklen -= 2 - else: # Misc Chunks - ###if DEBUG: print "------------ SURF: BLOK: IMAP: %s: skipping" % sub2chunkname - discard = data.read(sub2chunklen) - #end loop on blok header subchunks - ############################################################## - # blok attributes sub-chunk - ############################################################## - subchunkname, = struct.unpack("4s", data.read(4)) - subchunklen, = struct.unpack(">h", data.read(2)) - accumulate_i += subchunklen + 6 - if subchunkname != 'TMAP': - ###if DEBUG: print "---------- SURF: BLOK: %s: block aborting" % subchunkname - return {}, "" - ###if DEBUG: print "---------- TMAP" - i = 0 - while(i < subchunklen): # -----------left 6----------------------- loop on header parameters - sub2chunkname, = struct.unpack("4s", data.read(4)) - sub2chunklen, = struct.unpack(">h", data.read(2)) - i = i + 6 + sub2chunklen - if sub2chunkname == "CNTR": - ###if DEBUG: print "------------ CNTR" - x, y, z = struct.unpack(">fff", data.read(12)) - envelope, env_size = read_vx(data) - my_dict['CNTR'] = [x, y, z] - sub2chunklen -= (12+env_size) - elif sub2chunkname == "SIZE": - ###if DEBUG: print "------------ SIZE" - x, y, z = struct.unpack(">fff", data.read(12)) - envelope, env_size = read_vx(data) - my_dict['SIZE'] = [x, y, z] - sub2chunklen -= (12+env_size) - elif sub2chunkname == "ROTA": - ###if DEBUG: print "------------ ROTA" - x, y, z = struct.unpack(">fff", data.read(12)) - envelope, env_size = read_vx(data) - my_dict['ROTA'] = [x, y, z] - sub2chunklen -= (12+env_size) - elif sub2chunkname == "CSYS": - ###if DEBUG: print "------------ CSYS" - ena, = struct.unpack(">h", data.read(2)) - my_dict['CSYS'] = ena - sub2chunklen -= 2 - else: # Misc Chunks - ###if DEBUG: print "------------ SURF: BLOK: TMAP: %s: skipping" % sub2chunkname - pass - if sub2chunklen > 0: - discard = data.read(sub2chunklen) - #end loop on blok attributes subchunks - ############################################################## - # ok, now other attributes without sub_chunks - ############################################################## - while(accumulate_i < lenght): # ---------------------------------- loop on header parameters: lenght has already stripped the 6 bypes header - subchunkname, = struct.unpack("4s", data.read(4)) - subchunklen, = struct.unpack(">H", data.read(2)) - accumulate_i = accumulate_i + 6 + subchunklen - if subchunkname == "PROJ": - ###if DEBUG: print "---------- PROJ" - p, = struct.unpack(">h", data.read(2)) - my_dict['PROJ'] = p - subchunklen -= 2 - elif subchunkname == "AXIS": - ###if DEBUG: print "---------- AXIS" - a, = struct.unpack(">h", data.read(2)) - my_dict['MAJAXIS'] = a - subchunklen -= 2 - elif subchunkname == "IMAG": - ###if DEBUG: print "---------- IMAG" - i, i_size = read_vx(data) - my_dict['IMAG'] = i - subchunklen -= i_size - elif subchunkname == "WRAP": - ###if DEBUG: print "---------- WRAP" - ww, wh = struct.unpack(">hh", data.read(4)) - #reduce width and height to just 1 parameter for both - my_dict['WRAP'] = max([ww,wh]) - #my_dict['WRAPWIDTH'] = ww - #my_dict['WRAPHEIGHT'] = wh - subchunklen -= 4 - elif subchunkname == "WRPW": - ###if DEBUG: print "---------- WRPW" - w, = struct.unpack(">f", data.read(4)) - my_dict['WRPW'] = w - envelope, env_size = read_vx(data) - subchunklen -= (env_size+4) - elif subchunkname == "WRPH": - ###if DEBUG: print "---------- WRPH" - w, = struct.unpack(">f", data.read(4)) - my_dict['WRPH'] = w - envelope, env_size = read_vx(data) - subchunklen -= (env_size+4) - elif subchunkname == "VMAP": - ###if DEBUG: print "---------- VMAP" - vmp, i = read_name(data) - my_dict['VMAP'] = vmp - my_uvname = vmp - subchunklen -= i - else: # Misc Chunks - ###if DEBUG: print "---------- SURF: BLOK: %s: skipping" % subchunkname - pass - if subchunklen > 0: - discard = data.read(subchunklen) - #end loop on blok subchunks - return my_dict, my_uvname - - -# ===================== -# === Read Surfaces === -# ===================== -def read_surfs(lwochunk, surf_list, tag_list): - my_dict = {} - data = cStringIO.StringIO(lwochunk.read()) - surf_name, i = read_name(data) - parent_name, j = read_name(data) - i += j - if (surf_name == "") or not(surf_name in tag_list): - ###if DEBUG: print "Reading SURF: Actually empty surf name not allowed. Skipping" - return {} - if (parent_name != ""): - parent_index = [x['NAME'] for x in surf_list].count(parent_name) - if parent_index >0: - my_dict = surf_list[parent_index-1] - my_dict['NAME'] = surf_name - ###if DEBUG: print "Surface data for TAG %s" % surf_name - while(i < lwochunk.chunksize): - subchunkname, = struct.unpack("4s", data.read(4)) - subchunklen, = struct.unpack(">H", data.read(2)) - i = i + 6 + subchunklen #6 bytes subchunk header - if subchunkname == "COLR": #color: mapped on color - ###if DEBUG: print "-------- COLR" - r, g, b = struct.unpack(">fff", data.read(12)) - envelope, env_size = read_vx(data) - my_dict['COLR'] = [r, g, b] - subchunklen -= (12+env_size) - elif subchunkname == "DIFF": #diffusion: mapped on reflection (diffuse shader) - ###if DEBUG: print "-------- DIFF" - s, = struct.unpack(">f", data.read(4)) - envelope, env_size = read_vx(data) - my_dict['DIFF'] = s - subchunklen -= (4+env_size) - elif subchunkname == "SPEC": #specularity: mapped to specularity (spec shader) - ###if DEBUG: print "-------- SPEC" - s, = struct.unpack(">f", data.read(4)) - envelope, env_size = read_vx(data) - my_dict['SPEC'] = s - subchunklen -= (4+env_size) - elif subchunkname == "REFL": #reflection: mapped on raymirror - ###if DEBUG: print "-------- REFL" - s, = struct.unpack(">f", data.read(4)) - envelope, env_size = read_vx(data) - my_dict['REFL'] = s - subchunklen -= (4+env_size) - elif subchunkname == "TRNL": #translucency: mapped on same param - ###if DEBUG: print "-------- TRNL" - s, = struct.unpack(">f", data.read(4)) - envelope, env_size = read_vx(data) - my_dict['TRNL'] = s - subchunklen -= (4+env_size) - elif subchunkname == "GLOS": #glossiness: mapped on specularity hardness (spec shader) - ###if DEBUG: print "-------- GLOS" - s, = struct.unpack(">f", data.read(4)) - envelope, env_size = read_vx(data) - my_dict['GLOS'] = s - subchunklen -= (4+env_size) - elif subchunkname == "TRAN": #transparency: inverted and mapped on alpha channel - ###if DEBUG: print "-------- TRAN" - s, = struct.unpack(">f", data.read(4)) - envelope, env_size = read_vx(data) - my_dict['TRAN'] = s - subchunklen -= (4+env_size) - elif subchunkname == "LUMI": #luminosity: mapped on emit channel - ###if DEBUG: print "-------- LUMI" - s, = struct.unpack(">f", data.read(4)) - envelope, env_size = read_vx(data) - my_dict['LUMI'] = s - subchunklen -= (4+env_size) - elif subchunkname == "GVAL": #glow: mapped on add channel - ###if DEBUG: print "-------- GVAL" - s, = struct.unpack(">f", data.read(4)) - envelope, env_size = read_vx(data) - my_dict['GVAL'] = s - subchunklen -= (4+env_size) - elif subchunkname == "SMAN": #smoothing angle - ###if DEBUG: print "-------- SMAN" - s, = struct.unpack(">f", data.read(4)) - my_dict['SMAN'] = s - subchunklen -= 4 - elif subchunkname == "SIDE": #double sided? - ###if DEBUG: print "-------- SIDE" #if 1 side do not define key - s, = struct.unpack(">H", data.read(2)) - if s == 3: - my_dict['SIDE'] = s - subchunklen -= 2 - elif subchunkname == "RIND": #Refraction: mapped on IOR - ###if DEBUG: print "-------- RIND" - s, = struct.unpack(">f", data.read(4)) - envelope, env_size = read_vx(data) - my_dict['RIND'] = s - subchunklen -= (4+env_size) - elif subchunkname == "BLOK": #blocks - ###if DEBUG: print "-------- BLOK" - rr, uvname = read_surfblok(data.read(subchunklen)) - #paranoia setting: preventing adding an empty dict - if rr: # != {} - try: - my_dict['BLOK'].append(rr) - except: - my_dict['BLOK'] = [rr] - - if uvname: # != "": - my_dict['UVNAME'] = uvname #theoretically there could be a number of them: only one used per surf - # all are dictionaries - so testing keys - if not('g_IMAG' in my_dict) and ('CHAN' in rr) and ('OPAC' in rr) and ('IMAG' in rr): - if (rr['CHAN'] == 'COLR') and (rr['OPAC'] == 0): - my_dict['g_IMAG'] = rr['IMAG'] #do not set anything, just save image object for later assignment - subchunklen = 0 #force ending - else: # Misc Chunks - pass - ###if DEBUG: print "-------- SURF:%s: skipping" % subchunkname - if subchunklen > 0: - discard = data.read(subchunklen) - #end loop on surf chunks - try:#if my_dict.has_key('BLOK'): - my_dict['BLOK'].reverse() #texture applied in reverse order with respect to reading from lwo - except: - pass - - #uncomment this if material pre-allocated by read_surf - my_dict['g_MAT'] = bpy.data.materials.new(my_dict['NAME']) - ###if DEBUG: print "-> Material pre-allocated." - return my_dict - -# ========================= -# === Recalculate Faces === -# ========================= - -def get_uvface(complete_list, facenum): - # extract from the complete list only vertexes of the desired polygon - ''' - my_facelist = [] - for elem in complete_list: - if elem[0] == facenum: - my_facelist.append(elem) - return my_facelist - ''' - return [elem for elem in complete_list if elem[0] == facenum] - -def get_newindex(polygon_list, vertnum): - # extract from the polygon list the new index associated to a vertex - if not polygon_list: # == [] - return -1 - for elem in polygon_list: - if elem[1] == vertnum: - return elem[2] - # ###if DEBUG: print "WARNING: expected vertex %s for polygon %s. Polygon_list dump follows" % (vertnum, polygon_list[0][0]) - # ###if DEBUG: print polygon_list - return -1 - -def get_surf(surf_list, cur_tag): - for elem in surf_list: # elem can be None - if elem and elem['NAME'] == cur_tag: - return elem - return {} - - - -# ==================================== -# === Modified Create Blender Mesh === -# ==================================== -def my_create_mesh(clip_list, surf, objspec_list, current_facelist, objname, not_used_faces): - #take the needed faces and update the not-used face list - complete_vertlist = objspec_list[2] - complete_facelist = objspec_list[3] - uvcoords_dict = objspec_list[7] - facesuv_dict = objspec_list[8] - vertex_map = {} #implementation as dict - cur_ptag_faces = [] - cur_ptag_faces_indexes = [] - maxface = len(complete_facelist) - for ff in current_facelist: - if ff >= maxface: - ###if DEBUG: print "Non existent face addressed: Giving up with this object" - return None, not_used_faces #return the created object - cur_face = complete_facelist[ff] - cur_ptag_faces_indexes.append(ff) - if not_used_faces: # != [] - not_used_faces[ff] = -1 - for vv in cur_face: vertex_map[vv] = 1 - #end loop on faces - store_edge = 0 - - scn= bpy.data.scenes.active - msh = bpy.data.meshes.new() - obj = scn.objects.new(msh) - - mat = None - try: - msh.materials = [surf['g_MAT']] - except: - pass - - msh.mode |= Blender.Mesh.Modes.AUTOSMOOTH #smooth it anyway - if 'SMAN' in surf: # has_key - #not allowed mixed mode mesh (all the mesh is smoothed and all with the same angle) - #only one smoothing angle will be active! => take the max one - msh.degr = min(80, int(surf['SMAN']/3.1415926535897932384626433832795*180.0)) #lwo in radians - blender in degrees - - try: - img= lookup_imag(clip_list, surf['g_IMAG'])['g_IMG'] - except: - img= None - - #uv_flag = ((surf.has_key('UVNAME')) and (uvcoords_dict.has_key(surf['UVNAME'])) and (img != None)) - uv_flag = (('UVNAME' in surf) and (surf['UVNAME'] in uvcoords_dict)) - - ###if DEBUG: print "\n#===================================================================#" - ###if DEBUG: print "Processing Object: %s" % objname - ###if DEBUG: print "#===================================================================#" - - if uv_flag: - msh.verts.extend([(0.0,0.0,0.0),]) - j = 1 - else: - j = 0 - - def tmp_get_vert(k, i): - vertex_map[k] = i+j # j is the dummy vert - # ###if DEBUG: print complete_vertlist[i] - return complete_vertlist[k] - - - - msh.verts.extend([tmp_get_vert(k, i) for i, k in enumerate(vertex_map.iterkeys())]) - msh.transform(TXMTX) # faster then applying while reading. - #end sweep over vertexes - - #append faces - FACE_TEX= Blender.Mesh.FaceModes.TEX - FACE_ALPHA= Blender.Mesh.FaceTranspModes.ALPHA - EDGE_DRAW_FLAG= Blender.Mesh.EdgeFlags.EDGEDRAW | Blender.Mesh.EdgeFlags.EDGERENDER - - - edges = [] - face_data = [] # [(indicies, material, uvs, image), ] - face_uvs = [] - edges_fgon = [] - - if uv_flag: - uvcoords_dict_context = uvcoords_dict[surf['UVNAME']] - try: current_uvdict = facesuv_dict[surf['UVNAME']] - except: current_uvdict = None - - default_uv = Blender.Mathutils.Vector(0,0) - def tmp_get_face_uvs(cur_face, i): - uvs = [] - if current_uvdict: - uvface = get_uvface(current_uvdict,i) - for vi in cur_face: - ni = get_newindex(uvface, vi) - if ni == -1: ni = vi - - try: - uvs.append(uvcoords_dict_context[ ni ]) - except: - ###if DEBUG: print '\tWarning, Corrupt UVs' - uvs.append(default_uv) - else: - for vi in cur_face: - try: - uvs.append(uvcoords_dict_context[ vi ]) - except: - ###if DEBUG: print '\tWarning, Corrupt UVs' - uvs.append(default_uv) - - return uvs - cur_face - for i in cur_ptag_faces_indexes: - cur_face = complete_facelist[i] - numfaceverts = len(cur_face) - - if numfaceverts == 2: edges.append((vertex_map[cur_face[0]], vertex_map[cur_face[1]])) - elif numfaceverts == 3 or numfaceverts == 4: - rev_face = [__i for __i in reversed(cur_face)] - face_data.append( [vertex_map[j] for j in rev_face] ) - if uv_flag: face_uvs.append(tmp_get_face_uvs(rev_face, i)) - elif numfaceverts > 4: - meta_faces= BPyMesh.ngon(complete_vertlist, cur_face, PREF_FIX_LOOPS= True) - edge_face_count = {} - for mf in meta_faces: - # These will always be tri's since they are scanfill faces - mf = cur_face[mf[2]], cur_face[mf[1]], cur_face[mf[0]] - face_data.append( [vertex_map[j] for j in mf] ) - - if uv_flag: face_uvs.append(tmp_get_face_uvs(mf, i)) - - #if USE_FGON: - if len(meta_faces) > 1: - mf = face_data[-1] # reuse mf - for j in xrange(3): - v1= mf[j] - v2= mf[j-1] - if v1!=v2: - if v1>v2: - v2,v1= v1,v2 - try: - edge_face_count[v1,v2]+= 1 - except: - edge_face_count[v1,v2]= 0 - - - - if edge_face_count: - edges_fgon.extend( [vert_key for vert_key, count in edge_face_count.iteritems() if count] ) - - if edges: - msh.edges.extend(edges) - - face_mapping_removed = msh.faces.extend(face_data, indexList=True) - if 'TRAN' in surf or (mat and mat.alpha<1.0): # incase mat is null - transp_flag = True - else: - transp_flag = False - - if uv_flag: - msh.faceUV = True - msh_faces= msh.faces - for i, uvs in enumerate(face_uvs): - i_mapped = face_mapping_removed[i] - if i_mapped != None: - f = msh_faces[i_mapped] - f.uv = uvs - if img: - f.image = img - - if transp_flag: f.transp |= FACE_ALPHA - - if edges_fgon: - msh_edges = msh.edges - FGON= Blender.Mesh.EdgeFlags.FGON - edges_fgon = msh.findEdges( edges_fgon ) - if type(edges_fgon) != list: edges_fgon = [edges_fgon] - for ed in edges_fgon: - if ed!=None: - msh_edges[ed].flag |= FGON - - if not(uv_flag): #clear eventual UV data - msh.faceUV = False - - if uv_flag: - msh.verts.delete([0,]) - - return obj, not_used_faces #return the created object - - -# ============================================ -# === Set Subsurf attributes on given mesh === -# ============================================ -def set_subsurf(obj): - mods = obj.modifiers # get the object's modifiers - mod = mods.append(Blender.Modifier.Type.SUBSURF) # add a new subsurf modifier - mod[Blender.Modifier.Settings.LEVELS] = 2 # set subsurf subdivision levels to 2 - mod[Blender.Modifier.Settings.RENDLEVELS] = 2 # set subsurf rendertime subdivision levels to 2 - obj.makeDisplayList() - - -# ================================= -# === object size and dimension === -# ================================= -def obj_size_pos(obj): - bbox = obj.getBoundBox() - bbox_min = map(lambda *row: min(row), *bbox) #transpose & get min - bbox_max = map(lambda *row: max(row), *bbox) #transpose & get max - obj_size = (bbox_max[0]-bbox_min[0], bbox_max[1]-bbox_min[1], bbox_max[2]-bbox_min[2]) - obj_pos = ( (bbox_max[0]+bbox_min[0]) / 2, (bbox_max[1]+bbox_min[1]) / 2, (bbox_max[2]+bbox_min[2]) / 2) - return (obj_size, obj_pos) - - -# ========================= -# === Create the object === -# ========================= -def create_objects(clip_list, objspec_list, surf_list): - nf = len(objspec_list[3]) - not_used_faces = range(nf) - ptag_dict = objspec_list[5] - obj_dict = {} #links tag names to object, used for material assignments - obj_dim_dict = {} - obj_list = [] #have it handy for parent association - middlechar = "+" - endchar = "" - if (objspec_list[6] == 1): - middlechar = endchar = "#" - for cur_tag, ptag_dict_val in ptag_dict.iteritems(): - if ptag_dict_val != []: - cur_surf = get_surf(surf_list, cur_tag) - cur_obj, not_used_faces= my_create_mesh(clip_list, cur_surf, objspec_list, ptag_dict_val, objspec_list[0][:9]+middlechar+cur_tag[:9], not_used_faces) - # Works now with new modifiers - if objspec_list[6] == 1: - set_subsurf(cur_obj) - if cur_obj: # != None - obj_dict[cur_tag] = cur_obj - obj_dim_dict[cur_tag] = obj_size_pos(cur_obj) - obj_list.append(cur_obj) - #end loop on current group - #and what if some faces not used in any named PTAG? get rid of unused faces - orphans = [] - for tt in not_used_faces: - if tt > -1: orphans.append(tt) - #end sweep on unused face list - not_used_faces = None - if orphans: # != [] - cur_surf = get_surf(surf_list, "_Orphans") - cur_obj, not_used_faces = my_create_mesh(clip_list, cur_surf, objspec_list, orphans, objspec_list[0][:9]+middlechar+"Orphans", []) - if cur_obj: # != None - if objspec_list[6] == 1: - set_subsurf(cur_obj) - obj_dict["_Orphans"] = cur_obj - obj_dim_dict["_Orphans"] = obj_size_pos(cur_obj) - obj_list.append(cur_obj) - objspec_list[1]= obj_dict - objspec_list[4]= obj_dim_dict - - return - - - -# =========================================== -# === Lookup for image index in clip_list === -# =========================================== -def lookup_imag(clip_list, ima_id): - for ii in clip_list: - if ii and ii['ID'] == ima_id: - if 'XREF' in ii: # has_key - #cross reference - recursively look for images - return lookup_imag(clip_list, ii['XREF']) - else: - return ii - return None - - -# =================================================== -# === Create and assign image mapping to material === -# =================================================== -def create_blok(surf, mat, clip_list, obj_size, obj_pos): - - def output_size_ofs(size, pos, blok): - #just automate repetitive task - # 0 == X, 1 == Y, 2 == Z - size_default = [1.0] * 3 - size2 = [1.0] * 3 - ofs_default = [0.0] * 3 - offset = [1.0] * 3 - axis_default = [Blender.Texture.Proj.X, Blender.Texture.Proj.Y, Blender.Texture.Proj.Z] - axis = [1.0] * 3 - c_map_txt = [" X--", " -Y-", " --Z"] - c_map = [0,1,2] # standard, good for Z axis projection - if blok['MAJAXIS'] == 0: - c_map = [1,2,0] # X axis projection - if blok['MAJAXIS'] == 2: - c_map = [0,2,1] # Y axis projection - - ###if DEBUG: print "!!!axis mapping:" - #this is the smart way - ###if DEBUG: for mp in c_map: print c_map_txt[mp] - - if blok['SIZE'][0] != 0.0: #paranoia controls - size_default[0] = (size[0]/blok['SIZE'][0]) - ofs_default[0] = ((blok['CNTR'][0]-pos[0])/blok['SIZE'][0]) - if blok['SIZE'][1] != 0.0: - size_default[2] = (size[2]/blok['SIZE'][1]) - ofs_default[2] = ((blok['CNTR'][1]-pos[2])/blok['SIZE'][1]) - if blok['SIZE'][2] != 0.0: - size_default[1] = (size[1]/blok['SIZE'][2]) - ofs_default[1] = ((blok['CNTR'][2]-pos[1])/blok['SIZE'][2]) - - for mp in xrange(3): - axis[mp] = axis_default[c_map[mp]] - size2[mp] = size_default[c_map[mp]] - offset[mp] = ofs_default[c_map[mp]] - if offset[mp]>10.0: offset[mp]-10.0 - if offset[mp]<-10.0: offset[mp]+10.0 -# size = [size_default[mp] for mp in c_map] - - ###if DEBUG: print "!!!texture size and offsets:" - ###if DEBUG: print " sizeX = %.5f; sizeY = %.5f; sizeZ = %.5f" % (size[0],size[1],size[2]) - ###if DEBUG: print " ofsX = %.5f; ofsY = %.5f; ofsZ = %.5f" % (offset[0],offset[1],offset[2]) - return axis, size2, offset - - ti = 0 - alphaflag = 0 #switched to 1 if some tex in this block is using alpha - lastimag = 0 #experimental .... - for blok in surf['BLOK']: - ###if DEBUG: print "#...................................................................#" - ###if DEBUG: print "# Processing texture block no.%s for surf %s" % (ti,surf['NAME']) - ###if DEBUG: print "#...................................................................#" - # tobj.pdict (blok) - if ti > 9: break #only 8 channels 0..7 allowed for texture mapping - #if not blok['ENAB']: - # ###if DEBUG: print "***Image is not ENABled! Quitting this block" - # break - if not('IMAG' in blok): # has_key - ###if DEBUG: print "***No IMAGE for this block? Quitting" - break #extract out the image index within the clip_list - if blok['IMAG'] == 0: blok['IMAG'] = lastimag #experimental .... - ###if DEBUG: print "looking for image number %d" % blok['IMAG'] - ima = lookup_imag(clip_list, blok['IMAG']) - if ima == None: - ###if DEBUG: print "***Block index image not within CLIP list? Quitting Block" - break #safety check (paranoia setting) - img = ima['g_IMG'] - lastimag = blok['IMAG'] #experimental .... - if img == None: - ###if DEBUG: print "***Failed to pre-allocate image %s found: giving up" % ima['BASENAME'] - break - tname = str(ima['ID']) - if blok['ENAB']: - tname += "+" - else: - tname += "x" #let's signal when should not be enabled - if 'CHAN' in blok: # has_key - tname += blok['CHAN'] - newtex = bpy.data.textures.new(tname) - newtex.setType('Image') # make it anu image texture - newtex.image = img - #how does it extends beyond borders - if 'WRAP' in blok: # has_key - if (blok['WRAP'] == 3) or (blok['WRAP'] == 2): - newtex.setExtend('Extend') - elif (blok['WRAP'] == 1): - newtex.setExtend('Repeat') - elif (blok['WRAP'] == 0): - newtex.setExtend('Clip') - ###if DEBUG: print "generated texture %s" % tname - - #MapTo is determined by CHAN parameter - #assign some defaults - colfac = 1.0 - dvar = 1.0 - norfac = 0.5 - nega = False - mapflag = Blender.Texture.MapTo.COL #default to color - maptype = Blender.Texture.Mappings.FLAT - if 'CHAN' in blok: # has_key - if blok['CHAN'] == 'COLR' and 'OPACVAL' in blok: # has_key - colfac = blok['OPACVAL'] - # Blender needs this to be clamped - colfac = max(0.0, min(1.0, colfac)) - ###if DEBUG: print "!!!Set Texture -> MapTo -> Col = %.3f" % colfac - if blok['CHAN'] == 'BUMP': - mapflag = Blender.Texture.MapTo.NOR - if 'OPACVAL' in blok: norfac = blok['OPACVAL'] # has_key - ###if DEBUG: print "!!!Set Texture -> MapTo -> Nor = %.3f" % norfac - if blok['CHAN'] == 'LUMI': - mapflag = Blender.Texture.MapTo.EMIT - if 'OPACVAL' in blok: dvar = blok['OPACVAL'] # has_key - ###if DEBUG: print "!!!Set Texture -> MapTo -> DVar = %.3f" % dvar - if blok['CHAN'] == 'DIFF': - mapflag = Blender.Texture.MapTo.REF - if 'OPACVAL' in blok: dvar = blok['OPACVAL'] # has_key - ###if DEBUG: print "!!!Set Texture -> MapTo -> DVar = %.3f" % dvar - if blok['CHAN'] == 'SPEC': - mapflag = Blender.Texture.MapTo.SPEC - if 'OPACVAL' in blok: dvar = blok['OPACVAL'] # has_key - ###if DEBUG: print "!!!Set Texture -> MapTo -> DVar = %.3f" % dvar - if blok['CHAN'] == 'TRAN': - mapflag = Blender.Texture.MapTo.ALPHA - if 'OPACVAL' in blok: dvar = blok['OPACVAL'] # has_key - ###if DEBUG: print "!!!Set Texture -> MapTo -> DVar = %.3f" % dvar - alphaflag = 1 - nega = True - if 'NEGA' in blok: # has_key - ###if DEBUG: print "!!!Watch-out: effect of this texture channel must be INVERTED!" - nega = not nega - - blendmode_list = ['Mix', - 'Subtractive', - 'Difference', - 'Multiply', - 'Divide', - 'Mix with calculated alpha layer and stencil flag', - 'Texture Displacement', - 'Additive'] - set_blendmode = 7 #default additive - if 'OPAC' in blok: # has_key - set_blendmode = blok['OPAC'] - if set_blendmode == 5: #transparency - newtex.imageFlags |= Blender.Texture.ImageFlags.CALCALPHA - if nega: newtex.flags |= Blender.Texture.Flags.NEGALPHA - ###if DEBUG: print "!!!Set Texture -> MapTo -> Blending Mode = %s" % blendmode_list[set_blendmode] - - #the TexCo flag is determined by PROJ parameter - axis = [Blender.Texture.Proj.X, Blender.Texture.Proj.Y, Blender.Texture.Proj.Z] - size = [1.0] * 3 - ofs = [0.0] * 3 - if 'PROJ' in blok: # has_key - if blok['PROJ'] == 0: #0 - Planar - ###if DEBUG: print "!!!Flat projection" - coordflag = Blender.Texture.TexCo.ORCO - maptype = Blender.Texture.Mappings.FLAT - elif blok['PROJ'] == 1: #1 - Cylindrical - ###if DEBUG: print "!!!Cylindrical projection" - coordflag = Blender.Texture.TexCo.ORCO - maptype = Blender.Texture.Mappings.TUBE - elif blok['PROJ'] == 2: #2 - Spherical - ###if DEBUG: print "!!!Spherical projection" - coordflag = Blender.Texture.TexCo.ORCO - maptype = Blender.Texture.Mappings.SPHERE - elif blok['PROJ'] == 3: #3 - Cubic - ###if DEBUG: print "!!!Cubic projection" - coordflag = Blender.Texture.TexCo.ORCO - maptype = Blender.Texture.Mappings.CUBE - elif blok['PROJ'] == 4: #4 - Front Projection - ###if DEBUG: print "!!!Front projection" - coordflag = Blender.Texture.TexCo.ORCO - maptype = Blender.Texture.Mappings.FLAT # ??? could it be a FLAT with some other TexCo type? - elif blok['PROJ'] == 5: #5 - UV - ###if DEBUG: print "UVMapped" - coordflag = Blender.Texture.TexCo.UV - maptype = Blender.Texture.Mappings.FLAT #in case of UV default to FLAT mapping => effectively not used - if blok['PROJ'] != 5: #This holds for any projection map except UV - axis, size, ofs = output_size_ofs(obj_size, obj_pos, blok) - - # Clamp ofs and size else blender will raise an error - for ii in xrange(3): - ofs[ii]= min(10.0, max(-10, ofs[ii])) - size[ii]= min(100, max(-100, size[ii])) - - mat.setTexture(ti, newtex, coordflag, mapflag) - current_mtex = mat.getTextures()[ti] - current_mtex.mapping = maptype - current_mtex.colfac = colfac - current_mtex.dvar = dvar - current_mtex.norfac = norfac - current_mtex.neg = nega - current_mtex.xproj = axis[0] - current_mtex.yproj = axis[1] - current_mtex.zproj = axis[2] - current_mtex.size = tuple(size) - current_mtex.ofs = tuple(ofs) - if (set_blendmode == 5): #transparency - current_mtex.stencil = not (nega) - - ti += 1 - #end loop over bloks - return alphaflag - - -# ======================================== -# === Create and assign a new material === -# ======================================== -#def update_material(surf_list, ptag_dict, obj, clip_list, uv_dict, dir_part): -def update_material(clip_list, objspec, surf_list): - if (surf_list == []) or (objspec[5] == {}) or (objspec[1] == {}): - ###if DEBUG: print "something getting wrong in update_material: dump follows ..." - ###if DEBUG: print surf_list - ###if DEBUG: print objspec[5] - ###if DEBUG: print objspec[1] - return - obj_dict = objspec[1] - all_faces = objspec[3] - obj_dim_dict = objspec[4] - ptag_dict = objspec[5] - uvcoords_dict = objspec[7] - facesuv_dict = objspec[8] - for surf in surf_list: - if surf and surf['NAME'] in ptag_dict: # in ptag_dict.keys() - ###if DEBUG: print "#-------------------------------------------------------------------#" - ###if DEBUG: print "Processing surface (material): %s" % surf['NAME'] - ###if DEBUG: print "#-------------------------------------------------------------------#" - #material set up - facelist = ptag_dict[surf['NAME']] - #bounding box and position - cur_obj = obj_dict[surf['NAME']] - obj_size = obj_dim_dict[surf['NAME']][0] - obj_pos = obj_dim_dict[surf['NAME']][1] - ###if DEBUG: print surf - #uncomment this if material pre-allocated by read_surf - mat = surf['g_MAT'] - if mat == None: - ###if DEBUG: print "Sorry, no pre-allocated material to update. Giving up for %s." % surf['NAME'] - break - #mat = Blender.Material.New(surf['NAME']) - #surf['g_MAT'] = mat - if 'COLR' in surf: # has_key - mat.rgbCol = surf['COLR'] - if 'LUMI' in surf: - mat.setEmit(surf['LUMI']) - if 'GVAL' in surf: # has_key - mat.setAdd(surf['GVAL']) - if 'SPEC' in surf: # has_key - mat.setSpec(surf['SPEC']) #it should be * 2 but seems to be a bit higher lwo [0.0, 1.0] - blender [0.0, 2.0] - if 'DIFF' in surf: # has_key - mat.setRef(surf['DIFF']) #lwo [0.0, 1.0] - blender [0.0, 1.0] - if 'GLOS' in surf: # has_key #lwo [0.0, 1.0] - blender [0, 255] - glo = int(371.67 * surf['GLOS'] - 42.334) #linear mapping - seems to work better than exp mapping - if glo <32: glo = 32 #clamped to 32-255 - if glo >255: glo = 255 - mat.setHardness(glo) - if 'TRNL' in surf: # has_key - mat.setTranslucency(surf['TRNL']) #NOT SURE ABOUT THIS lwo [0.0, 1.0] - blender [0.0, 1.0] - - mm = mat.mode - mm |= Blender.Material.Modes.TRANSPSHADOW - if 'REFL' in surf: # has_key - mat.setRayMirr(surf['REFL']) #lwo [0.0, 1.0] - blender [0.0, 1.0] - mm |= Blender.Material.Modes.RAYMIRROR - if 'TRAN' in surf: # has_key - mat.setAlpha(1.0-surf['TRAN']) #lwo [0.0, 1.0] - blender [1.0, 0.0] - mm |= Blender.Material.Modes.RAYTRANSP - if 'RIND' in surf: # has_key - s = surf['RIND'] - if s < 1.0: s = 1.0 - if s > 3.0: s = 3.0 - mat.setIOR(s) #clipped to blender [1.0, 3.0] - mm |= Blender.Material.Modes.RAYTRANSP - if 'BLOK' in surf and surf['BLOK'] != []: - #update the material according to texture. - alphaflag = create_blok(surf, mat, clip_list, obj_size, obj_pos) - if alphaflag: - mm |= Blender.Material.Modes.RAYTRANSP - mat.mode = mm - #finished setting up the material - #end if exist SURF - #end loop on materials (SURFs) - return - - -# ====================== -# === Read Faces 6.0 === -# ====================== -def read_faces_6(lwochunk): - data = cStringIO.StringIO(lwochunk.read()) - faces = [] - polygon_type = data.read(4) - subsurf = 0 - if polygon_type != "FACE" and polygon_type != "PTCH": - ###if DEBUG: print "No FACE/PATCH Were Found. Polygon Type: %s" % polygon_type - return "", 2 - if polygon_type == 'PTCH': subsurf = 1 - i = 0 - while(i < lwochunk.chunksize-4): - #if not i%1000 and my_meshtools.show_progress: - # Blender.Window.DrawProgressBar(float(i)/lwochunk.chunksize, "Reading Faces") - facev = [] - numfaceverts, = struct.unpack(">H", data.read(2)) - i += 2 - - for j in xrange(numfaceverts): - index, index_size = read_vx(data) - i += index_size - facev.append(index) - faces.append(facev) - ###if DEBUG: print "read %s faces; type of block %d (0=FACE; 1=PATCH)" % (len(faces), subsurf) - return faces, subsurf - -def main(): - if not struct: - Blender.Draw.PupMenu('This importer requires a full python install') - return - - Blender.Window.FileSelector(read, "Import LWO", '*.lwo') - -if __name__=='__main__': - main() - - -# Cams debugging lwo loader -""" -TIME= Blender.sys.time() -import os -print 'Searching for files' -os.system('find /fe/lwo/Objects/ -follow -iname "*.lwo" > /tmp/templwo_list') -# os.system('find /storage/ -iname "*.lwo" > /tmp/templwo_list') -print '...Done' -file= open('/tmp/templwo_list', 'r') -lines= file.readlines() - -# sort by filesize for faster testing -lines_size = [(os.path.getsize(f[:-1]), f[:-1]) for f in lines] -lines_size.sort() -lines = [f[1] for f in lines_size] - -file.close() - -def between(v,a,b): - if v <= max(a,b) and v >= min(a,b): - return True - - return False -size= 0.0 -for i, _lwo in enumerate(lines): - #if i==425: # SCANFILL - #if 1: - #if i==520: # SCANFILL CRASH - #if i==47: # SCANFILL CRASH - #if between(i, 525, 550): - #if i > 1635: - #if i != 1519: # 730 - if i>141: - #if 1: - # _lwo= _lwo[:-1] - print 'Importing', _lwo, '\nNUMBER', i, 'of', len(lines) - _lwo_file= _lwo.split('/')[-1].split('\\')[-1] - newScn= bpy.data.scenes.new(_lwo_file) - bpy.data.scenes.active = newScn - size += ((os.path.getsize(_lwo)/1024.0))/ 1024.0 - read(_lwo) - # Remove objects to save memory? - ''' - for ob in newScn.objects: - if ob.type=='Mesh': - me= ob.getData(mesh=1) - me.verts= None - newScn.unlink(ob) - ''' - print 'mb size so far', size - -print 'TOTAL TIME: %.6f' % (Blender.sys.time() - TIME) -"""
\ No newline at end of file diff --git a/release/scripts/md2_export.py b/release/scripts/md2_export.py deleted file mode 100644 index f0fe6b9af40..00000000000 --- a/release/scripts/md2_export.py +++ /dev/null @@ -1,1271 +0,0 @@ -#!BPY - -""" -Name: 'MD2 (.md2)' -Blender: 243 -Group: 'Export' -Tooltip: 'Export to Quake file format (.md2).' -""" - -__author__ = 'Bob Holcomb' -__version__ = '0.18.1 patch 1' -__url__ = ["Bob's site, http://bane.servebeer.com", - "Support forum, http://bane.servebeer.com", "blender", "blenderartists.org"] -__email__ = ["Bob Holcomb, bob_holcomb:hotmail*com", "scripts"] -__bpydoc__ = """\ -This script Exports a Quake 2 file (MD2). - - Additional help from: Shadwolf, Skandal, Rojo, Cambo<br> - Thanks Guys! -""" - -# This is a PATCHED VERSION, fixing the bug due to which animations would -# (almost) never work. It is now also possible to output a MD2 model without -# texture. -# On: 23 january 2008 -# By: Boris van Schooten (schooten@cs.utwente.nl) - -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Script copyright (C): Bob Holcomb -# -# 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 ***** -# -------------------------------------------------------------------------- - - -import Blender -from Blender import * -from Blender.Draw import * -from Blender.BGL import * -from Blender.Window import * - -import struct, string -from types import * - - - -###################################################### -# GUI Loader -###################################################### - -# Export globals -g_filename=Create("tris.md2") -g_frame_filename=Create("default") - -g_filename_search=Create("") -g_frame_search=Create("default") - -g_texture_path=Create("") - -user_frame_list=[] - -#Globals -g_scale=Create(1.0) - -# Events -EVENT_NOEVENT=1 -EVENT_SAVE_MD2=2 -EVENT_CHOOSE_FILENAME=3 -EVENT_CHOOSE_FRAME=4 -EVENT_EXIT=100 - -###################################################### -# Callbacks for Window functions -###################################################### -def filename_callback(input_filename): - global g_filename - g_filename.val=input_filename - -def frame_callback(input_frame): - global g_frame_filename - g_frame_filename.val=input_frame - -def draw_gui(): - global g_scale - global g_filename - global g_frame_filename - global EVENT_NOEVENT,EVENT_SAVE_MD2,EVENT_CHOOSE_FILENAME,EVENT_CHOOSE_FRAME,EVENT_EXIT - global g_texture_path - - ########## Titles - glClear(GL_COLOR_BUFFER_BIT) - glRasterPos2d(10, 120) - Text("MD2 Export") - - ######### Parameters GUI Buttons - ######### MD2 Filename text entry - g_filename = String("MD2 file to save: ", EVENT_NOEVENT, 10, 75, 210, 18, - g_filename.val, 255, "MD2 file to save") - ########## MD2 File Search Button - Button("Browse",EVENT_CHOOSE_FILENAME,220,75,80,18) - - ########## MD2 Frame List Text entry - g_frame_filename = String("Frame List file to load: ", EVENT_NOEVENT, 10, 55, 210, 18, - g_frame_filename.val, 255, "Frame List to load-overrides MD2 defaults") - ########## Frame List Search Button - Button("Browse",EVENT_CHOOSE_FRAME,220,55,80,18) - - ########## Texture path to append - g_texture_path=String("Texture Path: ", EVENT_NOEVENT, 10,35,210,18, - g_texture_path.val,255, "Texture path to prepend") - - - ########## Scale slider-default is 1/8 which is a good scale for md2->blender - g_scale= Slider("Scale Factor: ", EVENT_NOEVENT, 10, 95, 210, 18, - 1.0, 0.001, 10.0, 1, "Scale factor for object Model"); - - ######### Draw and Exit Buttons - Button("Export",EVENT_SAVE_MD2 , 10, 10, 80, 18) - Button("Exit",EVENT_EXIT , 170, 10, 80, 18) - -def event(evt, val): - if (evt == QKEY and not val): - Exit() - -def bevent(evt): - global g_filename - global g_frame_filename - global EVENT_NOEVENT,EVENT_SAVE_MD2,EVENT_EXIT - - ######### Manages GUI events - if (evt==EVENT_EXIT): - Blender.Draw.Exit() - elif (evt==EVENT_CHOOSE_FILENAME): - FileSelector(filename_callback, "MD2 File Selection") - elif (evt==EVENT_CHOOSE_FRAME): - FileSelector(frame_callback, "Frame Selection") - elif (evt==EVENT_SAVE_MD2): - save_md2(g_filename.val) - Blender.Draw.Exit() - return - -Register(draw_gui, event, bevent) - -###################################################### -# MD2 Model Constants -###################################################### -MD2_MAX_TRIANGLES=4096 -MD2_MAX_VERTICES=2048 -MD2_MAX_TEXCOORDS=2048 -MD2_MAX_FRAMES=512 -MD2_MAX_SKINS=32 -MD2_MAX_FRAMESIZE=(MD2_MAX_VERTICES * 4 + 128) - -MD2_FRAME_NAME_LIST=(("stand",1,40), - ("run",41,46), - ("attack",47,54), - ("pain1",55,58), - ("pain2",59,62), - ("pain3",63,66), - ("jump",67,72), - ("flip",73,84), - ("salute", 85,95), - ("taunt",96,112), - ("wave",113,123), - ("point",124,135), - ("crstnd",136,154), - ("crwalk",155,160), - ("crattack",161,169), - ("crpain",170,173), - ("crdeath",174,178), - ("death1",179,184), - ("death2",185,190), - ("death3",191,198)) - #198 frames - -MD2_NORMALS=((-0.525731, 0.000000, 0.850651), - (-0.442863, 0.238856, 0.864188), - (-0.295242, 0.000000, 0.955423), - (-0.309017, 0.500000, 0.809017), - (-0.162460, 0.262866, 0.951056), - (0.000000, 0.000000, 1.000000), - (0.000000, 0.850651, 0.525731), - (-0.147621, 0.716567, 0.681718), - (0.147621, 0.716567, 0.681718), - (0.000000, 0.525731, 0.850651), - (0.309017, 0.500000, 0.809017), - (0.525731, 0.000000, 0.850651), - (0.295242, 0.000000, 0.955423), - (0.442863, 0.238856, 0.864188), - (0.162460, 0.262866, 0.951056), - (-0.681718, 0.147621, 0.716567), - (-0.809017, 0.309017, 0.500000), - (-0.587785, 0.425325, 0.688191), - (-0.850651, 0.525731, 0.000000), - (-0.864188, 0.442863, 0.238856), - (-0.716567, 0.681718, 0.147621), - (-0.688191, 0.587785, 0.425325), - (-0.500000, 0.809017, 0.309017), - (-0.238856, 0.864188, 0.442863), - (-0.425325, 0.688191, 0.587785), - (-0.716567, 0.681718, -0.147621), - (-0.500000, 0.809017, -0.309017), - (-0.525731, 0.850651, 0.000000), - (0.000000, 0.850651, -0.525731), - (-0.238856, 0.864188, -0.442863), - (0.000000, 0.955423, -0.295242), - (-0.262866, 0.951056, -0.162460), - (0.000000, 1.000000, 0.000000), - (0.000000, 0.955423, 0.295242), - (-0.262866, 0.951056, 0.162460), - (0.238856, 0.864188, 0.442863), - (0.262866, 0.951056, 0.162460), - (0.500000, 0.809017, 0.309017), - (0.238856, 0.864188, -0.442863), - (0.262866, 0.951056, -0.162460), - (0.500000, 0.809017, -0.309017), - (0.850651, 0.525731, 0.000000), - (0.716567, 0.681718, 0.147621), - (0.716567, 0.681718, -0.147621), - (0.525731, 0.850651, 0.000000), - (0.425325, 0.688191, 0.587785), - (0.864188, 0.442863, 0.238856), - (0.688191, 0.587785, 0.425325), - (0.809017, 0.309017, 0.500000), - (0.681718, 0.147621, 0.716567), - (0.587785, 0.425325, 0.688191), - (0.955423, 0.295242, 0.000000), - (1.000000, 0.000000, 0.000000), - (0.951056, 0.162460, 0.262866), - (0.850651, -0.525731, 0.000000), - (0.955423, -0.295242, 0.000000), - (0.864188, -0.442863, 0.238856), - (0.951056, -0.162460, 0.262866), - (0.809017, -0.309017, 0.500000), - (0.681718, -0.147621, 0.716567), - (0.850651, 0.000000, 0.525731), - (0.864188, 0.442863, -0.238856), - (0.809017, 0.309017, -0.500000), - (0.951056, 0.162460, -0.262866), - (0.525731, 0.000000, -0.850651), - (0.681718, 0.147621, -0.716567), - (0.681718, -0.147621, -0.716567), - (0.850651, 0.000000, -0.525731), - (0.809017, -0.309017, -0.500000), - (0.864188, -0.442863, -0.238856), - (0.951056, -0.162460, -0.262866), - (0.147621, 0.716567, -0.681718), - (0.309017, 0.500000, -0.809017), - (0.425325, 0.688191, -0.587785), - (0.442863, 0.238856, -0.864188), - (0.587785, 0.425325, -0.688191), - (0.688191, 0.587785, -0.425325), - (-0.147621, 0.716567, -0.681718), - (-0.309017, 0.500000, -0.809017), - (0.000000, 0.525731, -0.850651), - (-0.525731, 0.000000, -0.850651), - (-0.442863, 0.238856, -0.864188), - (-0.295242, 0.000000, -0.955423), - (-0.162460, 0.262866, -0.951056), - (0.000000, 0.000000, -1.000000), - (0.295242, 0.000000, -0.955423), - (0.162460, 0.262866, -0.951056), - (-0.442863, -0.238856, -0.864188), - (-0.309017, -0.500000, -0.809017), - (-0.162460, -0.262866, -0.951056), - (0.000000, -0.850651, -0.525731), - (-0.147621, -0.716567, -0.681718), - (0.147621, -0.716567, -0.681718), - (0.000000, -0.525731, -0.850651), - (0.309017, -0.500000, -0.809017), - (0.442863, -0.238856, -0.864188), - (0.162460, -0.262866, -0.951056), - (0.238856, -0.864188, -0.442863), - (0.500000, -0.809017, -0.309017), - (0.425325, -0.688191, -0.587785), - (0.716567, -0.681718, -0.147621), - (0.688191, -0.587785, -0.425325), - (0.587785, -0.425325, -0.688191), - (0.000000, -0.955423, -0.295242), - (0.000000, -1.000000, 0.000000), - (0.262866, -0.951056, -0.162460), - (0.000000, -0.850651, 0.525731), - (0.000000, -0.955423, 0.295242), - (0.238856, -0.864188, 0.442863), - (0.262866, -0.951056, 0.162460), - (0.500000, -0.809017, 0.309017), - (0.716567, -0.681718, 0.147621), - (0.525731, -0.850651, 0.000000), - (-0.238856, -0.864188, -0.442863), - (-0.500000, -0.809017, -0.309017), - (-0.262866, -0.951056, -0.162460), - (-0.850651, -0.525731, 0.000000), - (-0.716567, -0.681718, -0.147621), - (-0.716567, -0.681718, 0.147621), - (-0.525731, -0.850651, 0.000000), - (-0.500000, -0.809017, 0.309017), - (-0.238856, -0.864188, 0.442863), - (-0.262866, -0.951056, 0.162460), - (-0.864188, -0.442863, 0.238856), - (-0.809017, -0.309017, 0.500000), - (-0.688191, -0.587785, 0.425325), - (-0.681718, -0.147621, 0.716567), - (-0.442863, -0.238856, 0.864188), - (-0.587785, -0.425325, 0.688191), - (-0.309017, -0.500000, 0.809017), - (-0.147621, -0.716567, 0.681718), - (-0.425325, -0.688191, 0.587785), - (-0.162460, -0.262866, 0.951056), - (0.442863, -0.238856, 0.864188), - (0.162460, -0.262866, 0.951056), - (0.309017, -0.500000, 0.809017), - (0.147621, -0.716567, 0.681718), - (0.000000, -0.525731, 0.850651), - (0.425325, -0.688191, 0.587785), - (0.587785, -0.425325, 0.688191), - (0.688191, -0.587785, 0.425325), - (-0.955423, 0.295242, 0.000000), - (-0.951056, 0.162460, 0.262866), - (-1.000000, 0.000000, 0.000000), - (-0.850651, 0.000000, 0.525731), - (-0.955423, -0.295242, 0.000000), - (-0.951056, -0.162460, 0.262866), - (-0.864188, 0.442863, -0.238856), - (-0.951056, 0.162460, -0.262866), - (-0.809017, 0.309017, -0.500000), - (-0.864188, -0.442863, -0.238856), - (-0.951056, -0.162460, -0.262866), - (-0.809017, -0.309017, -0.500000), - (-0.681718, 0.147621, -0.716567), - (-0.681718, -0.147621, -0.716567), - (-0.850651, 0.000000, -0.525731), - (-0.688191, 0.587785, -0.425325), - (-0.587785, 0.425325, -0.688191), - (-0.425325, 0.688191, -0.587785), - (-0.425325, -0.688191, -0.587785), - (-0.587785, -0.425325, -0.688191), - (-0.688191, -0.587785, -0.425325)) - - -###################################################### -# MD2 data structures -###################################################### -class md2_point: - vertices=[] - lightnormalindex=0 - binary_format="<3BB" - def __init__(self): - self.vertices=[0]*3 - self.lightnormalindex=0 - def save(self, file): - temp_data=[0]*4 - temp_data[0]=self.vertices[0] - temp_data[1]=self.vertices[1] - temp_data[2]=self.vertices[2] - temp_data[3]=self.lightnormalindex - data=struct.pack(self.binary_format, temp_data[0], temp_data[1], temp_data[2], temp_data[3]) - file.write(data) - def dump(self): - print "MD2 Point Structure" - print "vertex X: ", self.vertices[0] - print "vertex Y: ", self.vertices[1] - print "vertex Z: ", self.vertices[2] - print "lightnormalindex: ",self.lightnormalindex - print "" - -class md2_face: - vertex_index=[] - texture_index=[] - binary_format="<3h3h" - def __init__(self): - self.vertex_index = [ 0, 0, 0 ] - self.texture_index = [ 0, 0, 0] - def save(self, file): - temp_data=[0]*6 - #swap vertices around so they draw right - temp_data[0]=self.vertex_index[0] - temp_data[1]=self.vertex_index[2] - temp_data[2]=self.vertex_index[1] - #swap texture vertices around so they draw right - temp_data[3]=self.texture_index[0] - temp_data[4]=self.texture_index[2] - temp_data[5]=self.texture_index[1] - data=struct.pack(self.binary_format,temp_data[0],temp_data[1],temp_data[2],temp_data[3],temp_data[4],temp_data[5]) - file.write(data) - def dump (self): - print "MD2 Face Structure" - print "vertex 1 index: ", self.vertex_index[0] - print "vertex 2 index: ", self.vertex_index[1] - print "vertex 3 index: ", self.vertex_index[2] - print "texture 1 index: ", self.texture_index[0] - print "texture 2 index: ", self.texture_index[1] - print "texture 3 index: ", self.texture_index[2] - print "" - -class md2_tex_coord: - u=0 - v=0 - binary_format="<2h" - def __init__(self): - self.u=0 - self.v=0 - def save(self, file): - temp_data=[0]*2 - temp_data[0]=self.u - temp_data[1]=self.v - data=struct.pack(self.binary_format, temp_data[0], temp_data[1]) - file.write(data) - def dump (self): - print "MD2 Texture Coordinate Structure" - print "texture coordinate u: ",self.u - print "texture coordinate v: ",self.v - print "" - -class md2_GL_command: - s=0.0 - t=0.0 - vert_index=0 - binary_format="<2fi" - - def __init__(self): - self.s=0.0 - self.t=0.0 - vert_index=0 - def save(self,file): - temp_data=[0]*3 - temp_data[0]=float(self.s) - temp_data[1]=float(self.t) - temp_data[2]=self.vert_index - data=struct.pack(self.binary_format, temp_data[0],temp_data[1],temp_data[2]) - file.write(data) - def dump (self): - print "MD2 OpenGL Command" - print "s: ", self.s - print "t: ", self.t - print "Vertex Index: ", self.vert_index - print "" - -class md2_GL_cmd_list: - num=0 - cmd_list=[] - binary_format="<i" - - def __init__(self): - self.num=0 - self.cmd_list=[] - - def save(self,file): - data=struct.pack(self.binary_format, self.num) - file.write(data) - for cmd in self.cmd_list: - cmd.save(file) - def dump(self): - print "MD2 OpenGL Command List" - print "number: ", self.num - for cmd in self.cmd_list: - cmd.dump() - print "" - -class md2_skin: - name="" - binary_format="<64s" - def __init__(self): - self.name="" - def save(self, file): - temp_data=self.name - data=struct.pack(self.binary_format, temp_data) - file.write(data) - def dump (self): - print "MD2 Skin" - print "skin name: ",self.name - print "" - -class md2_frame: - scale=[] - translate=[] - name=[] - vertices=[] - binary_format="<3f3f16s" - - def __init__(self): - self.scale=[0.0]*3 - self.translate=[0.0]*3 - self.name="" - self.vertices=[] - def save(self, file): - temp_data=[0]*7 - temp_data[0]=float(self.scale[0]) - temp_data[1]=float(self.scale[1]) - temp_data[2]=float(self.scale[2]) - temp_data[3]=float(self.translate[0]) - temp_data[4]=float(self.translate[1]) - temp_data[5]=float(self.translate[2]) - temp_data[6]=self.name - data=struct.pack(self.binary_format, temp_data[0],temp_data[1],temp_data[2],temp_data[3],temp_data[4],temp_data[5],temp_data[6]) - file.write(data) - def dump (self): - print "MD2 Frame" - print "scale x: ",self.scale[0] - print "scale y: ",self.scale[1] - print "scale z: ",self.scale[2] - print "translate x: ",self.translate[0] - print "translate y: ",self.translate[1] - print "translate z: ",self.translate[2] - print "name: ",self.name - print "" - -class md2_obj: - #Header Structure - ident=0 #int 0 This is used to identify the file - version=0 #int 1 The version number of the file (Must be 8) - skin_width=0 #int 2 The skin width in pixels - skin_height=0 #int 3 The skin height in pixels - frame_size=0 #int 4 The size in bytes the frames are - num_skins=0 #int 5 The number of skins associated with the model - num_vertices=0 #int 6 The number of vertices (constant for each frame) - num_tex_coords=0 #int 7 The number of texture coordinates - num_faces=0 #int 8 The number of faces (polygons) - num_GL_commands=0 #int 9 The number of gl commands - num_frames=0 #int 10 The number of animation frames - offset_skins=0 #int 11 The offset in the file for the skin data - offset_tex_coords=0 #int 12 The offset in the file for the texture data - offset_faces=0 #int 13 The offset in the file for the face data - offset_frames=0 #int 14 The offset in the file for the frames data - offset_GL_commands=0#int 15 The offset in the file for the gl commands data - offset_end=0 #int 16 The end of the file offset - binary_format="<17i" #little-endian (<), 17 integers (17i) - #md2 data objects - tex_coords=[] - faces=[] - frames=[] - skins=[] - GL_commands=[] - - def __init__ (self): - self.tex_coords=[] - self.faces=[] - self.frames=[] - self.skins=[] - def save(self, file): - temp_data=[0]*17 - temp_data[0]=self.ident - temp_data[1]=self.version - temp_data[2]=self.skin_width - temp_data[3]=self.skin_height - temp_data[4]=self.frame_size - temp_data[5]=self.num_skins - temp_data[6]=self.num_vertices - temp_data[7]=self.num_tex_coords - temp_data[8]=self.num_faces - temp_data[9]=self.num_GL_commands - temp_data[10]=self.num_frames - temp_data[11]=self.offset_skins - temp_data[12]=self.offset_tex_coords - temp_data[13]=self.offset_faces - temp_data[14]=self.offset_frames - temp_data[15]=self.offset_GL_commands - temp_data[16]=self.offset_end - data=struct.pack(self.binary_format, temp_data[0],temp_data[1],temp_data[2],temp_data[3],temp_data[4],temp_data[5],temp_data[6],temp_data[7],temp_data[8],temp_data[9],temp_data[10],temp_data[11],temp_data[12],temp_data[13],temp_data[14],temp_data[15],temp_data[16]) - file.write(data) - #write the skin data - for skin in self.skins: - skin.save(file) - #save the texture coordinates - for tex_coord in self.tex_coords: - tex_coord.save(file) - #save the face info - for face in self.faces: - face.save(file) - #save the frames - for frame in self.frames: - frame.save(file) - for vert in frame.vertices: - vert.save(file) - #save the GL command List - for cmd in self.GL_commands: - cmd.save(file) - def dump (self): - print "Header Information" - print "ident: ", self.ident - print "version: ", self.version - print "skin width: ", self.skin_width - print "skin height: ", self.skin_height - print "frame size: ", self.frame_size - print "number of skins: ", self.num_skins - print "number of texture coordinates: ", self.num_tex_coords - print "number of faces: ", self.num_faces - print "number of frames: ", self.num_frames - print "number of vertices: ", self.num_vertices - print "number of GL commands: ",self.num_GL_commands - print "offset skins: ", self.offset_skins - print "offset texture coordinates: ", self.offset_tex_coords - print "offset faces: ", self.offset_faces - print "offset frames: ",self.offset_frames - print "offset GL Commands: ",self.offset_GL_commands - print "offset end: ",self.offset_end - print "" - -###################################################### -# Validation -###################################################### - -def validation(object): - global user_frame_list - - #get access to the mesh data - mesh=object.getData(False, True) #get the object (not just name) and the Mesh, not NMesh - - #check it's composed of only tri's - result=0 - for face in mesh.faces: - if len(face.verts)!=3: - #select the face for future triangulation - face.sel=1 - if result==0: #first time we have this problem, don't pop-up a window every time it finds a quad - print "Model not made entirely of triangles" - result=Blender.Draw.PupMenu("Model not made entirely out of Triangles-Convert?%t|YES|Quit") - - #triangulate or quit - if result==1: - #selecting face mode - Blender.Mesh.Mode(3) - editmode = Window.EditMode() # are we in edit mode? If so ... - if editmode: Window.EditMode(0) # leave edit mode before getting the mesh - mesh.quadToTriangle(0) #use closest verticies in breaking a quad - elif result==2: - return False #user will fix (I guess) - - #check it has UV coordinates - if mesh.vertexUV==True: - print "Vertex UV not supported" - result=Blender.Draw.PupMenu("Vertex UV not suppored-Use Sticky UV%t|Quit") - return False - - elif mesh.faceUV==True: - for face in mesh.faces: - if(len(face.uv)==3): - pass - else: - print "Model's vertices do not all have UV" - result=Blender.Draw.PupMenu("Model's vertices do not all have UV%t|Quit") - return False - - else: - print "Model does not have UV (face or vertex)" - result=Blender.Draw.PupMenu("Model does not have UV (face or vertex)%t|Output (0,0) as UV coordinates and do not generate GL commands|Quit") - if result==2: - return False - - #check it has an associated texture map - last_face="" - if mesh.faceUV: - last_face=mesh.faces[0].image - #check if each face uses the same texture map (only one allowed) - for face in mesh.faces: - mesh_image=face.image - if not mesh_image: - print "Model has a face without a texture Map" - result=Blender.Draw.PupMenu("Model has a face without a texture Map%t|This should never happen!") - #return False - if mesh_image!=last_face: - print "Model has more than 1 texture map assigned" - result=Blender.Draw.PupMenu("Model has more than 1 texture map assigned%t|Quit") - #return False - if mesh_image: - try: size=mesh_image.getSize() - except: size= 256,256 # No image data - #is this really what the user wants - if (size[0]!=256 or size[1]!=256): - print "Texture map size is non-standard (not 256x256), it is: ",size[0],"x",size[1] - result=Blender.Draw.PupMenu("Texture map size is non-standard (not 256x256), it is: "+str(size[0])+"x"+str(size[1])+": Continue?%t|YES|NO") - if(result==2): - return False - - - #verify frame list data - user_frame_list=get_frame_list() - temp=user_frame_list[len(user_frame_list)-1] - temp_num_frames=temp[2] - - #verify tri/vert/frame counts are within MD2 standard - face_count=len(mesh.faces) - vert_count=len(mesh.verts) - frame_count=temp_num_frames - - if face_count>MD2_MAX_TRIANGLES: - print "Number of triangles exceeds MD2 standard: ", face_count,">",MD2_MAX_TRIANGLES - result=Blender.Draw.PupMenu("Number of triangles exceeds MD2 standard: Continue?%t|YES|NO") - if(result==2): - return False - if vert_count>MD2_MAX_VERTICES: - print "Number of verticies exceeds MD2 standard",vert_count,">",MD2_MAX_VERTICES - result=Blender.Draw.PupMenu("Number of verticies exceeds MD2 standard: Continue?%t|YES|NO") - if(result==2): - return False - if frame_count>MD2_MAX_FRAMES: - print "Number of frames exceeds MD2 standard of",frame_count,">",MD2_MAX_FRAMES - result=Blender.Draw.PupMenu("Number of frames exceeds MD2 standard: Continue?%t|YES|NO") - if(result==2): - return False - #model is OK - return True - -###################################################### -# Fill MD2 data structure -###################################################### -def fill_md2(md2, object): - #global defines - global user_frame_list - global g_texture_path - - Blender.Window.DrawProgressBar(0.25,"Filling MD2 Data") - - #get a Mesh, not NMesh - mesh=object.getData(False, True) - #don't forget to copy the data! -- Boris van Schooten - mesh=mesh.__copy__(); - #load up some intermediate data structures - tex_list={} - tex_count=0 - #create the vertex list from the first frame - Blender.Set("curframe", 1) - - has_uvs = mesh.faceUV - - #header information - md2.ident=844121161 - md2.version=8 - md2.num_vertices=len(mesh.verts) - md2.num_faces=len(mesh.faces) - - #get the skin information - #use the first faces' image for the texture information - if has_uvs: - mesh_image=mesh.faces[0].image - try: size=mesh_image.getSize() - except: size= 256,256 - - md2.skin_width=size[0] - md2.skin_height=size[1] - md2.num_skins=1 - #add a skin node to the md2 data structure - md2.skins.append(md2_skin()) - md2.skins[0].name=g_texture_path.val+Blender.sys.basename(mesh_image.getFilename()) - if len(md2.skins[0].name)>64: - print "Texture Path and name is more than 64 characters" - result=Blender.Draw.PupMenu("Texture path and name is more than 64 characters-Quitting") - return False - - #put texture information in the md2 structure - #build UV coord dictionary (prevents double entries-saves space) - if not has_uvs: - t=(0,0) - - for face in mesh.faces: - for i in xrange(0,3): - if has_uvs: - t=(face.uv[i]) - - tex_key=(t[0],t[1]) - if not tex_list.has_key(tex_key): - tex_list[tex_key]=tex_count - tex_count+=1 - md2.num_tex_coords=tex_count #each vert has its own UV coord - - for this_tex in xrange (0, md2.num_tex_coords): - md2.tex_coords.append(md2_tex_coord()) - for coord, index in tex_list.iteritems(): - #md2.tex_coords.append(md2_tex_coord()) - md2.tex_coords[index].u=int(coord[0]*md2.skin_width) - md2.tex_coords[index].v=int((1-coord[1])*md2.skin_height) - - #put faces in the md2 structure - #for each face in the model - - if not has_uvs: - uv_coords=[(0,0)]*3 - - for this_face in xrange(0, md2.num_faces): - md2.faces.append(md2_face()) - mf = mesh.faces[this_face] - mf_v = mf.v - if has_uvs: - uv_coords = mf.uv - - for i in xrange(0,3): - #blender uses indexed vertexes so this works very well - md2.faces[this_face].vertex_index[i] = mf_v[i].index - #lookup texture index in dictionary - if has_uvs: - uv_coord = uv_coords[i] - # otherwise we set it before - - tex_key=(uv_coord[0],uv_coord[1]) - tex_index=tex_list[tex_key] - md2.faces[this_face].texture_index[i]=tex_index - - Blender.Window.DrawProgressBar(0.5, "Computing GL Commands") - - #compute GL commands - md2.num_GL_commands=build_GL_commands(md2, mesh) - - #get the frame data - #calculate 1 frame size + (1 vert size*num_verts) - md2.frame_size=40+(md2.num_vertices*4) #in bytes - - #get the frame list - user_frame_list=get_frame_list() - if user_frame_list=="default": - md2.num_frames=198 - else: - temp=user_frame_list[len(user_frame_list)-1] #last item - md2.num_frames=temp[2] #last frame number - - - progress=0.5 - progressIncrement=0.25/md2.num_frames - - #fill in each frame with frame info and all the vertex data for that frame - for frame_counter in xrange(0,md2.num_frames): - - progress+=progressIncrement - Blender.Window.DrawProgressBar(progress, "Calculating Frame: %d of %d" % (frame_counter, md2.num_frames)) - - #add a frame - md2.frames.append(md2_frame()) - #update the mesh objects vertex positions for the animation - Blender.Set("curframe", frame_counter) #set blender to the correct frame - - - - - mesh.getFromObject(object) #update the mesh to make verts current - mesh.transform(object.matrixWorld) - -#each frame has a scale and transform value that gets the vertex value between 0-255 -#since the scale and transform are the same for the all the verts in the frame, we only need -#to figure this out once per frame - - #we need to start with the bounding box - #bounding_box=object.getBoundBox() #uses the object, not the mesh data - #initialize with the first vertex for both min and max. X and Y are swapped for MD2 format - - #initialize - frame_min_x=100000.0 - frame_max_x=-100000.0 - frame_min_y=100000.0 - frame_max_y=-100000.0 - frame_min_z=100000.0 - frame_max_z=-100000.0 - - for face in mesh.faces: - for vert in face: - co = vert.co - if frame_min_x>co[1]: frame_min_x=co[1] - if frame_max_x<co[1]: frame_max_x=co[1] - if frame_min_y>co[0]: frame_min_y=co[0] - if frame_max_y<co[0]: frame_max_y=co[0] - if frame_min_z>co[2]: frame_min_z=co[2] - if frame_max_z<co[2]: frame_max_z=co[2] - - #the scale is the difference between the min and max (on that axis) / 255 - frame_scale_x=(frame_max_x-frame_min_x)/255 - frame_scale_y=(frame_max_y-frame_min_y)/255 - frame_scale_z=(frame_max_z-frame_min_z)/255 - - if frame_scale_x == 0: frame_scale_x = 1.0 - if frame_scale_y == 0: frame_scale_y = 1.0 - if frame_scale_z == 0: frame_scale_z = 1.0 - - #translate value of the mesh to center it on the origin - frame_trans_x=frame_min_x - frame_trans_y=frame_min_y - frame_trans_z=frame_min_z - - #fill in the data - md2.frames[frame_counter].scale=(-frame_scale_x, frame_scale_y, frame_scale_z) - md2.frames[frame_counter].translate=(-frame_trans_x, frame_trans_y, frame_trans_z) - - #now for the vertices - for vert_counter in xrange(0, md2.num_vertices): - #add a vertex to the md2 structure - md2.frames[frame_counter].vertices.append(md2_point()) - #figure out the new coords based on scale and transform - #then translates the point so it's not less than 0 - #then scale it so it's between 0..255 - #print "frame scale : ", frame_scale_x, " ", frame_scale_y, " ", frame_scale_z - co = mesh.verts[vert_counter].co - new_x=int((co[1]-frame_trans_x)/frame_scale_x) - new_y=int((co[0]-frame_trans_y)/frame_scale_y) - new_z=int((co[2]-frame_trans_z)/frame_scale_z) - #put them in the structure - md2.frames[frame_counter].vertices[vert_counter].vertices=(new_x, new_y, new_z) - - #need to add the lookup table check here - maxdot = -999999.0; - maxdotindex = -1; - - - #swap y and x for difference in axis orientation - no = mesh.verts[vert_counter].no - x1= -no[1] - y1= no[0] - z1= no[2] - - for j in xrange(0,162): - #dot = (x[0]*y[0]+x[1]*y[1]+x[2]*y[2]) - dot = (x1*MD2_NORMALS[j][0] + y1*MD2_NORMALS[j][1]+ z1*MD2_NORMALS[j][2]); - if (dot > maxdot): - maxdot = dot; - maxdotindex = j; - - # See patch [#19206], gives good info on this line below. - md2.frames[frame_counter].vertices[vert_counter].lightnormalindex=maxdotindex - - del maxdot, maxdotindex - del new_x, new_y, new_z - del frame_max_x, frame_max_y, frame_max_z, frame_min_x, frame_min_y, frame_min_z - del frame_scale_x, frame_scale_y, frame_scale_z, frame_trans_x, frame_trans_y, frame_trans_z - - - #output all the frame names-user_frame_list is loaded during the validation - for frame_set in user_frame_list: - for counter in xrange(frame_set[1]-1, frame_set[2]): - md2.frames[counter].name=frame_set[0]+"_"+str(counter-frame_set[1]+2) - - #compute these after everthing is loaded into a md2 structure - header_size=17*4 #17 integers, and each integer is 4 bytes - skin_size=64*md2.num_skins #64 char per skin * number of skins - tex_coord_size=4*md2.num_tex_coords #2 short * number of texture coords - face_size=12*md2.num_faces #3 shorts for vertex index, 3 shorts for tex index - frames_size=(((12+12+16)+(4*md2.num_vertices)) * md2.num_frames) #frame info+verts per frame*num frames - GL_command_size=md2.num_GL_commands*4 #each is an int or float, so 4 bytes per - - #fill in the info about offsets - md2.offset_skins=0+header_size - md2.offset_tex_coords=md2.offset_skins+skin_size - md2.offset_faces=md2.offset_tex_coords+tex_coord_size - md2.offset_frames=md2.offset_faces+face_size - md2.offset_GL_commands=md2.offset_frames+frames_size - md2.offset_end=md2.offset_GL_commands+GL_command_size - -###################################################### -# Get Frame List -###################################################### -def get_frame_list(): - global g_frame_filename - frame_list=[] - - if g_frame_filename.val=="default": - return MD2_FRAME_NAME_LIST - - else: - #check for file - if (Blender.sys.exists(g_frame_filename.val)==1): - #open file and read it in - file=open(g_frame_filename.val,"r") - lines=file.readlines() - file.close() - - #check header (first line) - if lines[0].strip() != "# MD2 Frame Name List": - print "its not a valid file" - result=Blender.Draw.PupMenu("This is not a valid frame definition file-using default%t|OK") - return MD2_FRAME_NAME_LIST - else: - #read in the data - num_frames=0 - for counter in xrange(1, len(lines)): - current_line=lines[counter].strip() - if current_line[0]=="#": - #found a comment - pass - else: - data=current_line.split() - frame_list.append([data[0],num_frames+1, num_frames+int(data[1])]) - num_frames+=int(data[1]) - return frame_list - else: - print "Cannot find file" - result=Blender.Draw.PupMenu("Cannot find frame definion file-using default%t|OK") - return MD2_FRAME_NAME_LIST - -###################################################### -# Globals for GL command list calculations -###################################################### -used_tris=[] -edge_dict={} -strip_verts=[] -strip_st=[] -strip_tris=[] -strip_first_run=True -odd=False - -###################################################### -# Find Strip length function -###################################################### -def find_strip_length(mesh, start_tri, edge_key): - #print "Finding strip length" - - global used_tris - global edge_dict - global strip_tris - global strip_st - global strip_verts - global strip_first_run - global odd - - used_tris[start_tri]=2 - - strip_tris.append(start_tri) #add this tri to the potential list of tri-strip - - #print "I am face: ", start_tri - #print "Using edge Key: ", edge_key - - faces=edge_dict[edge_key] #get list of face indexes that share this edge - if (len(faces)==0): - #print "Cant find edge with key: ", edge_key - pass - - #print "Faces sharing this edge: ", faces - for face_index in faces: - face=mesh.faces[face_index] - if face_index==start_tri: #don't want to check myself - #print "I found myself, continuing" - pass - else: - if used_tris[face_index]!=0: #found a used tri-move along - #print "Found a used tri: ", face_index - pass - else: - #find non-shared vert - for vert_counter in xrange(0,3): - if (face.verts[vert_counter].index!=edge_key[0] and face.verts[vert_counter].index!=edge_key[1]): - next_vert=vert_counter - - if(odd==False): - #print "Found a suitable even connecting tri: ", face_index - used_tris[face_index]=2 #mark as dirty for this rum - odd=True - - #find the new edge - if(face.verts[next_vert].index < face.verts[(next_vert+2)%3].index): - temp_key=(face.verts[next_vert].index,face.verts[(next_vert+2)%3].index) - else: - temp_key=(face.verts[(next_vert+2)%3].index, face.verts[next_vert].index) - - #print "temp key: ", temp_key - temp_faces=edge_dict[temp_key] - - if(len(temp_faces)==0): - print "Can't find any other faces with key: ", temp_key - else: - #search the new edge - #print "found other faces, searching them" - find_strip_length(mesh, face_index, temp_key) #recursive greedy-takes first tri it finds as best - break; - else: - #print "Found a suitable odd connecting tri: ", face_index - used_tris[face_index]=2 #mark as dirty for this rum - odd=False - - #find the new edge - if(face.verts[next_vert].index < face.verts[(next_vert+1)%3].index): - temp_key=(face.verts[next_vert].index,face.verts[(next_vert+1)%3].index) - else: - temp_key=(face.verts[(next_vert+1)%3].index, face.verts[next_vert].index) - #print "temp key: ", temp_key - temp_faces=edge_dict[temp_key] - if(len(temp_faces)==0): - print "Can't find any other faces with key: ", temp_key - else: - #search the new edge - #print "found other faces, searching them" - find_strip_length(mesh, face_index, temp_key) #recursive greedy-takes first tri it finds as best - break; - - return len(strip_tris) - - -###################################################### -# Tri-Stripify function -###################################################### -def stripify_tri_list(mesh, edge_key): - global edge_dict - global strip_tris - global strip_st - global strip_verts - - shared_edge=[] - key=[] - - #print "*****Stripify the triangle list*******" - #print "strip tris: ", strip_tris - #print "strip_tri length: ", len(strip_tris) - - for tri_counter in xrange(0, len(strip_tris)): - face=mesh.faces[strip_tris[tri_counter]] - if (tri_counter==0): #first one only - #find non-edge vert - for vert_counter in xrange(0,3): - if (face.verts[vert_counter].index!=edge_key[0] and face.verts[vert_counter].index!=edge_key[1]): - start_vert=vert_counter - strip_verts.append(face.verts[start_vert].index) - strip_st.append(face.uv[start_vert]) - - strip_verts.append(face.verts[(start_vert+2)%3].index) - strip_st.append(face.uv[(start_vert+2)%3]) - - strip_verts.append(face.verts[(start_vert+1)%3].index) - strip_st.append(face.uv[(start_vert+1)%3]) - else: - for vert_counter in xrange(0,3): - if(face.verts[vert_counter].index!=strip_verts[-1] and face.verts[vert_counter].index!=strip_verts[-2]): - strip_verts.append(face.verts[vert_counter].index) - strip_st.append(face.uv[vert_counter]) - break - - - -###################################################### -# Build GL command List -###################################################### -def build_GL_commands(md2, mesh): - # we can't output gl command structure without uv - if not mesh.faceUV: - print "No UV: not building GL Commands" - return 0 - - print "Building GL Commands" - - global used_tris - global edge_dict - global strip_verts - global strip_tris - global strip_st - - #globals initialization - used_tris=[0]*len(mesh.faces) - #print "Used: ", used_tris - num_commands=0 - - #edge dictionary generation - edge_dict=dict([(ed.key,[]) for ed in mesh.edges]) - for face in (mesh.faces): - for key in face.edge_keys: - edge_dict[key].append(face.index) - - #print "edge Dict: ", edge_dict - - for tri_counter in xrange(0,len(mesh.faces)): - if used_tris[tri_counter]!=0: - #print "Found a used triangle: ", tri_counter - pass - else: - #print "Found an unused triangle: ", tri_counter - - #intialization - strip_tris=[0]*0 - strip_verts=[0]*0 - strip_st=[0]*0 - strip_first_run=True - odd=True - - #find the strip length - strip_length=find_strip_length(mesh, tri_counter, mesh.faces[tri_counter].edge_keys[0]) - - #mark tris as used - for used_counter in xrange(0,strip_length): - used_tris[strip_tris[used_counter]]=1 - - stripify_tri_list(mesh, mesh.faces[tri_counter].edge_keys[0]) - - #create command list - cmd_list=md2_GL_cmd_list() - #number of commands in this list - print "strip length: ", strip_length - cmd_list.num=(len(strip_tris)+2) #positive for strips, fans would be negative, but not supported yet - num_commands+=1 - - #add s,t,vert for this command list - for command_counter in xrange(0, len(strip_tris)+2): - cmd=md2_GL_command() - cmd.s=strip_st[command_counter][0] - cmd.t=1.0-strip_st[command_counter][1] #flip upside down - cmd.vert_index=strip_verts[command_counter] - num_commands+=3 - cmd_list.cmd_list.append(cmd) - print "Cmd List length: ", len(cmd_list.cmd_list) - print "Cmd list num: ", cmd_list.num - print "Cmd List: ", cmd_list.dump() - md2.GL_commands.append(cmd_list) - - #add the null command at the end - temp_cmdlist=md2_GL_cmd_list() - temp_cmdlist.num=0 - md2.GL_commands.append(temp_cmdlist) - num_commands+=1 - - #cleanup and return - used=strip_vert=strip_st=strip_tris=0 - return num_commands - - - - -###################################################### -# Save MD2 Format -###################################################### -def save_md2(filename): - print "" - print "***********************************" - print "MD2 Export" - print "***********************************" - print "" - - Blender.Window.DrawProgressBar(0.0,"Begining MD2 Export") - - md2=md2_obj() #blank md2 object to save - - #get the object - mesh_objs = Blender.Object.GetSelected() - - #check there is a blender object selected - if len(mesh_objs)==0: - print "Fatal Error: Must select a mesh to output as MD2" - print "Found nothing" - result=Blender.Draw.PupMenu("Must select an object to export%t|OK") - return - - mesh_obj=mesh_objs[0] #this gets the first object (should be only one) - - #check if it's a mesh object - if mesh_obj.getType()!="Mesh": - print "Fatal Error: Must select a mesh to output as MD2" - print "Found: ", mesh_obj.getType() - result=Blender.Draw.PupMenu("Selected Object must be a mesh to output as MD2%t|OK") - return - - ok=validation(mesh_obj) - if ok==False: - return - - fill_md2(md2, mesh_obj) - md2.dump() - - Blender.Window.DrawProgressBar(1.0, "Writing to Disk") - - #actually write it to disk - file=open(filename,"wb") - md2.save(file) - file.close() - - #cleanup - md2=0 - - print "Closed the file" - diff --git a/release/scripts/md2_import.py b/release/scripts/md2_import.py deleted file mode 100644 index f52746259a6..00000000000 --- a/release/scripts/md2_import.py +++ /dev/null @@ -1,600 +0,0 @@ -#!BPY - -""" -Name: 'MD2 (.md2)' -Blender: 239 -Group: 'Import' -Tooltip: 'Import from Quake file format (.md2).' -""" - -__author__ = 'Bob Holcomb' -__version__ = '0.16' -__url__ = ["Bob's site, http://bane.servebeer.com", - "Support forum, http://scourage.servebeer.com/phpbb/", "blender", "blenderartists.org"] -__email__ = ["Bob Holcomb, bob_holcomb:hotmail*com", "scripts"] -__bpydoc__ = """\ -This script imports a Quake 2 file (MD2), textures, -and animations into blender for editing. Loader is based on MD2 loader from www.gametutorials.com-Thanks DigiBen! and the md3 blender loader by PhaethonH <phaethon@linux.ucla.edu><br> - - Additional help from: Shadwolf, Skandal, Rojo and Campbell Barton<br> - Thanks Guys! -""" - -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Script copyright (C) Bob Holcomb -# -# 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 ***** -# -------------------------------------------------------------------------- - - -import Blender -from Blender import Mesh, Object, sys -from Blender.BGL import * -from Blender.Draw import * -from Blender.Window import * -from Blender.Mathutils import Vector -import struct -from types import * - - -###################################################### -# Main Body -###################################################### - -#returns the string from a null terminated string -def asciiz (s): - n = 0 - while (ord(s[n]) != 0): - n = n + 1 - return s[0:n] - - -###################################################### -# MD2 Model Constants -###################################################### -MD2_MAX_TRIANGLES=4096 -MD2_MAX_VERTICES=2048 -MD2_MAX_TEXCOORDS=2048 -MD2_MAX_FRAMES=512 -MD2_MAX_SKINS=32 -MD2_MAX_FRAMESIZE=(MD2_MAX_VERTICES * 4 + 128) - -###################################################### -# MD2 data structures -###################################################### -class md2_alias_triangle(object): - __slots__ = 'vertices', 'lightnormalindex' - binary_format="<3BB" #little-endian (<), 3 Unsigned char - - def __init__(self): - self.vertices=[0]*3 - self.lightnormalindex=0 - - def load(self, file): - temp_data = file.read(struct.calcsize(self.binary_format)) - data = struct.unpack(self.binary_format, temp_data) - self.vertices[0]=data[0] - self.vertices[1]=data[1] - self.vertices[2]=data[2] - self.lightnormalindex=data[3] - return self - - def dump(self): - print "MD2 Alias_Triangle Structure" - print "vertex: ", self.vertices[0] - print "vertex: ", self.vertices[1] - print "vertex: ", self.vertices[2] - print "lightnormalindex: ",self.lightnormalindex - print "" - -class md2_face(object): - - binary_format="<3h3h" #little-endian (<), 3 short, 3 short - - __slots__ = 'vertex_index', 'texture_index' - - def __init__(self): - self.vertex_index = [ 0, 0, 0 ] - self.texture_index = [ 0, 0, 0] - - def load (self, file): - temp_data=file.read(struct.calcsize(self.binary_format)) - data=struct.unpack(self.binary_format, temp_data) - self.vertex_index[0]=data[0] - self.vertex_index[1]=data[1] - self.vertex_index[2]=data[2] - self.texture_index[0]=data[3] - self.texture_index[1]=data[4] - self.texture_index[2]=data[5] - return self - - def dump (self): - print "MD2 Face Structure" - print "vertex index: ", self.vertex_index[0] - print "vertex index: ", self.vertex_index[1] - print "vertex index: ", self.vertex_index[2] - print "texture index: ", self.texture_index[0] - print "texture index: ", self.texture_index[1] - print "texture index: ", self.texture_index[2] - print "" - -class md2_tex_coord(object): - __slots__ = 'u', 'v' - binary_format="<2h" #little-endian (<), 2 unsigned short - - def __init__(self): - self.u=0 - self.v=0 - - def load (self, file): - temp_data=file.read(struct.calcsize(self.binary_format)) - data=struct.unpack(self.binary_format, temp_data) - self.u=data[0] - self.v=data[1] - return self - - def dump (self): - print "MD2 Texture Coordinate Structure" - print "texture coordinate u: ",self.u - print "texture coordinate v: ",self.v - print "" - - -class md2_skin(object): - __slots__ = 'name' - binary_format="<64s" #little-endian (<), char[64] - - def __init__(self): - self.name="" - - def load (self, file): - temp_data=file.read(struct.calcsize(self.binary_format)) - data=struct.unpack(self.binary_format, temp_data) - self.name=asciiz(data[0]) - return self - - def dump (self): - print "MD2 Skin" - print "skin name: ",self.name - print "" - -class md2_alias_frame(object): - __slots__ = 'scale', 'translate', 'name', 'vertices' - binary_format="<3f3f16s" #little-endian (<), 3 float, 3 float char[16] - #did not add the "3bb" to the end of the binary format - #because the alias_vertices will be read in through - #thier own loader - - def __init__(self): - self.scale=[0.0]*3 - self.translate=[0.0]*3 - self.name="" - self.vertices=[] - - - def load (self, file): - temp_data=file.read(struct.calcsize(self.binary_format)) - data=struct.unpack(self.binary_format, temp_data) - self.scale[0]=data[0] - self.scale[1]=data[1] - self.scale[2]=data[2] - self.translate[0]=data[3] - self.translate[1]=data[4] - self.translate[2]=data[5] - self.name=asciiz(data[6]) - return self - - def dump (self): - print "MD2 Alias Frame" - print "scale x: ",self.scale[0] - print "scale y: ",self.scale[1] - print "scale z: ",self.scale[2] - print "translate x: ",self.translate[0] - print "translate y: ",self.translate[1] - print "translate z: ",self.translate[2] - print "name: ",self.name - print "" - -class md2_obj(object): - __slots__ =\ - 'tex_coords', 'faces', 'frames',\ - 'skins', 'ident', 'version',\ - 'skin_width', 'skin_height',\ - 'frame_size', 'num_skins', 'num_vertices',\ - 'num_tex_coords', 'num_faces', 'num_GL_commands',\ - 'num_frames', 'offset_skins', 'offset_tex_coords',\ - 'offset_faces', 'offset_frames', 'offset_GL_commands' - - ''' - #Header Structure - ident=0 #int 0 This is used to identify the file - version=0 #int 1 The version number of the file (Must be 8) - skin_width=0 #int 2 The skin width in pixels - skin_height=0 #int 3 The skin height in pixels - frame_size=0 #int 4 The size in bytes the frames are - num_skins=0 #int 5 The number of skins associated with the model - num_vertices=0 #int 6 The number of vertices (constant for each frame) - num_tex_coords=0 #int 7 The number of texture coordinates - num_faces=0 #int 8 The number of faces (polygons) - num_GL_commands=0 #int 9 The number of gl commands - num_frames=0 #int 10 The number of animation frames - offset_skins=0 #int 11 The offset in the file for the skin data - offset_tex_coords=0 #int 12 The offset in the file for the texture data - offset_faces=0 #int 13 The offset in the file for the face data - offset_frames=0 #int 14 The offset in the file for the frames data - offset_GL_commands=0#int 15 The offset in the file for the gl commands data - offset_end=0 #int 16 The end of the file offset - ''' - binary_format="<17i" #little-endian (<), 17 integers (17i) - - #md2 data objects - - def __init__ (self): - self.tex_coords=[] - self.faces=[] - self.frames=[] - self.skins=[] - - - def load (self, file): - temp_data = file.read(struct.calcsize(self.binary_format)) - data = struct.unpack(self.binary_format, temp_data) - - self.ident=data[0] - self.version=data[1] - - if (self.ident!=844121161 or self.version!=8): - print "Not a valid MD2 file" - Exit() - - self.skin_width=data[2] - self.skin_height=data[3] - self.frame_size=data[4] - - #make the # of skin objects for model - self.num_skins=data[5] - for i in xrange(0,self.num_skins): - self.skins.append(md2_skin()) - - self.num_vertices=data[6] - - #make the # of texture coordinates for model - self.num_tex_coords=data[7] - for i in xrange(0,self.num_tex_coords): - self.tex_coords.append(md2_tex_coord()) - - #make the # of triangle faces for model - self.num_faces=data[8] - for i in xrange(0,self.num_faces): - self.faces.append(md2_face()) - - self.num_GL_commands=data[9] - - #make the # of frames for the model - self.num_frames=data[10] - for i in xrange(0,self.num_frames): - self.frames.append(md2_alias_frame()) - #make the # of vertices for each frame - for j in xrange(0,self.num_vertices): - self.frames[i].vertices.append(md2_alias_triangle()) - - self.offset_skins=data[11] - self.offset_tex_coords=data[12] - self.offset_faces=data[13] - self.offset_frames=data[14] - self.offset_GL_commands=data[15] - - #load the skin info - file.seek(self.offset_skins,0) - for i in xrange(0, self.num_skins): - self.skins[i].load(file) - #self.skins[i].dump() - - #load the texture coordinates - file.seek(self.offset_tex_coords,0) - for i in xrange(0, self.num_tex_coords): - self.tex_coords[i].load(file) - #self.tex_coords[i].dump() - - #load the face info - file.seek(self.offset_faces,0) - for i in xrange(0, self.num_faces): - self.faces[i].load(file) - #self.faces[i].dump() - - #load the frames - file.seek(self.offset_frames,0) - for i in xrange(0, self.num_frames): - self.frames[i].load(file) - #self.frames[i].dump() - for j in xrange(0,self.num_vertices): - self.frames[i].vertices[j].load(file) - #self.frames[i].vertices[j].dump() - return self - - def dump (self): - print "Header Information" - print "ident: ", self.ident - print "version: ", self.version - print "skin width: ", self.skin_width - print "skin height: ", self.skin_height - print "frame size: ", self.frame_size - print "number of skins: ", self.num_skins - print "number of texture coordinates: ", self.num_tex_coords - print "number of faces: ", self.num_faces - print "number of frames: ", self.num_frames - print "number of vertices: ", self.num_vertices - print "offset skins: ", self.offset_skins - print "offset texture coordinates: ", self.offset_tex_coords - print "offset faces: ", self.offset_faces - print "offset frames: ",self.offset_frames - print "" - -###################################################### -# Import functions -###################################################### -def load_textures(md2, texture_filename): - #did the user specify a texture they wanted to use? - if texture_filename: - if (Blender.sys.exists(texture_filename)): - try: return Blender.Image.Load(texture_filename) - except: return -1 # could not load? - - #does the model have textures specified with it? - if int(md2.num_skins) > 0: - for i in xrange(0,md2.num_skins): - #md2.skins[i].dump() - if (Blender.sys.exists(md2.skins[i].name)): - try: return Blender.Image.Load(md2.skins[i].name) - except: return -1 - - -def animate_md2(md2, mesh): - ######### Animate the verts through keyframe animation - - # Fast access to the meshes vertex coords - verts = [v.co for v in mesh.verts] - scale = g_scale.val - - for i in xrange(1, md2.num_frames): - frame = md2.frames[i] - #update the vertices - for j in xrange(md2.num_vertices): - x=(frame.scale[0] * frame.vertices[j].vertices[0] + frame.translate[0]) * scale - y=(frame.scale[1] * frame.vertices[j].vertices[1] + frame.translate[1]) * scale - z=(frame.scale[2] * frame.vertices[j].vertices[2] + frame.translate[2]) * scale - - #put the vertex in the right spot - verts[j][:] = y,-x,z - - mesh.insertKey(i,"absolute") - # mesh.insertKey(i) - - #not really necissary, but I like playing with the frame counter - Blender.Set("curframe", i) - - - # Make the keys animate in the 3d view. - key = mesh.key - key.relative = False - - # Add an IPO to teh Key - ipo = Blender.Ipo.New('Key', 'md2') - key.ipo = ipo - # Add a curve to the IPO - curve = ipo.addCurve('Basis') - - # Add 2 points to cycle through the frames. - curve.append((1, 0)) - curve.append((md2.num_frames, (md2.num_frames-1)/10.0)) - curve.interpolation = Blender.IpoCurve.InterpTypes.LINEAR - - - -def load_md2(md2_filename, texture_filename): - #read the file in - file=open(md2_filename,"rb") - WaitCursor(1) - DrawProgressBar(0.0, 'Loading MD2') - md2=md2_obj() - md2.load(file) - #md2.dump() - file.close() - - ######### Creates a new mesh - mesh = Mesh.New() - - uv_coord=[] - #uv_list=[] - verts_extend = [] - #load the textures to use later - #-1 if there is no texture to load - mesh_image=load_textures(md2, texture_filename) - if mesh_image == -1 and texture_filename: - print 'MD2 Import, Warning, texture "%s" could not load' - - ######### Make the verts - DrawProgressBar(0.25,"Loading Vertex Data") - frame = md2.frames[0] - scale = g_scale.val - - def tmp_get_vertex(i): - #use the first frame for the mesh vertices - x=(frame.scale[0]*frame.vertices[i].vertices[0]+frame.translate[0])*scale - y=(frame.scale[1]*frame.vertices[i].vertices[1]+frame.translate[1])*scale - z=(frame.scale[2]*frame.vertices[i].vertices[2]+frame.translate[2])*scale - return y,-x,z - - mesh.verts.extend( [tmp_get_vertex(i) for i in xrange(0,md2.num_vertices)] ) - del tmp_get_vertex - - ######## Make the UV list - DrawProgressBar(0.50,"Loading UV Data") - - w = float(md2.skin_width) - h = float(md2.skin_height) - if w <= 0.0: w = 1.0 - if h <= 0.0: h = 1.0 - #for some reason quake2 texture maps are upside down, flip that - uv_list = [Vector(co.u/w, 1-(co.v/h)) for co in md2.tex_coords] - del w, h - - ######### Make the faces - DrawProgressBar(0.75,"Loading Face Data") - faces = [] - face_uvs = [] - for md2_face in md2.faces: - f = md2_face.vertex_index[0], md2_face.vertex_index[2], md2_face.vertex_index[1] - uv = uv_list[md2_face.texture_index[0]], uv_list[md2_face.texture_index[2]], uv_list[md2_face.texture_index[1]] - - if f[2] == 0: - # EEKADOODLE :/ - f= f[1], f[2], f[0] - uv= uv[1], uv[2], uv[0] - - #ditto in reverse order with the texture verts - faces.append(f) - face_uvs.append(uv) - - - face_mapping = mesh.faces.extend(faces, indexList=True) - print len(faces) - print len(mesh.faces) - mesh.faceUV= True #turn on face UV coordinates for this mesh - mesh_faces = mesh.faces - for i, uv in enumerate(face_uvs): - if face_mapping[i] != None: - f = mesh_faces[face_mapping[i]] - f.uv = uv - if (mesh_image!=-1): - f.image=mesh_image - - scn= Blender.Scene.GetCurrent() - mesh_obj= scn.objects.new(mesh) - animate_md2(md2, mesh) - DrawProgressBar(0.98,"Loading Animation Data") - - #locate the Object containing the mesh at the cursor location - cursor_pos=Blender.Window.GetCursorPos() - mesh_obj.setLocation(float(cursor_pos[0]),float(cursor_pos[1]),float(cursor_pos[2])) - DrawProgressBar (1.0, "") - WaitCursor(0) - -#*********************************************** -# MAIN -#*********************************************** - -# Import globals -g_md2_filename=Create("*.md2") -#g_md2_filename=Create("/d/warvet/tris.md2") -g_texture_filename=Create('') -# g_texture_filename=Create("/d/warvet/warvet.jpg") - -g_filename_search=Create("*.md2") -g_texture_search=Create('') -# g_texture_search=Create("/d/warvet/warvet.jpg") - -#Globals -g_scale=Create(1.0) - -# Events -EVENT_NOEVENT=1 -EVENT_LOAD_MD2=2 -EVENT_CHOOSE_FILENAME=3 -EVENT_CHOOSE_TEXTURE=4 -EVENT_SAVE_MD2=5 -EVENT_EXIT=100 - -###################################################### -# Callbacks for Window functions -###################################################### -def filename_callback(input_filename): - global g_md2_filename - g_md2_filename.val=input_filename - -def texture_callback(input_texture): - global g_texture_filename - g_texture_filename.val=input_texture - -###################################################### -# GUI Loader -###################################################### - - -def draw_gui(): - global g_scale - global g_md2_filename - global g_texture_filename - global EVENT_NOEVENT,EVENT_LOAD_MD2,EVENT_CHOOSE_FILENAME,EVENT_CHOOSE_TEXTURE,EVENT_EXIT - - ########## Titles - glClear(GL_COLOR_BUFFER_BIT) - glRasterPos2d(8, 125) - Text("MD2 loader") - - ######### Parameters GUI Buttons - BeginAlign() - g_md2_filename = String("MD2 file to load: ", EVENT_NOEVENT, 10, 55, 210, 18, - g_md2_filename.val, 255, "MD2 file to load") - ########## MD2 File Search Button - Button("Browse",EVENT_CHOOSE_FILENAME,220,55,80,18) - EndAlign() - - BeginAlign() - g_texture_filename = String("Texture file to load: ", EVENT_NOEVENT, 10, 35, 210, 18, - g_texture_filename.val, 255, "Texture file to load-overrides MD2 file") - ########## Texture Search Button - Button("Browse",EVENT_CHOOSE_TEXTURE,220,35,80,18) - EndAlign() - - ########## Scale slider-default is 1/8 which is a good scale for md2->blender - g_scale= Slider("Scale Factor: ", EVENT_NOEVENT, 10, 75, 210, 18, - 1.0, 0.001, 10.0, 1, "Scale factor for obj Model"); - - ######### Draw and Exit Buttons - Button("Load",EVENT_LOAD_MD2 , 10, 10, 80, 18) - Button("Exit",EVENT_EXIT , 170, 10, 80, 18) - -def event(evt, val): - if (evt == QKEY and not val): - Blender.Draw.Exit() - -def bevent(evt): - global g_md2_filename - global g_texture_filename - global EVENT_NOEVENT,EVENT_LOAD_MD2,EVENT_SAVE_MD2,EVENT_EXIT - - ######### Manages GUI events - if (evt==EVENT_EXIT): - Blender.Draw.Exit() - elif (evt==EVENT_CHOOSE_FILENAME): - FileSelector(filename_callback, "MD2 File Selection") - elif (evt==EVENT_CHOOSE_TEXTURE): - FileSelector(texture_callback, "Texture Selection") - elif (evt==EVENT_LOAD_MD2): - if not Blender.sys.exists(g_md2_filename.val): - PupMenu('Model file does not exist') - return - else: - load_md2(g_md2_filename.val, g_texture_filename.val) - Blender.Redraw() - Blender.Draw.Exit() - return - -if __name__ == '__main__': - Register(draw_gui, event, bevent) diff --git a/release/scripts/mesh_boneweight_copy.py b/release/scripts/mesh_boneweight_copy.py deleted file mode 100644 index d2a477fbc0b..00000000000 --- a/release/scripts/mesh_boneweight_copy.py +++ /dev/null @@ -1,287 +0,0 @@ -#!BPY -""" -Name: 'Bone Weight Copy' -Blender: 245 -Group: 'Object' -Tooltip: 'Copy Bone Weights from 1 mesh, to all other selected meshes.' -""" - -__author__ = "Campbell Barton aka ideasman42" -__url__ = ["www.blender.org", "blenderartists.org", "www.python.org"] -__version__ = "0.1" -__bpydoc__ = """\ - -Bone Weight Copy - -This script is used to copy bone weights from 1 mesh with weights (the source mesh) to many (the target meshes). -Weights are copied from 1 mesh to another based on how close they are together. - -For normal operation, select 1 source mesh with vertex weights and any number of unweighted meshes that overlap the source mesh. -Then run this script using default options and check the new weigh. - - -A differnt way to use this script is to update the weights an an alredy weighted mesh. -this is done using the "Copy to Selected" option enabled and works a bit differently, -With the target mesh, select the verts you want to update. -since all meshes have weights we cant just use the weighted mesh as the source, -so the Active Object is used for the source mesh. -Run the script and the selected verts on all non active meshes will be updated. -""" - -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Script copyright (C) Campbell J Barton -# -# 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 ***** -# -------------------------------------------------------------------------- - -import Blender -from Blender import Armature, Object, Mathutils, Window, Mesh -Vector= Mathutils.Vector -SMALL_NUM= 0.000001 -def copy_bone_influences(_from, _to, PREF_SEL_ONLY, PREF_NO_XCROSS): - ob_from, me_from, world_verts_from, from_groups= _from - ob_to, me_to, world_verts_to, dummy= _to - del dummy - - def getSnapIdx(seek_vec, vecs): - ''' - Returns the closest vec to snap_points - ''' - - # First seek the closest Z axis vert idx/v - seek_vec_x,seek_vec_y,seek_vec_z= seek_vec - - from_vec_idx= 0 - - len_vecs= len(vecs) - - upidx= len_vecs-1 - loidx= 0 - - while from_vec_idx < len_vecs and vecs[from_vec_idx][1].z < seek_vec_z: - from_vec_idx+=1 - - # Clamp if we overstepped. - if from_vec_idx >= len_vecs: - from_vec_idx-=1 - - close_dist= (vecs[from_vec_idx][1]-seek_vec).length - close_idx= vecs[from_vec_idx][0] - - upidx= from_vec_idx+1 - loidx= from_vec_idx-1 - - # Set uselo/useup. This means we can keep seeking up/down. - if upidx >= len_vecs: useup= False - else: useup= True - - if loidx < 0: uselo= False - else: uselo= True - - # Seek up/down to find the closest v to seek vec. - while uselo or useup: - if useup: - if upidx >= len_vecs: - useup= False - else: - i,v= vecs[upidx] - if (not PREF_NO_XCROSS) or ((v.x >= -SMALL_NUM and seek_vec_x >= -SMALL_NUM) or (v.x <= SMALL_NUM and seek_vec_x <= SMALL_NUM)): # enfoce xcrossing - if v.z-seek_vec_z > close_dist: - # the verticle distance is greater then the best distance sofar. we can stop looking up. - useup= False - elif abs(seek_vec_y-v.y) < close_dist and abs(seek_vec_x-v.x) < close_dist: - # This is in the limit measure it. - l= (seek_vec-v).length - if l<close_dist: - close_dist= l - close_idx= i - upidx+=1 - - if uselo: - - if loidx == 0: - uselo= False - else: - i,v= vecs[loidx] - if (not PREF_NO_XCROSS) or ((v.x >= -SMALL_NUM and seek_vec_x >= -SMALL_NUM) or (v.x <= SMALL_NUM and seek_vec_x <= SMALL_NUM)): # enfoce xcrossing - if seek_vec_z-v.z > close_dist: - # the verticle distance is greater then the best distance sofar. we can stop looking up. - uselo= False - elif abs(seek_vec_y-v.y) < close_dist and abs(seek_vec_x-v.x) < close_dist: - # This is in the limit measure it. - l= (seek_vec-v).length - if l<close_dist: - close_dist= l - close_idx= i - loidx-=1 - - return close_idx - - - to_groups= me_to.getVertGroupNames() # if not PREF_SEL_ONLY will always be [] - from_groups= me_from.getVertGroupNames() - - if PREF_SEL_ONLY: # remove selected verts from all groups. - vsel= [v.index for v in me_to.verts if v.sel] - for group in to_groups: - me_to.removeVertsFromGroup(group, vsel) - else: # Add all groups. - for group in from_groups: - me_to.addVertGroup(group) - - add_ = Mesh.AssignModes.ADD - - for i, co in enumerate(world_verts_to): - if (not PREF_SEL_ONLY) or (PREF_SEL_ONLY and me_to.verts[i].sel): - - Window.DrawProgressBar(0.99 * (i/float(len(world_verts_to))), 'Copy "%s" -> "%s" ' % (ob_from.name, ob_to.name)) - - from_idx= getSnapIdx(co, world_verts_from) - from_infs= me_from.getVertexInfluences(from_idx) - - for group, weight in from_infs: - - # Add where needed. - if PREF_SEL_ONLY and group not in to_groups: - me_to.addVertGroup(group) - to_groups.append(group) - - me_to.assignVertsToGroup(group, [i], weight, add_) - - me_to.update() - -# ZSORT return (i/co) tuples, used for fast seeking of the snapvert. -def worldspace_verts_idx(me, ob): - mat= ob.matrixWorld - verts_zsort= [ (i, v.co*mat) for i, v in enumerate(me.verts) ] - - # Sorts along the Z Axis so we can optimize the getsnap. - try: verts_zsort.sort(key = lambda a: a[1].z) - except: verts_zsort.sort(lambda a,b: cmp(a[1].z, b[1].z,)) - - return verts_zsort - - -def worldspace_verts(me, ob): - mat= ob.matrixWorld - return [ v.co*mat for v in me.verts ] - -def subdivMesh(me, subdivs): - oldmode = Mesh.Mode() - Mesh.Mode(Mesh.SelectModes['FACE']) - me.sel= 1 - for i in xrange(subdivs): - me.subdivide(0) - Mesh.Mode(oldmode) - - -def main(): - print '\nStarting BoneWeight Copy...' - scn= Blender.Scene.GetCurrent() - contextSel= Object.GetSelected() - if not contextSel: - Blender.Draw.PupMenu('Error%t|2 or more mesh objects need to be selected.|aborting.') - return - - PREF_QUALITY= Blender.Draw.Create(0) - PREF_NO_XCROSS= Blender.Draw.Create(0) - PREF_SEL_ONLY= Blender.Draw.Create(0) - - pup_block = [\ - ('Quality:', PREF_QUALITY, 0, 4, 'Generate interpolated verts for a higher quality result.'),\ - ('No X Crossing', PREF_NO_XCROSS, 'Do not snap across the zero X axis'),\ - '',\ - '"Update Selected" copies',\ - 'active object weights to',\ - 'selected verts on the other',\ - 'selected mesh objects.',\ - ('Update Selected', PREF_SEL_ONLY, 'Only copy new weights to selected verts on the target mesh. (use active object as source)'),\ - ] - - - if not Blender.Draw.PupBlock("Copy Weights for %i Meshs" % len(contextSel), pup_block): - return - - PREF_SEL_ONLY= PREF_SEL_ONLY.val - PREF_NO_XCROSS= PREF_NO_XCROSS.val - quality= PREF_QUALITY.val - - act_ob= scn.objects.active - if PREF_SEL_ONLY and act_ob==None: - Blender.Draw.PupMenu('Error%t|When dealing with 2 or more meshes with vgroups|There must be an active object|to be used as a source|aborting.') - return - - sel=[] - from_data= None - - for ob in contextSel: - if ob.type=='Mesh': - me= ob.getData(mesh=1) - groups= me.getVertGroupNames() - - # If this is the only mesh with a group OR if its one of many, but its active. - if groups and ((ob==act_ob and PREF_SEL_ONLY) or (not PREF_SEL_ONLY)): - if from_data: - Blender.Draw.PupMenu('More then 1 mesh has vertex weights, only select 1 mesh with weights. aborting.') - return - else: - # This uses worldspace_verts_idx which gets (idx,co) pairs, then zsorts. - if quality: - for _ob in contextSel: - _ob.sel=0 - ob.sel=1 - Object.Duplicate(mesh=1) - ob= scn.objects.active - me= ob.getData(mesh=1) - # groups will be the same - print '\tGenerating higher %ix quality weights.' % quality - subdivMesh(me, quality) - scn.unlink(ob) - from_data= (ob, me, worldspace_verts_idx(me, ob), groups) - - else: - data= (ob, me, worldspace_verts(me, ob), groups) - sel.append(data) - - if not from_data: - Blender.Draw.PupMenu('Error%t|No mesh with vertex groups found.') - return - - if not sel: - Blender.Draw.PupMenu('Error%t|Select 2 or more mesh objects, aborting.') - if quality: from_data[1].verts= None - return - - t= Blender.sys.time() - Window.WaitCursor(1) - - # Now do the copy. - print '\tCopying from "%s" to %i other mesh(es).' % (from_data[0].name, len(sel)) - for data in sel: - copy_bone_influences(from_data, data, PREF_SEL_ONLY, PREF_NO_XCROSS) - - # We cant unlink the mesh, but at least remove its data. - if quality: - from_data[1].verts= None - - print 'Copy Complete in %.6f sec' % (Blender.sys.time()-t) - Window.DrawProgressBar(1.0, '') - Window.WaitCursor(0) - -if __name__ == '__main__': - main()
\ No newline at end of file diff --git a/release/scripts/mesh_cleanup.py b/release/scripts/mesh_cleanup.py deleted file mode 100644 index 27adca335cb..00000000000 --- a/release/scripts/mesh_cleanup.py +++ /dev/null @@ -1,456 +0,0 @@ -#!BPY -""" -Name: 'Clean Meshes' -Blender: 245 -Group: 'Mesh' -Tooltip: 'Clean unused data from all selected mesh objects.' -""" - -__author__ = "Campbell Barton aka ideasman42" -__url__ = ["www.blender.org", "blenderartists.org", "www.python.org"] -__version__ = "0.1" -__bpydoc__ = """\ -Clean Meshes - -Cleans unused data from selected meshes -""" - -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Script copyright (C) Campbell J Barton -# -# 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 ***** -# -------------------------------------------------------------------------- - - -from Blender import * -import bpy -from Blender.Mathutils import TriangleArea - -import Blender -import BPyMesh -dict2MeshWeight= BPyMesh.dict2MeshWeight -meshWeight2Dict= BPyMesh.meshWeight2Dict - -def rem_free_verts(me): - vert_users= [0] * len(me.verts) - for f in me.faces: - for v in f: - vert_users[v.index]+=1 - - for e in me.edges: - for v in e: # loop on edge verts - vert_users[v.index]+=1 - - verts_free= [i for i, users in enumerate(vert_users) if not users] - - if verts_free: - pass - me.verts.delete(verts_free) - return len(verts_free) - -def rem_free_edges(me, limit=None): - ''' Only remove based on limit if a limit is set, else remove all ''' - - edgeDict= {} # will use a set when python 2.4 is standard. - - for f in me.faces: - for edkey in f.edge_keys: - edgeDict[edkey] = None - - edges_free= [] - for e in me.edges: - if not edgeDict.has_key(e.key): - edges_free.append(e) - - if limit != None: - edges_free= [e for e in edges_free if e.length <= limit] - - me.edges.delete(edges_free) - return len(edges_free) - -def rem_area_faces(me, limit=0.001): - ''' Faces that have an area below the limit ''' - rem_faces= [f for f in me.faces if f.area <= limit] - if rem_faces: - me.faces.delete( 0, rem_faces ) - return len(rem_faces) - -def rem_perimeter_faces(me, limit=0.001): - ''' Faces whos combine edge length is below the limit ''' - def faceEdLen(f): - v= f.v - if len(v) == 3: - return\ - (v[0].co-v[1].co).length +\ - (v[1].co-v[2].co).length +\ - (v[2].co-v[0].co).length - else: # 4 - return\ - (v[0].co-v[1].co).length +\ - (v[1].co-v[2].co).length +\ - (v[2].co-v[3].co).length +\ - (v[3].co-v[0].co).length - rem_faces= [f for f in me.faces if faceEdLen(f) <= limit] - if rem_faces: - me.faces.delete( 0, rem_faces ) - return len(rem_faces) - -def rem_unused_materials(me): - materials= me.materials - len_materials= len(materials) - if len_materials < 2: - return 0 - - rem_materials= 0 - - material_users= dict( [(i,0) for i in xrange(len_materials)] ) - - for f in me.faces: - f_mat = f.mat - # Make sure the face index isnt too big. this happens sometimes. - if f_mat >= len_materials: - f_mat = f.mat = 0 - material_users[f_mat] += 1 - - # mat_idx_subtract= 0 - # reindex_mapping= dict( [(i,0) for i in xrange(len_materials)] ) - - reindex_mapping_ls = range(len_materials) - for i in range(len_materials-1, -1, -1): - if material_users[i] == 0: - del reindex_mapping_ls[i] - del materials[i] - rem_materials+=1 - - reindex_mapping= {} - - for i, mat in enumerate(reindex_mapping_ls): - reindex_mapping[mat] = i - - for f in me.faces: - f.mat= reindex_mapping[f.mat] - - me.materials= materials - return rem_materials - - -def rem_free_groups(me, groupNames, vWeightDict): - ''' cound how many vert users a group has and remove unused groups ''' - rem_groups = 0 - groupUserDict= dict([(group,0) for group in groupNames]) - - for vertexWeight in vWeightDict: - for group, weight in vertexWeight.iteritems(): - groupUserDict[group] += 1 - - i=len(groupNames) - while i: - i-=1 - group= groupNames[i] - if groupUserDict[group] == 0: - del groupNames[i] - print '\tremoving, vgroup', group - rem_groups+=1 - return rem_groups - -def rem_zero_weights(me, limit, groupNames, vWeightDict): - ''' remove verts from a group when their weight is zero.''' - rem_vweight_count= 0 - for vertexWeight in vWeightDict: - items= vertexWeight.items() - for group, weight in items: - if weight < limit: - del vertexWeight[group] - rem_vweight_count+= 1 - - return rem_vweight_count - - -def normalize_vweight(me, groupNames, vWeightDict): - for vertexWeight in vWeightDict: - unit= 0.0 - for group, weight in vertexWeight.iteritems(): - unit+= weight - - if unit != 1.0 and unit != 0.0: - for group, weight in vertexWeight.iteritems(): - vertexWeight[group]= weight/unit - -def isnan(f): - fstring = str(f).lower() - if 'nan' in fstring: - return True - if 'inf' in fstring: - return True - - return False - -def fix_nan_verts__internal(me): - rem_nan = 0 - for v in me.verts: - co = v.co - for i in (0,1,2): - if isnan(co[i]): - co[i] = 0.0 - rem_nan += 1 - return rem_nan - -def fix_nan_verts(me): - rem_nan = 0 - key = me.key - if key: - # Find the object, and get a mesh thats thinked to the oblink. - # this is a bit crap but needed to set the active key. - me_oblink = None - for ob in bpy.data.objects: - me_oblink = ob.getData(mesh=1) - if me_oblink == me: - me = me_oblink - break - if not me_oblink: - ob = None - - if key and ob: - blocks = key.blocks - # print blocks - orig_pin = ob.pinShape - orig_shape = ob.activeShape - orig_relative = key.relative - ob.pinShape = True - for i, block in enumerate(blocks): - ob.activeShape = i+1 - ob.makeDisplayList() - rem_nan += fix_nan_verts__internal(me) - me.update(block.name) # get the new verts - ob.pinShape = orig_pin - ob.activeShape = orig_shape - key.relative = orig_relative - - else: # No keys, simple operation - rem_nan = fix_nan_verts__internal(me) - - return rem_nan - -def fix_nan_uvs(me): - rem_nan = 0 - if me.faceUV: - orig_uvlayer = me.activeUVLayer - for uvlayer in me.getUVLayerNames(): - me.activeUVLayer = uvlayer - for f in me.faces: - for uv in f.uv: - for i in (0,1): - if isnan(uv[i]): - uv[i] = 0.0 - rem_nan += 1 - me.activeUVLayer = orig_uvlayer - return rem_nan - - -def has_vcol(me): - for f in me.faces: - for col in f.col: - if not (255 == col.r == col.g == col.b): - return True - return False - -def rem_white_vcol_layers(me): - vcols_removed = 0 - if me.vertexColors: - for col in me.getColorLayerNames(): - me.activeColorLayer = col - if not has_vcol(me): - me.removeColorLayer(col) - vcols_removed += 1 - - return vcols_removed - - -def main(): - sce= bpy.data.scenes.active - obsel= list(sce.objects.context) - actob= sce.objects.active - - is_editmode= Window.EditMode() - - # Edit mode object is not active, add it to the list. - if is_editmode and (not actob.sel): - obsel.append(actob) - - - #====================================# - # Popup menu to select the functions # - #====================================# - - CLEAN_ALL_DATA= Draw.Create(0) - CLEAN_VERTS_FREE= Draw.Create(1) - CLEAN_EDGE_NOFACE= Draw.Create(0) - CLEAN_EDGE_SMALL= Draw.Create(0) - CLEAN_FACE_PERIMETER= Draw.Create(0) - CLEAN_FACE_SMALL= Draw.Create(0) - - CLEAN_MATERIALS= Draw.Create(0) - CLEAN_WHITE_VCOL_LAYERS= Draw.Create(0) - CLEAN_GROUP= Draw.Create(0) - CLEAN_VWEIGHT= Draw.Create(0) - CLEAN_WEIGHT_NORMALIZE= Draw.Create(0) - limit= Draw.Create(0.01) - - CLEAN_NAN_VERTS= Draw.Create(0) - CLEAN_NAN_UVS= Draw.Create(0) - - # Get USER Options - - pup_block= [\ - ('Verts: free', CLEAN_VERTS_FREE, 'Remove verts that are not used by an edge or a face.'),\ - ('Edges: free', CLEAN_EDGE_NOFACE, 'Remove edges that are not in a face.'),\ - ('Edges: short', CLEAN_EDGE_SMALL, 'Remove edges that are below the length limit.'),\ - ('Faces: small perimeter', CLEAN_FACE_PERIMETER, 'Remove faces below the perimeter limit.'),\ - ('Faces: small area', CLEAN_FACE_SMALL, 'Remove faces below the area limit (may remove faces stopping T-face artifacts).'),\ - ('limit: ', limit, 0.001, 1.0, 'Limit for the area and length tests above (a higher limit will remove more data).'),\ - ('Material Clean', CLEAN_MATERIALS, 'Remove unused materials.'),\ - ('Color Layers', CLEAN_WHITE_VCOL_LAYERS, 'Remove vertex color layers that are totaly white'),\ - ('VGroup Clean', CLEAN_GROUP, 'Remove vertex groups that have no verts using them.'),\ - ('Weight Clean', CLEAN_VWEIGHT, 'Remove zero weighted verts from groups (limit is zero threshold).'),\ - ('WeightNormalize', CLEAN_WEIGHT_NORMALIZE, 'Make the sum total of vertex weights accross vgroups 1.0 for each vertex.'),\ - 'Clean NAN values',\ - ('NAN Verts', CLEAN_NAN_VERTS, 'Make NAN or INF verts (0,0,0)'),\ - ('NAN UVs', CLEAN_NAN_UVS, 'Make NAN or INF UVs (0,0)'),\ - '',\ - ('All Mesh Data', CLEAN_ALL_DATA, 'Warning! Operate on ALL mesh objects in your Blend file. Use with care'),\ - ] - - if not Draw.PupBlock('Clean Selected Meshes...', pup_block): - return - - CLEAN_VERTS_FREE= CLEAN_VERTS_FREE.val - CLEAN_EDGE_NOFACE= CLEAN_EDGE_NOFACE.val - CLEAN_EDGE_SMALL= CLEAN_EDGE_SMALL.val - CLEAN_FACE_PERIMETER= CLEAN_FACE_PERIMETER.val - CLEAN_FACE_SMALL= CLEAN_FACE_SMALL.val - CLEAN_MATERIALS= CLEAN_MATERIALS.val - CLEAN_WHITE_VCOL_LAYERS= CLEAN_WHITE_VCOL_LAYERS.val - CLEAN_GROUP= CLEAN_GROUP.val - CLEAN_VWEIGHT= CLEAN_VWEIGHT.val - CLEAN_WEIGHT_NORMALIZE= CLEAN_WEIGHT_NORMALIZE.val - limit= limit.val - CLEAN_ALL_DATA= CLEAN_ALL_DATA.val - CLEAN_NAN_VERTS= CLEAN_NAN_VERTS.val - CLEAN_NAN_UVS= CLEAN_NAN_UVS.val - - if is_editmode: Window.EditMode(0) - - if CLEAN_ALL_DATA: - if CLEAN_GROUP or CLEAN_VWEIGHT or CLEAN_WEIGHT_NORMALIZE: - # For groups we need the objects linked to the mesh - meshes= [ob.getData(mesh=1) for ob in bpy.data.objects if ob.type == 'Mesh' if not ob.lib] - else: - meshes= bpy.data.meshes - else: - meshes= [ob.getData(mesh=1) for ob in obsel if ob.type == 'Mesh'] - - tot_meshes = len(meshes) # so we can decrement libdata - rem_face_count= rem_edge_count= rem_vert_count= rem_material_count= rem_vcol_layer_count= rem_group_count= rem_vweight_count= fix_nan_vcount= fix_nan_uvcount= 0 - if not meshes: - if is_editmode: Window.EditMode(1) - Draw.PupMenu('No meshes to clean') - - Blender.Window.WaitCursor(1) - bpy.data.meshes.tag = False - for me in meshes: - - # Dont touch the same data twice - if me.tag: - tot_meshes -= 1 - continue - me.tag = True - - if me.lib: - tot_meshes -= 1 - continue - - if me.multires: - multires_level_orig = me.multiresDrawLevel - me.multiresDrawLevel = 1 - print 'Warning, cannot perform destructive operations on multires mesh:', me.name - else: - if CLEAN_FACE_SMALL: - rem_face_count += rem_area_faces(me, limit) - - if CLEAN_FACE_PERIMETER: - rem_face_count += rem_perimeter_faces(me, limit) - - if CLEAN_EDGE_SMALL: # for all use 2- remove all edges. - rem_edge_count += rem_free_edges(me, limit) - - if CLEAN_EDGE_NOFACE: - rem_edge_count += rem_free_edges(me) - - if CLEAN_VERTS_FREE: - rem_vert_count += rem_free_verts(me) - - if CLEAN_MATERIALS: - rem_material_count += rem_unused_materials(me) - - if CLEAN_WHITE_VCOL_LAYERS: - rem_vcol_layer_count += rem_white_vcol_layers(me) - - if CLEAN_VWEIGHT or CLEAN_GROUP or CLEAN_WEIGHT_NORMALIZE: - groupNames, vWeightDict= meshWeight2Dict(me) - - if CLEAN_VWEIGHT: - rem_vweight_count += rem_zero_weights(me, limit, groupNames, vWeightDict) - - if CLEAN_GROUP: - rem_group_count += rem_free_groups(me, groupNames, vWeightDict) - pass - - if CLEAN_WEIGHT_NORMALIZE: - normalize_vweight(me, groupNames, vWeightDict) - - # Copy back to mesh vertex groups. - dict2MeshWeight(me, groupNames, vWeightDict) - - if CLEAN_NAN_VERTS: - fix_nan_vcount = fix_nan_verts(me) - - if CLEAN_NAN_UVS: - fix_nan_uvcount = fix_nan_uvs(me) - - # restore multires. - if me.multires: - me.multiresDrawLevel = multires_level_orig - - Blender.Window.WaitCursor(0) - if is_editmode: Window.EditMode(0) - stat_string= 'Removed from ' + str(tot_meshes) + ' Mesh(es)%t|' - - if CLEAN_VERTS_FREE: stat_string+= 'Verts: %i|' % rem_vert_count - if CLEAN_EDGE_SMALL or CLEAN_EDGE_NOFACE: stat_string+= 'Edges: %i|' % rem_edge_count - if CLEAN_FACE_SMALL or CLEAN_FACE_PERIMETER: stat_string+= 'Faces: %i|' % rem_face_count - if CLEAN_MATERIALS: stat_string+= 'Materials: %i|' % rem_material_count - if CLEAN_WHITE_VCOL_LAYERS: stat_string+= 'Color Layers: %i|' % rem_vcol_layer_count - if CLEAN_VWEIGHT: stat_string+= 'VWeights: %i|' % rem_vweight_count - if CLEAN_GROUP: stat_string+= 'VGroups: %i|' % rem_group_count - if CLEAN_NAN_VERTS: stat_string+= 'Vert Nan Fix: %i|' % fix_nan_vcount - if CLEAN_NAN_UVS: stat_string+= 'UV Nan Fix: %i|' % fix_nan_uvcount - Draw.PupMenu(stat_string) - - -if __name__ == '__main__': - main()
\ No newline at end of file diff --git a/release/scripts/mesh_edges2curves.py b/release/scripts/mesh_edges2curves.py deleted file mode 100644 index 670165dda51..00000000000 --- a/release/scripts/mesh_edges2curves.py +++ /dev/null @@ -1,166 +0,0 @@ -#!BPY -""" Registration info for Blender menus: -Name: 'Edges to Curve' -Blender: 241 -Group: 'Mesh' -Tip: 'Edges not used by a face are converted into polyline(s)' -""" -__author__ = ("Campbell Barton") -__url__ = ("blender", "blenderartists.org") -__version__ = "1.0 2006/02/08" - -__bpydoc__ = """\ -Edges to Curves - -This script converts open and closed edge loops into curve polylines - -Supported:<br> - Polylines where each vert has no more then 2 edges attached to it. -""" - -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Script copyright (C) Campbell J Barton -# -# 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 ***** -# -------------------------------------------------------------------------- - -from Blender import * - -def polysFromMesh(me): - # a polyline is 2 - #polylines are a list - polyLines = [] - - # Get edges not used by a face - edgeDict= dict([ (ed.key, ed) for ed in me.edges ]) - for f in me.faces: - for key in f.edge_keys: - try: - del edgeDict[key] - except: - pass - - edges= edgeDict.values() - - - while edges: - currentEdge= edges.pop() - startVert= currentEdge.v2 - endVert= currentEdge.v1 - polyLine= [startVert, endVert] - ok= 1 - while ok: - ok= 0 - #for i, ed in enumerate(edges): - i=len(edges) - while i: - i-=1 - ed= edges[i] - if ed.v1 == endVert: - polyLine.append(ed.v2) - endVert= polyLine[-1] - ok=1 - del edges[i] - #break - elif ed.v2 == endVert: - polyLine.append(ed.v1) - endVert= polyLine[-1] - ok=1 - del edges[i] - #break - elif ed.v1 == startVert: - polyLine.insert(0, ed.v2) - startVert= polyLine[0] - ok=1 - del edges[i] - #break - elif ed.v2 == startVert: - polyLine.insert(0, ed.v1) - startVert= polyLine[0] - ok=1 - del edges[i] - #break - polyLines.append((polyLine, polyLine[0]==polyLine[-1])) - # print len(edges), len(polyLines) - return polyLines - - -def mesh2polys(): - scn= Scene.GetCurrent() - scn.objects.selected = [] - - meshOb= scn.objects.active - if meshOb==None or meshOb.type != 'Mesh': - Draw.PupMenu( 'ERROR: No Active Mesh Selected, Aborting' ) - return - Window.WaitCursor(1) - Window.EditMode(0) - me = meshOb.getData(mesh=1) - polygons= polysFromMesh(me) - w = 1.0 - cu= Curve.New() - cu.name = me.name - cu.setFlag(1) - - ob = scn.objects.active = scn.objects.new(cu) - ob.setMatrix(meshOb.matrixWorld) - - i=0 - for poly, closed in polygons: - if closed: - vIdx= 1 - else: - vIdx= 0 - - v= poly[vIdx] - cu.appendNurb((v.co.x, v.co.y, v.co.z, w)) - vIdx += 1 - cu[i].type= 0 # Poly Line - - # Close the polyline if its closed. - if closed: - cu[i].setFlagU(1) - - # Add all the points in the polyline. - while vIdx<len(poly): - v= poly[vIdx] - cu.appendPoint(i, (v.co.x, v.co.y, v.co.z, w)) - vIdx+=1 - i+=1 - Window.WaitCursor(0) - -# not used as yet. -""" -def writepolys(): - me = Scene.GetCurrent().getActiveObject().getData(mesh=1) - polygons= polysFromMesh(me) - file=open('/polygons.txt', 'w') - for ply in polygons: - file.write('polygon ') - if ply[1]: - file.write('closed ') - else: - file.write('open ') - file.write('%i\n' % len(ply[0])) - for pt in ply[0]: - file.write('%.6f %.6f %.6f\n' % tuple(pt.co) ) - file.close() -""" - -if __name__ == '__main__': - mesh2polys() diff --git a/release/scripts/mesh_mirror_tool.py b/release/scripts/mesh_mirror_tool.py deleted file mode 100644 index 8e22e26cd53..00000000000 --- a/release/scripts/mesh_mirror_tool.py +++ /dev/null @@ -1,352 +0,0 @@ -#!BPY -""" -Name: 'Mirror Vertex Locations & Weight' -Blender: 241 -Group: 'Mesh' -Tooltip: 'Snap Verticies to X mirrored locations and weights.' -""" - -__author__ = "Campbell Barton aka ideasman42" -__url__ = ["www.blender.org", "blenderartists.org", "www.python.org"] -__version__= '1.0' -__bpydoc__= '''\ -This script is used to mirror vertex locations and weights -It is useful if you have a model that was made symmetrical -but has verts that have moved from their mirrored locations slightly, -causing blenders X-Mirror options not to work. - -Weights can be mirrored too, this is useful if you want to model 1 side of a mesh, copy the mesh and flip it. -You can then use this script to mirror to the copy, even creating new flipped vertex groups, renaming group name left to right or .L to .R - -Vertex positions are mirrored by doing a locational lookup, -finding matching verts on both sides of a mesh and moving to the left/right or mid location. - -The vertex weights work differently, they are mirrored my location also, -but they mirror in pairs, rather it works by finding the closest vertex on the flip side and using its weight. - -When a location mirror is finished, verts that have not been mirrored will remain selected. -a good way to check both sides are mirrord is to select the mirrored parts, -run this script with default options and then see of there are any selected verts. - -For details on each option read the tooltips. -''' - -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Script copyright (C) Campbell Barton -# -# 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 ***** -# -------------------------------------------------------------------------- - - -from Blender import Draw, Window, Scene, Mesh, Mathutils, sys, Object -import BPyMesh - -BIGNUM= 1<<30 - -def mesh_mirror(me, PREF_MIRROR_LOCATION, PREF_XMID_SNAP, PREF_MAX_DIST, PREF_XZERO_THRESH, PREF_MODE, PREF_SEL_ONLY, PREF_EDGE_USERS, PREF_MIRROR_WEIGHTS, PREF_FLIP_NAMES, PREF_CREATE_FLIP_NAMES): - ''' - PREF_MIRROR_LOCATION, Will we mirror locations? - PREF_XMID_SNAP, Should we snap verts to X-0? - PREF_MAX_DIST, Maximum distance to test snapping verts. - PREF_XZERO_THRESH, How close verts must be to the middle before they are considered X-Zero verts. - PREF_MODE, 0:middle, 1: Left. 2:Right. - PREF_SEL_ONLY, only snap the selection - PREF_EDGE_USERS, match only verts with the same number of edge users. - PREF_MIRROR_LOCATION, - ''' - - - # Operate on all verts - if not PREF_SEL_ONLY: - for v in me.verts: - v.sel=1 - - - if PREF_EDGE_USERS: - edge_users= [0]*len(me.verts) - for ed in me.edges: - edge_users[ed.v1.index]+=1 - edge_users[ed.v2.index]+=1 - - - - if PREF_XMID_SNAP: # Do we snap locations at all? - for v in me.verts: - if v.sel: - if abs(v.co.x) <= PREF_XZERO_THRESH: - v.co.x= 0 - v.sel= 0 - - # alredy de-selected verts - neg_vts = [v for v in me.verts if v.sel and v.co.x < 0] - pos_vts = [v for v in me.verts if v.sel and v.co.x > 0] - - else: - # Use a small margin verts must be outside before we mirror them. - neg_vts = [v for v in me.verts if v.sel if v.co.x < -PREF_XZERO_THRESH] - pos_vts = [v for v in me.verts if v.sel if v.co.x > PREF_XZERO_THRESH] - - - - #*Mirror Location*********************************************************# - if PREF_MIRROR_LOCATION: - mirror_pairs= [] - # allign the negative with the positive. - flipvec= Mathutils.Vector() - len_neg_vts= float(len(neg_vts)) - for i1, nv in enumerate(neg_vts): - if nv.sel: # we may alredy be mirrored, if so well be deselected - nv_co= nv.co - for i2, pv in enumerate(pos_vts): - if pv.sel: - # Enforce edge users. - if not PREF_EDGE_USERS or edge_users[i1]==edge_users[i2]: - flipvec[:]= pv.co - flipvec.x= -flipvec.x - l= (nv_co-flipvec).length - - if l==0.0: # Both are alredy mirrored so we dont need to think about them. - # De-Select so we dont use again/ - pv.sel= nv.sel= 0 - - # Record a match. - elif l<=PREF_MAX_DIST: - - # We can adjust the length by the normal, now we know the length is under the limit. - # DISABLED, WASNT VERY USEFULL - ''' - if PREF_NOR_WEIGHT>0: - # Get the normal and flipm reuse flipvec - flipvec[:]= pv.no - flipvec.x= -flipvec.x - try: - ang= Mathutils.AngleBetweenVecs(nv.no, flipvec)/180.0 - except: # on rare occasions angle between vecs will fail.- zero length vec. - ang= 0 - - l=l*(1+(ang*PREF_NOR_WEIGHT)) - ''' - # Record the pairs for sorting to see who will get joined - mirror_pairs.append((l, nv, pv)) - - # Update every 20 loops - if i1 % 10 == 0: - Window.DrawProgressBar(0.8 * (i1/len_neg_vts), 'Mirror verts %i of %i' % (i1, len_neg_vts)) - - Window.DrawProgressBar(0.9, 'Mirror verts: Updating locations') - - # Now we have a list of the pairs we might use, lets find the best and do them first. - # de-selecting as we go. so we can makke sure not to mess it up. - try: mirror_pairs.sort(key = lambda a: a[0]) - except: mirror_pairs.sort(lambda a,b: cmp(a[0], b[0])) - - for dist, v1,v2 in mirror_pairs: # dist, neg, pos - if v1.sel and v2.sel: - if PREF_MODE==0: # Middle - flipvec[:]= v2.co # positive - flipvec.x= -flipvec.x # negatve - v2.co= v1.co= (flipvec+v1.co)*0.5 # midway - v2.co.x= -v2.co.x - elif PREF_MODE==2: # Left - v2.co= v1.co - v2.co.x= -v2.co.x - elif PREF_MODE==1: # Right - v1.co= v2.co - v1.co.x= -v1.co.x - v1.sel= v2.sel= 0 - - - #*Mirror Weights**********************************************************# - if PREF_MIRROR_WEIGHTS: - - groupNames, vWeightDict= BPyMesh.meshWeight2Dict(me) - mirror_pairs_l2r= [] # Stor a list of matches for these verts. - mirror_pairs_r2l= [] # Stor a list of matches for these verts. - - # allign the negative with the positive. - flipvec= Mathutils.Vector() - len_neg_vts= float(len(neg_vts)) - - # Here we make a tuple to look through, if were middle well need to look through both. - if PREF_MODE==0: # Middle - find_set= ((neg_vts, pos_vts, mirror_pairs_l2r), (pos_vts, neg_vts, mirror_pairs_r2l)) - elif PREF_MODE==1: # Left - find_set= ((neg_vts, pos_vts, mirror_pairs_l2r), ) - elif PREF_MODE==2: # Right - find_set= ((pos_vts, neg_vts, mirror_pairs_r2l), ) - - - # Do a locational lookup again :/ - This isnt that good form but if we havnt mirrored weights well need to do it anyway. - # The Difference with this is that we dont need to have 1:1 match for each vert- just get each vert to find another mirrored vert - # and use its weight. - # Use "find_set" so we can do a flipped search L>R and R>L without duplicate code. - for vtls_A, vtls_B, pair_ls in find_set: - for i1, vA in enumerate(vtls_A): - best_len=1<<30 # BIGNUM - best_idx=-1 - - # Find the BEST match - vA_co= vA.co - for i2, vB in enumerate(vtls_B): - # Enforce edge users. - if not PREF_EDGE_USERS or edge_users[i1]==edge_users[i2]: - flipvec[:]= vB.co - flipvec.x= -flipvec.x - l= (vA_co-flipvec).length - - if l<best_len: - best_len=l - best_idx=i2 - - if best_idx != -1: - pair_ls.append((vtls_A[i1].index, vtls_B[best_idx].index)) # neg, pos. - - # Now we can merge the weights - if PREF_MODE==0: # Middle - newVWeightDict= [vWeightDict[i] for i in xrange(len(me.verts))] # Have empty dicts just incase - for pair_ls in (mirror_pairs_l2r, mirror_pairs_r2l): - if PREF_FLIP_NAMES: - for i1, i2 in pair_ls: - flipWeight, groupNames= BPyMesh.dictWeightFlipGroups( vWeightDict[i2], groupNames, PREF_CREATE_FLIP_NAMES ) - newVWeightDict[i1]= BPyMesh.dictWeightMerge([vWeightDict[i1], flipWeight] ) - else: - for i1, i2 in pair_ls: - newVWeightDict[i1]= BPyMesh.dictWeightMerge([vWeightDict[i1], vWeightDict[i2]]) - - vWeightDict= newVWeightDict - - elif PREF_MODE==1: # Left - if PREF_FLIP_NAMES: - for i1, i2 in mirror_pairs_l2r: - vWeightDict[i2], groupNames= BPyMesh.dictWeightFlipGroups(vWeightDict[i1], groupNames, PREF_CREATE_FLIP_NAMES) - else: - for i1, i2 in mirror_pairs_l2r: - vWeightDict[i2]= vWeightDict[i1] # Warning Multiple instances of the same data, its ok in this case but dont modify later. - - elif PREF_MODE==2: # Right - if PREF_FLIP_NAMES: - for i1, i2 in mirror_pairs_r2l: - vWeightDict[i2], groupNames= BPyMesh.dictWeightFlipGroups(vWeightDict[i1], groupNames, PREF_CREATE_FLIP_NAMES) - else: - for i1, i2 in mirror_pairs_r2l: - vWeightDict[i2]= vWeightDict[i1] # Warning, ditto above - - BPyMesh.dict2MeshWeight(me, groupNames, vWeightDict) - - me.update() - -def main(): - scn = Scene.GetCurrent() - act_ob= scn.getActiveObject() - if act_ob.getType()!='Mesh': - act_ob= None - - sel= [ob for ob in Object.GetSelected() if ob.getType()=='Mesh' if ob != act_ob] - if not sel and not act_ob: - Draw.PupMenu('Error, select a mesh as your active object') - return - - # Defaults - PREF_EDITMESH_ONLY= Draw.Create(1) - PREF_MIRROR_LOCATION= Draw.Create(1) - PREF_XMID_SNAP= Draw.Create(1) - PREF_MAX_DIST= Draw.Create(0.02) - PREF_XZERO_THRESH= Draw.Create(0.002) - - #PREF_MODE= Draw.Create(0) # THIS IS TOOO CONFUSING, HAVE 2 BUTTONS AND MAKE THE MODE FROM THEM. - PREF_MODE_L2R= Draw.Create(1) - PREF_MODE_R2L= Draw.Create(0) - - PREF_SEL_ONLY= Draw.Create(1) - PREF_EDGE_USERS= Draw.Create(0) - # Weights - PREF_MIRROR_WEIGHTS= Draw.Create(0) - PREF_FLIP_NAMES= Draw.Create(1) - PREF_CREATE_FLIP_NAMES= Draw.Create(1) - - pup_block = [\ - ('EditMesh Only', PREF_EDITMESH_ONLY, 'If disabled, will mirror all selected meshes.'),\ - 'Left (-), Right (+)',\ - ('Left > Right', PREF_MODE_L2R, 'Copy from the Left to Right of the mesh. Enable Both for a mid loc/weight.'),\ - ('Right > Left', PREF_MODE_R2L, 'Copy from the Right to Left of the mesh. Enable Both for a mid loc/weight.'),\ - '',\ - ('MaxDist:', PREF_MAX_DIST, 0.0, 1.0, 'Generate interpolated verts so closer vert weights can be copied.'),\ - ('XZero limit:', PREF_XZERO_THRESH, 0.0, 1.0, 'Mirror verts above this distance from the middle, else lock to X/zero.'),\ - ('Sel Verts Only', PREF_SEL_ONLY, 'Only mirror selected verts. Else try and mirror all'),\ - ('Edge Users', PREF_EDGE_USERS, 'Only match up verts that have the same number of edge users.'),\ - 'Location Prefs',\ - ('Mirror Location', PREF_MIRROR_LOCATION, 'Mirror vertex locations.'),\ - ('XMidSnap Verts', PREF_XMID_SNAP, 'Snap middle verts to X Zero (uses XZero limit)'),\ - 'Weight Prefs',\ - ('Mirror Weights', PREF_MIRROR_WEIGHTS, 'Mirror vertex locations.'),\ - ('Flip Groups', PREF_FLIP_NAMES, 'Mirror flip names.'),\ - ('New Flip Groups', PREF_CREATE_FLIP_NAMES, 'Make new groups for flipped names.'),\ - ] - - if not Draw.PupBlock("X Mirror mesh tool", pup_block): - return - - # WORK OUT THE MODE 0 - # PREF_MODE, 0:middle, 1: Left. 2:Right. - PREF_MODE_R2L= PREF_MODE_R2L.val - PREF_MODE_L2R= PREF_MODE_L2R.val - - if PREF_MODE_R2L and PREF_MODE_L2R: - PREF_MODE= 0 # Middle - elif not PREF_MODE_R2L and PREF_MODE_L2R: - PREF_MODE= 1 # Left to Right - elif PREF_MODE_R2L and not PREF_MODE_L2R: - PREF_MODE= 2 # Right to Left - else: # Neither Selected. Do middle anyway - PREF_MODE= 0 - - - PREF_EDITMESH_ONLY= PREF_EDITMESH_ONLY.val - PREF_MIRROR_LOCATION= PREF_MIRROR_LOCATION.val - PREF_XMID_SNAP= PREF_XMID_SNAP.val - PREF_MAX_DIST= PREF_MAX_DIST.val - PREF_XZERO_THRESH= PREF_XZERO_THRESH.val - PREF_SEL_ONLY= PREF_SEL_ONLY.val - PREF_EDGE_USERS= PREF_EDGE_USERS.val - # weights - PREF_MIRROR_WEIGHTS= PREF_MIRROR_WEIGHTS.val - PREF_FLIP_NAMES= PREF_FLIP_NAMES.val - PREF_CREATE_FLIP_NAMES= PREF_CREATE_FLIP_NAMES.val - - t= sys.time() - - is_editmode = Window.EditMode() # Exit Editmode. - if is_editmode: Window.EditMode(0) - Mesh.Mode(Mesh.SelectModes['VERTEX']) - Window.WaitCursor(1) - - if act_ob: - mesh_mirror(act_ob.getData(mesh=1), PREF_MIRROR_LOCATION, PREF_XMID_SNAP, PREF_MAX_DIST, PREF_XZERO_THRESH, PREF_MODE, PREF_SEL_ONLY, PREF_EDGE_USERS, PREF_MIRROR_WEIGHTS, PREF_FLIP_NAMES, PREF_CREATE_FLIP_NAMES) - if (not PREF_EDITMESH_ONLY) and sel: - for ob in sel: - mesh_mirror(ob.getData(mesh=1), PREF_MIRROR_LOCATION, PREF_XMID_SNAP, PREF_MAX_DIST, PREF_XZERO_THRESH, PREF_MODE, PREF_SEL_ONLY, PREF_EDGE_USERS, PREF_MIRROR_WEIGHTS, PREF_FLIP_NAMES, PREF_CREATE_FLIP_NAMES) - - if is_editmode: Window.EditMode(1) - Window.WaitCursor(0) - Window.DrawProgressBar(1.0, '') - Window.RedrawAll() - - print 'Mirror done in %.6f sec.' % (sys.time()-t) - -if __name__ == '__main__': - main() diff --git a/release/scripts/mesh_poly_reduce.py b/release/scripts/mesh_poly_reduce.py deleted file mode 100644 index 6dfd7a90efc..00000000000 --- a/release/scripts/mesh_poly_reduce.py +++ /dev/null @@ -1,143 +0,0 @@ -#!BPY -""" -Name: 'Poly Reducer' -Blender: 243 -Group: 'Mesh' -Tooltip: 'Removed polygons from a mesh while maintaining the shape, textures and weights.' -""" - -__author__ = "Campbell Barton" -__url__ = ("blender", "blenderartists.org") -__version__ = "1.0 2006/02/07" - -__bpydoc__ = """\ -This script simplifies the mesh by removing faces, keeping the overall shape of the mesh. -""" - -from Blender import Draw, Window, Scene, Mesh, Mathutils, sys, Object -import BPyMesh -# reload(BPyMesh) -import BPyMessages - -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Script copyright (C) Campbell J Barton -# -# 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 ***** -# -------------------------------------------------------------------------- - - -def main(): - scn = Scene.GetCurrent() - act_ob= scn.objects.active - if not act_ob or act_ob.type != 'Mesh': - BPyMessages.Error_NoMeshActive() - return - - act_me= act_ob.getData(mesh=1) - - if act_me.multires: - BPyMessages.Error_NoMeshMultiresEdit() - return - - act_group= act_me.activeGroup - if not act_group: act_group= '' - - - # Defaults - PREF_REDUX= Draw.Create(0.5) - PREF_BOUNDRY_WEIGHT= Draw.Create(5.0) - PREF_REM_DOUBLES= Draw.Create(1) - PREF_FACE_AREA_WEIGHT= Draw.Create(1.0) - PREF_FACE_TRIANGULATE= Draw.Create(1) - - VGROUP_INF_ENABLE= Draw.Create(0) - VGROUP_INF_REDUX= Draw.Create(act_group) - VGROUP_INF_WEIGHT= Draw.Create(10.0) - - PREF_DO_UV= Draw.Create(1) - PREF_DO_VCOL= Draw.Create(1) - PREF_DO_WEIGHTS= Draw.Create(1) - PREF_OTHER_SEL_OBS= Draw.Create(0) - - pup_block = [\ - ('Poly Reduce:', PREF_REDUX, 0.05, 0.95, 'Scale the meshes poly count by this value.'),\ - ('Boundry Weight:', PREF_BOUNDRY_WEIGHT, 0.0, 20.0, 'Weight boundry verts by this scale, 0.0 for no boundry weighting.'),\ - ('Area Weight:', PREF_FACE_AREA_WEIGHT, 0.0, 20.0, 'Collapse edges effecting lower area faces first.'),\ - ('Triangulate', PREF_FACE_TRIANGULATE, 'Convert quads to tris before reduction, for more choices of edges to collapse.'),\ - '',\ - ('VGroup Weighting', VGROUP_INF_ENABLE, 'Use a vertex group to influence the reduction, higher weights for higher quality '),\ - ('vgroup name: ', VGROUP_INF_REDUX, 0, 32, 'The name of the vertex group to use for the weight map'),\ - ('vgroup mult: ', VGROUP_INF_WEIGHT, 0.0, 100.0, 'How much to make the weight effect the reduction'),\ - ('Other Selected Obs', PREF_OTHER_SEL_OBS, 'reduce other selected objects.'),\ - '',\ - '',\ - '',\ - ('UV Coords', PREF_DO_UV, 'Interpolate UV Coords.'),\ - ('Vert Colors', PREF_DO_VCOL, 'Interpolate Vertex Colors'),\ - ('Vert Weights', PREF_DO_WEIGHTS, 'Interpolate Vertex Weights'),\ - ('Remove Doubles', PREF_REM_DOUBLES, 'Remove doubles before reducing to avoid boundry tearing.'),\ - ] - - if not Draw.PupBlock("Poly Reducer", pup_block): - return - - PREF_REDUX= PREF_REDUX.val - PREF_BOUNDRY_WEIGHT= PREF_BOUNDRY_WEIGHT.val - PREF_REM_DOUBLES= PREF_REM_DOUBLES.val - PREF_FACE_AREA_WEIGHT= PREF_FACE_AREA_WEIGHT.val - PREF_FACE_TRIANGULATE= PREF_FACE_TRIANGULATE.val - - VGROUP_INF_ENABLE= VGROUP_INF_ENABLE.val - VGROUP_INF_WEIGHT= VGROUP_INF_WEIGHT.val - - if VGROUP_INF_ENABLE and VGROUP_INF_WEIGHT: - VGROUP_INF_REDUX= VGROUP_INF_REDUX.val - else: - VGROUP_INF_WEIGHT= 0.0 - VGROUP_INF_REDUX= None - - - PREF_DO_UV= PREF_DO_UV.val - PREF_DO_VCOL= PREF_DO_VCOL.val - PREF_DO_WEIGHTS= PREF_DO_WEIGHTS.val - PREF_OTHER_SEL_OBS= PREF_OTHER_SEL_OBS.val - - - t= sys.time() - - is_editmode = Window.EditMode() # Exit Editmode. - if is_editmode: Window.EditMode(0) - Window.WaitCursor(1) - print 'reducing:', act_ob.name, act_ob.getData(1) - BPyMesh.redux(act_ob, PREF_REDUX, PREF_BOUNDRY_WEIGHT, PREF_REM_DOUBLES, PREF_FACE_AREA_WEIGHT, PREF_FACE_TRIANGULATE, PREF_DO_UV, PREF_DO_VCOL, PREF_DO_WEIGHTS, VGROUP_INF_REDUX, VGROUP_INF_WEIGHT) - - if PREF_OTHER_SEL_OBS: - for ob in scn.objects.context: - if ob.type == 'Mesh' and ob != act_ob: - print 'reducing:', ob.name, ob.getData(1) - BPyMesh.redux(ob, PREF_REDUX, PREF_BOUNDRY_WEIGHT, PREF_REM_DOUBLES, PREF_FACE_AREA_WEIGHT, PREF_FACE_TRIANGULATE, PREF_DO_UV, PREF_DO_VCOL, PREF_DO_WEIGHTS, VGROUP_INF_REDUX, VGROUP_INF_WEIGHT) - Window.RedrawAll() - - if is_editmode: Window.EditMode(1) - Window.WaitCursor(0) - Window.RedrawAll() - - print 'Reduction done in %.6f sec.' % (sys.time()-t) - -if __name__ == '__main__': - main()
\ No newline at end of file diff --git a/release/scripts/mesh_poly_reduce_grid.py b/release/scripts/mesh_poly_reduce_grid.py deleted file mode 100644 index 2903909027a..00000000000 --- a/release/scripts/mesh_poly_reduce_grid.py +++ /dev/null @@ -1,351 +0,0 @@ -#!BPY -""" -Name: 'Poly Reduce Selection (Unsubsurf)' -Blender: 245 -Group: 'Mesh' -Tooltip: 'predictable mesh simplifaction maintaining face loops' -""" - -from Blender import Scene, Mesh, Window, sys -import BPyMessages -import bpy - -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Script copyright (C) Campbell J Barton -# -# 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 ***** -# -------------------------------------------------------------------------- - - -def my_mesh_util(me): - me_verts = me.verts - - vert_faces = [ [] for v in me_verts] - vert_faces_corner = [ [] for v in me_verts] - - - # Ignore topology where there are not 2 faces connected to an edge. - edge_count = {} - for f in me.faces: - for edkey in f.edge_keys: - try: - edge_count[edkey] += 1 - except: - edge_count[edkey] = 1 - - for edkey, count in edge_count.iteritems(): - - # Ignore verts that connect to edges with more than 2 faces. - if count != 2: - vert_faces[edkey[0]] = None - vert_faces[edkey[1]] = None - # Done - - - - def faces_set_verts(face_ls): - unique_verts = set() - for f in face_ls: - for v in f: - unique_verts.add(v.index) - return unique_verts - - for f in me.faces: - for corner, v in enumerate(f): - i = v.index - if vert_faces[i] != None: - vert_faces[i].append(f) - vert_faces_corner[i].append( corner ) - - grid_data_ls = [] - - for vi, face_ls in enumerate(vert_faces): - if face_ls != None: - if len(face_ls) == 4: - if face_ls[0].sel and face_ls[1].sel and face_ls[2].sel and face_ls[3].sel: - # Support triangles also - unique_vert_count = len(faces_set_verts(face_ls)) - quads = 0 - for f in face_ls: - if len(f) ==4: - quads += 1 - if unique_vert_count==5+quads: # yay we have a grid - grid_data_ls.append( (vi, face_ls) ) - - elif len(face_ls) == 3: - if face_ls[0].sel and face_ls[1].sel and face_ls[2].sel: - unique_vert_count = len(faces_set_verts(face_ls)) - if unique_vert_count==4: # yay we have 3 triangles to make into a bigger triangle - grid_data_ls.append( (vi, face_ls) ) - - - - # Now sort out which grid faces to use - - - # This list will be used for items we can convert, vertex is key, faces are values - grid_data_dict = {} - - if not grid_data_ls: - print "doing nothing" - return - - # quick lookup for the opposing corner of a qiad - quad_diag_mapping = 2,3,0,1 - - verts_used = [0] * len(me_verts) # 0 == untouched, 1==should touch, 2==touched - verts_used[grid_data_ls[0][0]] = 1 # start touching 1! - - # From the corner vert, get the 2 edges that are not the corner or its opposing vert, this edge will make a new face - quad_edge_mapping = (1,3), (2,0), (1,3), (0,2) # hi-low, low-hi order is intended - tri_edge_mapping = (1,2), (0,2), (0,1) - - done_somthing = True - while done_somthing: - done_somthing = False - grid_data_ls_index = -1 - - for vi, face_ls in grid_data_ls: - grid_data_ls_index += 1 - if len(face_ls) == 3: - grid_data_dict[vi] = face_ls - grid_data_ls.pop( grid_data_ls_index ) - break - elif len(face_ls) == 4: - # print vi - if verts_used[vi] == 1: - verts_used[vi] = 2 # dont look at this again. - done_somthing = True - - grid_data_dict[vi] = face_ls - - # Tag all faces verts as used - - for i, f in enumerate(face_ls): - # i == face index on vert, needed to recall which corner were on. - v_corner = vert_faces_corner[vi][i] - fv =f.v - - if len(f) == 4: - v_other = quad_diag_mapping[v_corner] - # get the 2 other corners - corner1, corner2 = quad_edge_mapping[v_corner] - if verts_used[fv[v_other].index] == 0: - verts_used[fv[v_other].index] = 1 # TAG for touching! - else: - corner1, corner2 = tri_edge_mapping[v_corner] - - verts_used[fv[corner1].index] = 2 # Dont use these, they are - verts_used[fv[corner2].index] = 2 - - - # remove this since we have used it. - grid_data_ls.pop( grid_data_ls_index ) - - break - - if done_somthing == False: - # See if there are any that have not even been tagged, (probably on a different island), then tag them. - - for vi, face_ls in grid_data_ls: - if verts_used[vi] == 0: - verts_used[vi] = 1 - done_somthing = True - break - - - # Now we have all the areas we will fill, calculate corner triangles we need to fill in. - new_faces = [] - quad_del_vt_map = (1,2,3), (0,2,3), (0,1,3), (0,1,2) - for vi, face_ls in grid_data_dict.iteritems(): - for i, f in enumerate(face_ls): - if len(f) == 4: - # i == face index on vert, needed to recall which corner were on. - v_corner = vert_faces_corner[vi][i] - v_other = quad_diag_mapping[v_corner] - fv =f.v - - #print verts_used[fv[v_other].index] - #if verts_used[fv[v_other].index] != 2: # DOSNT WORK ALWAYS - - if 1: # THIS IS LAzY - some of these faces will be removed after adding. - # Ok we are removing half of this face, add the other half - - # This is probably slower - # new_faces.append( [fv[ii].index for ii in (0,1,2,3) if ii != v_corner ] ) - - # do this instead - new_faces.append( (fv[quad_del_vt_map[v_corner][0]], fv[quad_del_vt_map[v_corner][1]], fv[quad_del_vt_map[v_corner][2]]) ) - - del grid_data_ls - - - # me.sel = 0 - def faceCombine4(vi, face_ls): - edges = [] - - for i, f in enumerate(face_ls): - fv = f.v - v_corner = vert_faces_corner[vi][i] - if len(f)==4: ed = quad_edge_mapping[v_corner] - else: ed = tri_edge_mapping[v_corner] - - edges.append( [fv[ed[0]].index, fv[ed[1]].index] ) - - # get the face from the edges - face = edges.pop() - while len(face) != 4: - # print len(edges), edges, face - for ed_idx, ed in enumerate(edges): - if face[-1] == ed[0] and (ed[1] != face[0]): - face.append(ed[1]) - elif face[-1] == ed[1] and (ed[0] != face[0]): - face.append(ed[0]) - else: - continue - - edges.pop(ed_idx) # we used the edge alredy - break - - return face - - for vi, face_ls in grid_data_dict.iteritems(): - if len(face_ls) == 4: - new_faces.append( faceCombine4(vi, face_ls) ) - #pass - if len(face_ls) == 3: # 3 triangles - face = list(faces_set_verts(face_ls)) - face.remove(vi) - new_faces.append( face ) - - - # Now remove verts surounded by 3 triangles - - - - # print new_edges - # me.faces.extend(new_faces, ignoreDups=True) - - ''' - faces_remove = [] - for vi, face_ls in grid_data_dict.iteritems(): - faces_remove.extend(face_ls) - ''' - - orig_facelen = len(me.faces) - - orig_faces = list(me.faces) - me.faces.extend(new_faces, ignoreDups=True) - new_faces = list(me.faces)[len(orig_faces):] - - - - - - if me.faceUV: - uvnames = me.getUVLayerNames() - act_uvlay = me.activeUVLayer - - vert_faces_uvs = [] - vert_faces_images = [] - - - act_uvlay = me.activeUVLayer - - for uvlay in uvnames: - me.activeUVLayer = uvlay - vert_faces_uvs[:] = [None] * len(me.verts) - vert_faces_images[:] = vert_faces_uvs[:] - - for i,f in enumerate(orig_faces): - img = f.image - fv = f.v - uv = f.uv - mat = f.mat - for i,v in enumerate(fv): - vi = v.index - vert_faces_uvs[vi] = uv[i] # no nice averaging - vert_faces_images[vi] = img - - - # Now copy UVs across - for f in new_faces: - fi = [v.index for v in f.v] - f.image = vert_faces_images[fi[0]] - uv = f.uv - for i,vi in enumerate(fi): - uv[i][:] = vert_faces_uvs[vi] - - if len(me.materials) > 1: - vert_faces_mats = [None] * len(me.verts) - for i,f in enumerate(orig_faces): - mat = f.mat - for i,v in enumerate(f.v): - vi = v.index - vert_faces_mats[vi] = mat - - # Now copy UVs across - for f in new_faces: - print vert_faces_mats[f.v[0].index] - f.mat = vert_faces_mats[f.v[0].index] - - - me.verts.delete(grid_data_dict.keys()) - - # me.faces.delete(1, faces_remove) - - if me.faceUV: - me.activeUVLayer = act_uvlay - - me.calcNormals() - -def main(): - - # Gets the current scene, there can be many scenes in 1 blend file. - sce = bpy.data.scenes.active - - # Get the active object, there can only ever be 1 - # and the active object is always the editmode object. - ob_act = sce.objects.active - - if not ob_act or ob_act.type != 'Mesh': - BPyMessages.Error_NoMeshActive() - return - - is_editmode = Window.EditMode() - if is_editmode: Window.EditMode(0) - - Window.WaitCursor(1) - me = ob_act.getData(mesh=1) # old NMesh api is default - t = sys.time() - - # Run the mesh editing function - my_mesh_util(me) - - # Restore editmode if it was enabled - if is_editmode: Window.EditMode(1) - - # Timing the script is a good way to be aware on any speed hits when scripting - print 'My Script finished in %.2f seconds' % (sys.time()-t) - Window.WaitCursor(0) - - -# This lets you can import the script without running it -if __name__ == '__main__': - main() - diff --git a/release/scripts/mesh_skin.py b/release/scripts/mesh_skin.py deleted file mode 100644 index 4a330a516fb..00000000000 --- a/release/scripts/mesh_skin.py +++ /dev/null @@ -1,639 +0,0 @@ -#!BPY - -""" -Name: 'Skin Faces/Edge-Loops' -Blender: 243 -Group: 'MeshFaceKey' -Tooltip: 'Select 2 vert loops, then run this script.' -""" - -__author__ = "Campbell Barton AKA Ideasman" -__url__ = ["blenderartists.org", "www.blender.org"] -__version__ = "1.1 2006/12/26" - -__bpydoc__ = """\ -With this script vertex loops can be skinned: faces are created to connect the -selected loops of vertices. - -Usage: - -In mesh Edit mode select the vertices of the loops (closed paths / curves of -vertices: circles, for example) that should be skinned, then run this script. -A pop-up will provide further options, if the results of a method are not adequate try one of the others. -""" - - -# $Id$ -# -# -------------------------------------------------------------------------- -# Skin Selected edges 1.0 By Campbell Barton (AKA Ideasman) -# -------------------------------------------------------------------------- -# ***** 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 ***** -# -------------------------------------------------------------------------- - -# Made by Ideasman/Campbell 2005/06/15 - cbarton@metavr.com - -import Blender -import bpy -from Blender import Window -from Blender.Mathutils import MidpointVecs, Vector -from Blender.Mathutils import AngleBetweenVecs as _AngleBetweenVecs_ -import BPyMessages - -from Blender.Draw import PupMenu - -BIG_NUM = 1<<30 - -global CULL_METHOD -CULL_METHOD = 0 - -def AngleBetweenVecs(a1,a2): - try: - return _AngleBetweenVecs_(a1,a2) - except: - return 180.0 - -class edge(object): - __slots__ = 'v1', 'v2', 'co1', 'co2', 'length', 'removed', 'match', 'cent', 'angle', 'next', 'prev', 'normal', 'fake' - def __init__(self, v1,v2): - self.v1 = v1 - self.v2 = v2 - co1, co2= v1.co, v2.co - self.co1= co1 - self.co2= co2 - - # uv1 uv2 vcol1 vcol2 # Add later - self.length = (co1 - co2).length - self.removed = 0 # Have we been culled from the eloop - self.match = None # The other edge were making a face with - - self.cent= MidpointVecs(co1, co2) - self.angle= 0.0 - self.fake= False - -class edgeLoop(object): - __slots__ = 'centre', 'edges', 'normal', 'closed', 'backup_edges' - def __init__(self, loop, me, closed): # Vert loop - # Use next and prev, nextDist, prevDist - - # Get Loops centre. - fac= len(loop) - verts = me.verts - self.centre= reduce(lambda a,b: a+verts[b].co/fac, loop, Vector()) - - # Convert Vert loop to Edges. - self.edges = [edge(verts[loop[vIdx-1]], verts[loop[vIdx]]) for vIdx in xrange(len(loop))] - - if not closed: - self.edges[0].fake = True # fake edge option - - self.closed = closed - - - # Assign linked list - for eIdx in xrange(len(self.edges)-1): - self.edges[eIdx].next = self.edges[eIdx+1] - self.edges[eIdx].prev = self.edges[eIdx-1] - # Now last - self.edges[-1].next = self.edges[0] - self.edges[-1].prev = self.edges[-2] - - - - # GENERATE AN AVERAGE NORMAL FOR THE WHOLE LOOP. - self.normal = Vector() - for e in self.edges: - n = (self.centre-e.co1).cross(self.centre-e.co2) - # Do we realy need tot normalize? - n.normalize() - self.normal += n - - # Generate the angle - va= e.cent - e.prev.cent - vb= e.next.cent - e.cent - - e.angle= AngleBetweenVecs(va, vb) - - # Blur the angles - #for e in self.edges: - # e.angle= (e.angle+e.next.angle)/2 - - # Blur the angles - #for e in self.edges: - # e.angle= (e.angle+e.prev.angle)/2 - - self.normal.normalize() - - # Generate a normal for each edge. - for e in self.edges: - - n1 = e.co1 - n2 = e.co2 - n3 = e.prev.co1 - - a = n1-n2 - b = n1-n3 - normal1 = a.cross(b) - normal1.normalize() - - n1 = e.co2 - n3 = e.next.co2 - n2 = e.co1 - - a = n1-n2 - b = n1-n3 - - normal2 = a.cross(b) - normal2.normalize() - - # Reuse normal1 var - normal1 += normal1 + normal2 - normal1.normalize() - - e.normal = normal1 - #print e.normal - - - - def backup(self): - # Keep a backup of the edges - self.backup_edges = self.edges[:] - - def restore(self): - self.edges = self.backup_edges[:] - for e in self.edges: - e.removed = 0 - - def reverse(self): - self.edges.reverse() - self.normal.negate() - - for e in self.edges: - e.normal.negate() - e.v1, e.v2 = e.v2, e.v1 - e.co1, e.co2 = e.co2, e.co1 - e.next, e.prev = e.prev, e.next - - - def removeSmallest(self, cullNum, otherLoopLen): - ''' - Removes N Smallest edges and backs up the loop, - this is so we can loop between 2 loops as if they are the same length, - backing up and restoring incase the loop needs to be skinned with another loop of a different length. - ''' - global CULL_METHOD - if CULL_METHOD == 1: # Shortest edge - eloopCopy = self.edges[:] - - # Length sort, smallest first - try: eloopCopy.sort(key = lambda e1: e1.length) - except: eloopCopy.sort(lambda e1, e2: cmp(e1.length, e2.length )) - - # Dont use atm - #eloopCopy.sort(lambda e1, e2: cmp(e1.angle*e1.length, e2.angle*e2.length)) # Length sort, smallest first - #eloopCopy.sort(lambda e1, e2: cmp(e1.angle, e2.angle)) # Length sort, smallest first - - remNum = 0 - for i, e in enumerate(eloopCopy): - if not e.fake: - e.removed = 1 - self.edges.remove( e ) # Remove from own list, still in linked list. - remNum += 1 - - if not remNum < cullNum: - break - - else: # CULL METHOD is even - - culled = 0 - - step = int(otherLoopLen / float(cullNum)) * 2 - - currentEdge = self.edges[0] - while culled < cullNum: - - # Get the shortest face in the next STEP - step_count= 0 - bestAng= 360.0 - smallestEdge= None - while step_count<=step or smallestEdge==None: - step_count+=1 - if not currentEdge.removed: # 0 or -1 will not be accepted - if currentEdge.angle<bestAng and not currentEdge.fake: - smallestEdge= currentEdge - bestAng= currentEdge.angle - - currentEdge = currentEdge.next - - # In that stepping length we have the smallest edge.remove it - smallestEdge.removed = 1 - self.edges.remove(smallestEdge) - - # Start scanning from the edge we found? - result is over fanning- no good. - #currentEdge= smallestEdge.next - - culled+=1 - - -# Returns face edges. -# face must have edge data. - -def getSelectedEdges(me, ob): - MESH_MODE= Blender.Mesh.Mode() - - if MESH_MODE & Blender.Mesh.SelectModes.EDGE or MESH_MODE & Blender.Mesh.SelectModes.VERTEX: - Blender.Mesh.Mode(Blender.Mesh.SelectModes.EDGE) - edges= [ ed for ed in me.edges if ed.sel ] - # print len(edges), len(me.edges) - Blender.Mesh.Mode(MESH_MODE) - return edges - - elif MESH_MODE & Blender.Mesh.SelectModes.FACE: - Blender.Mesh.Mode(Blender.Mesh.SelectModes.EDGE) - - # value is [edge, face_sel_user_in] - ''' - try: # Python 2.4 only - edge_dict= dict((ed.key, [ed, 0]) for ed in me.edges) - except: - ''' - # Cant try 2.4 syntax because python 2.3 will complain still - edge_dict= dict([(ed.key, [ed, 0]) for ed in me.edges]) - - for f in me.faces: - if f.sel: - for edkey in f.edge_keys: - edge_dict[edkey][1] += 1 - - Blender.Mesh.Mode(MESH_MODE) - return [ ed_data[0] for ed_data in edge_dict.itervalues() if ed_data[1] == 1 ] - - - -def getVertLoops(selEdges, me): - ''' - return a list of vert loops, closed and open [(loop, closed)...] - ''' - - mainVertLoops = [] - # second method - tot = len(me.verts) - vert_siblings = [[] for i in xrange(tot)] - vert_used = [False] * tot - - for ed in selEdges: - i1, i2 = ed.key - vert_siblings[i1].append(i2) - vert_siblings[i2].append(i1) - - # find the first used vert and keep looping. - for i in xrange(tot): - if vert_siblings[i] and not vert_used[i]: - sbl = vert_siblings[i] # siblings - - if len(sbl) > 2: - return None - - vert_used[i] = True - - # do an edgeloop seek - if len(sbl) == 2: - contextVertLoop= [sbl[0], i, sbl[1]] # start the vert loop - vert_used[contextVertLoop[ 0]] = True - vert_used[contextVertLoop[-1]] = True - else: - contextVertLoop= [i, sbl[0]] - vert_used[contextVertLoop[ 1]] = True - - # Always seek up - ok = True - while ok: - ok = False - closed = False - sbl = vert_siblings[contextVertLoop[-1]] - if len(sbl) == 2: - next = sbl[not sbl.index( contextVertLoop[-2] )] - if vert_used[next]: - closed = True - # break - else: - contextVertLoop.append( next ) # get the vert that isnt the second last - vert_used[next] = True - ok = True - - # Seek down as long as the starting vert was not at the edge. - if not closed and len(vert_siblings[i]) == 2: - - ok = True - while ok: - ok = False - sbl = vert_siblings[contextVertLoop[0]] - if len(sbl) == 2: - next = sbl[not sbl.index( contextVertLoop[1] )] - if vert_used[next]: - closed = True - else: - contextVertLoop.insert(0, next) # get the vert that isnt the second last - vert_used[next] = True - ok = True - - mainVertLoops.append((contextVertLoop, closed)) - - - verts = me.verts - # convert from indicies to verts - # mainVertLoops = [([verts[i] for i in contextVertLoop], closed) for contextVertLoop, closed in mainVertLoops] - # print len(mainVertLoops) - return mainVertLoops - - - -def skin2EdgeLoops(eloop1, eloop2, me, ob, MODE): - - new_faces= [] # - - # Make sure e1 loops is bigger then e2 - if len(eloop1.edges) != len(eloop2.edges): - if len(eloop1.edges) < len(eloop2.edges): - eloop1, eloop2 = eloop2, eloop1 - - eloop1.backup() # were about to cull faces - CULL_FACES = len(eloop1.edges) - len(eloop2.edges) - eloop1.removeSmallest(CULL_FACES, len(eloop1.edges)) - else: - CULL_FACES = 0 - # First make sure poly vert loops are in sync with eachother. - - # The vector allong which we are skinning. - skinVector = eloop1.centre - eloop2.centre - - loopDist = skinVector.length - - # IS THE LOOP FLIPPED, IF SO FLIP BACK. we keep it flipped, its ok, - if eloop1.closed or eloop2.closed: - angleBetweenLoopNormals = AngleBetweenVecs(eloop1.normal, eloop2.normal) - if angleBetweenLoopNormals > 90: - eloop2.reverse() - - - DIR= eloop1.centre - eloop2.centre - - # if eloop2.closed: - bestEloopDist = BIG_NUM - bestOffset = 0 - # Loop rotation offset to test.1 - eLoopIdxs = range(len(eloop1.edges)) - for offset in xrange(len(eloop1.edges)): - totEloopDist = 0 # Measure this total distance for thsi loop. - - offsetIndexLs = eLoopIdxs[offset:] + eLoopIdxs[:offset] # Make offset index list - - - # e1Idx is always from 0uu to N, e2Idx is offset. - for e1Idx, e2Idx in enumerate(offsetIndexLs): - e1= eloop1.edges[e1Idx] - e2= eloop2.edges[e2Idx] - - - # Include fan connections in the measurement. - OK= True - while OK or e1.removed: - OK= False - - # Measure the vloop distance =============== - diff= ((e1.cent - e2.cent).length) #/ nangle1 - - ed_dir= e1.cent-e2.cent - a_diff= AngleBetweenVecs(DIR, ed_dir)/18 # 0 t0 18 - - totEloopDist += (diff * (1+a_diff)) / (1+loopDist) - - # Premeture break if where no better off - if totEloopDist > bestEloopDist: - break - - e1=e1.next - - if totEloopDist < bestEloopDist: - bestOffset = offset - bestEloopDist = totEloopDist - - # Modify V2 LS for Best offset - eloop2.edges = eloop2.edges[bestOffset:] + eloop2.edges[:bestOffset] - - else: - # Both are open loops, easier to calculate. - - - # Make sure the fake edges are at the start. - for i, edloop in enumerate((eloop1, eloop2)): - # print "LOOPO" - if edloop.edges[0].fake: - # alredy at the start - #print "A" - pass - elif edloop.edges[-1].fake: - # put the end at the start - edloop.edges.insert(0, edloop.edges.pop()) - #print "B" - - else: - for j, ed in enumerate(edloop.edges): - if ed.fake: - #print "C" - edloop.edges = edloop.edges = edloop.edges[j:] + edloop.edges[:j] - break - # print "DONE" - ed1, ed2 = eloop1.edges[0], eloop2.edges[0] - - if not ed1.fake or not ed2.fake: - raise "Error" - - # Find the join that isnt flipped (juts like detecting a bow-tie face) - a1 = (ed1.co1 - ed2.co1).length + (ed1.co2 - ed2.co2).length - a2 = (ed1.co1 - ed2.co2).length + (ed1.co2 - ed2.co1).length - - if a1 > a2: - eloop2.reverse() - # make the first edge the start edge still - eloop2.edges.insert(0, eloop2.edges.pop()) - - - - - for loopIdx in xrange(len(eloop2.edges)): - e1 = eloop1.edges[loopIdx] - e2 = eloop2.edges[loopIdx] - - # Remember the pairs for fan filling culled edges. - e1.match = e2; e2.match = e1 - - if not (e1.fake or e2.fake): - new_faces.append([e1.v1, e1.v2, e2.v2, e2.v1]) - - # FAN FILL MISSING FACES. - if CULL_FACES: - # Culled edges will be in eloop1. - FAN_FILLED_FACES = 0 - - contextEdge = eloop1.edges[0] # The larger of teh 2 - while FAN_FILLED_FACES < CULL_FACES: - while contextEdge.next.removed == 0: - contextEdge = contextEdge.next - - vertFanPivot = contextEdge.match.v2 - - while contextEdge.next.removed == 1: - #if not contextEdge.next.fake: - new_faces.append([contextEdge.next.v1, contextEdge.next.v2, vertFanPivot]) - - # Should we use another var?, this will work for now. - contextEdge.next.removed = 1 - - contextEdge = contextEdge.next - FAN_FILLED_FACES += 1 - - # may need to fan fill backwards 1 for non closed loops. - - eloop1.restore() # Add culled back into the list. - - return new_faces - -def main(): - global CULL_METHOD - - is_editmode = Window.EditMode() - if is_editmode: Window.EditMode(0) - ob = bpy.data.scenes.active.objects.active - if ob == None or ob.type != 'Mesh': - BPyMessages.Error_NoMeshActive() - return - - me = ob.getData(mesh=1) - - if me.multires: - BPyMessages.Error_NoMeshMultiresEdit() - return - - time1 = Blender.sys.time() - selEdges = getSelectedEdges(me, ob) - vertLoops = getVertLoops(selEdges, me) # list of lists of edges. - if vertLoops == None: - PupMenu('Error%t|Selection includes verts that are a part of more then 1 loop') - if is_editmode: Window.EditMode(1) - return - # print len(vertLoops) - - - if len(vertLoops) > 2: - choice = PupMenu('Loft '+str(len(vertLoops))+' edge loops%t|loop|segment') - if choice == -1: - if is_editmode: Window.EditMode(1) - return - elif len(vertLoops) < 2: - PupMenu('Error%t|No Vertloops found!') - if is_editmode: Window.EditMode(1) - return - else: - choice = 2 - - - # The line below checks if any of the vert loops are differenyt in length. - if False in [len(v[0]) == len(vertLoops[0][0]) for v in vertLoops]: - CULL_METHOD = PupMenu('Small to large edge loop distrobution method%t|remove edges evenly|remove smallest edges') - if CULL_METHOD == -1: - if is_editmode: Window.EditMode(1) - return - - if CULL_METHOD ==1: # RESET CULL_METHOD - CULL_METHOD = 0 # shortest - else: - CULL_METHOD = 1 # even - - - time1 = Blender.sys.time() - # Convert to special edge data. - edgeLoops = [] - for vloop, closed in vertLoops: - edgeLoops.append(edgeLoop(vloop, me, closed)) - - - # VERT LOOP ORDERING CODE - # "Build a worm" list - grow from Both ends - edgeOrderedList = [edgeLoops.pop()] - - # Find the closest. - bestSoFar = BIG_NUM - bestIdxSoFar = None - for edLoopIdx, edLoop in enumerate(edgeLoops): - l =(edgeOrderedList[-1].centre - edLoop.centre).length - if l < bestSoFar: - bestIdxSoFar = edLoopIdx - bestSoFar = l - - edgeOrderedList.append( edgeLoops.pop(bestIdxSoFar) ) - - # Now we have the 2 closest, append to either end- - # Find the closest. - while edgeLoops: - bestSoFar = BIG_NUM - bestIdxSoFar = None - first_or_last = 0 # Zero is first - for edLoopIdx, edLoop in enumerate(edgeLoops): - l1 =(edgeOrderedList[-1].centre - edLoop.centre).length - - if l1 < bestSoFar: - bestIdxSoFar = edLoopIdx - bestSoFar = l1 - first_or_last = 1 # last - - l2 =(edgeOrderedList[0].centre - edLoop.centre).length - if l2 < bestSoFar: - bestIdxSoFar = edLoopIdx - bestSoFar = l2 - first_or_last = 0 # last - - if first_or_last: # add closest Last - edgeOrderedList.append( edgeLoops.pop(bestIdxSoFar) ) - else: # Add closest First - edgeOrderedList.insert(0, edgeLoops.pop(bestIdxSoFar) ) # First - - faces = [] - - for i in xrange(len(edgeOrderedList)-1): - faces.extend( skin2EdgeLoops(edgeOrderedList[i], edgeOrderedList[i+1], me, ob, 0) ) - if choice == 1 and len(edgeOrderedList) > 2: # Loop - faces.extend( skin2EdgeLoops(edgeOrderedList[0], edgeOrderedList[-1], me, ob, 0) ) - - # REMOVE SELECTED FACES. - MESH_MODE= Blender.Mesh.Mode() - if MESH_MODE & Blender.Mesh.SelectModes.EDGE or MESH_MODE & Blender.Mesh.SelectModes.VERTEX: pass - elif MESH_MODE & Blender.Mesh.SelectModes.FACE: - try: me.faces.delete(1, [ f for f in me.faces if f.sel ]) - except: pass - - me.faces.extend(faces, smooth = True) - - print '\nSkin done in %.4f sec.' % (Blender.sys.time()-time1) - - - if is_editmode: Window.EditMode(1) - -if __name__ == '__main__': - main() diff --git a/release/scripts/mesh_solidify.py b/release/scripts/mesh_solidify.py deleted file mode 100644 index 9e11ed68c63..00000000000 --- a/release/scripts/mesh_solidify.py +++ /dev/null @@ -1,345 +0,0 @@ -#!BPY -""" -Name: 'Solidify Selection' -Blender: 243 -Group: 'Mesh' -Tooltip: 'Makes the mesh solid by creating a second skin.' -""" - -__author__ = "Campbell Barton" -__url__ = ("www.blender.org", "blenderartists.org") -__version__ = "1.1" - -__bpydoc__ = """\ -This script makes a skin from the selected faces. -Optionaly you can skin between the original and new faces to make a watertight solid object -""" - -# -------------------------------------------------------------------------- -# Solidify Selection 1.0 by Campbell Barton (AKA Ideasman42) -# -------------------------------------------------------------------------- -# ***** 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 ***** -# -------------------------------------------------------------------------- - -from Blender import * -import bpy -import BPyMesh -# reload(BPyMesh) -import BPyMessages -# reload(BPyMessages) - -from BPyMathutils import angleToLength - -# python 2.3 has no reversed() iterator. this will only work on lists and tuples -try: - reversed -except: - def reversed(l): return l[::-1] - -def copy_facedata_multilayer(me, from_faces, to_faces): - ''' - Tkes 2 lists of faces and copies multilayer data from 1 to another - make sure they are aligned, cant copy from a quad to a tri, used for solidify selection. - ''' - - def copy_default_face(data): - face_from, face_to = data - face_to.mat = face_from.mat - face_to.smooth = face_from.smooth - face_to.sel = True - face_from.sel = False - - def copy_tex_face(data): - face_from, face_to = data - face_to.uv = [c for c in reversed(face_from.uv)] - face_to.mode = face_from.mode - face_to.flag = face_from.flag - face_to.image = face_from.image - - def copy_col_face(data): - face_from, face_to = data - face_to.col = [c for c in reversed(face_from.col)] - - # make a list of face_from, face_to pairs - #face_pairs = zip(faces_sel, [me_faces[len_faces + i] for i in xrange(len(faces_sel))]) - face_pairs = zip(from_faces, to_faces) - - # Copy properties from 1 set of faces to another. - map(copy_default_face, face_pairs) - - for uvlayer in me.getUVLayerNames(): - me.activeUVLayer = uvlayer - map(copy_tex_face, face_pairs) - - for collayer in me.getColorLayerNames(): - me.activeColorLayer = collayer - map(copy_col_face, face_pairs) - - # Now add quads between if we wants - - -Ang= Mathutils.AngleBetweenVecs -SMALL_NUM=0.00001 - -def solidify(me, PREF_THICK, PREF_SKIN_SIDES=True, PREF_REM_ORIG=False, PREF_COLLAPSE_SIDES=False): - - # Main code function - me_faces = me.faces - faces_sel= [f for f in me_faces if f.sel] - - BPyMesh.meshCalcNormals(me) - normals= [v.no for v in me.verts] - vertFaces= [[] for i in xrange(len(me.verts))] - for f in me_faces: - no=f.no - for v in f: - vertFaces[v.index].append(no) - - # Scale the normals by the face angles from the vertex Normals. - for i in xrange(len(me.verts)): - length=0.0 - if vertFaces[i]: - for fno in vertFaces[i]: - try: - a= Ang(fno, normals[i]) - except: - a= 0 - if a>=90: - length+=1 - elif a < SMALL_NUM: - length+= 1 - else: - length+= angleToLength(a) - - length= length/len(vertFaces[i]) - #print 'LENGTH %.6f' % length - # normals[i]= (normals[i] * length) * PREF_THICK - normals[i] *= length * PREF_THICK - - - - len_verts = len( me.verts ) - len_faces = len( me_faces ) - - vert_mapping= [-1] * len(me.verts) - verts= [] - for f in faces_sel: - for v in f: - i= v.index - if vert_mapping[i]==-1: - vert_mapping[i]= len_verts + len(verts) - verts.append(v.co + normals[i]) - - #verts= [v.co + normals[v.index] for v in me.verts] - - me.verts.extend( verts ) - #faces= [tuple([ me.verts[v.index+len_verts] for v in reversed(f.v)]) for f in me_faces ] - faces= [ tuple([vert_mapping[v.index] for v in reversed(f.v)]) for f in faces_sel ] - me_faces.extend( faces ) - - - - - # Old method before multi UVs - """ - has_uv = me.faceUV - has_vcol = me.vertexColors - for i, orig_f in enumerate(faces_sel): - new_f= me_faces[len_faces + i] - new_f.mat = orig_f.mat - new_f.smooth = orig_f.smooth - orig_f.sel=False - new_f.sel= True - new_f = me_faces[i+len_faces] - if has_uv: - new_f.uv = [c for c in reversed(orig_f.uv)] - new_f.mode = orig_f.mode - new_f.flag = orig_f.flag - if orig_f.image: - new_f.image = orig_f.image - if has_vcol: - new_f.col = [c for c in reversed(orig_f.col)] - """ - copy_facedata_multilayer(me, faces_sel, [me_faces[len_faces + i] for i in xrange(len(faces_sel))]) - - if PREF_SKIN_SIDES or PREF_COLLAPSE_SIDES: - skin_side_faces= [] - skin_side_faces_orig= [] - # Get edges of faces that only have 1 user - so we can make walls - edges = {} - - # So we can reference indicies that wrap back to the start. - ROT_TRI_INDEX = 0,1,2,0 - ROT_QUAD_INDEX = 0,1,2,3,0 - - for f in faces_sel: - f_v= f.v - for i, edgekey in enumerate(f.edge_keys): - if edges.has_key(edgekey): - edges[edgekey]= None - else: - if len(f_v) == 3: - edges[edgekey] = f, f_v, i, ROT_TRI_INDEX[i+1] - else: - edges[edgekey] = f, f_v, i, ROT_QUAD_INDEX[i+1] - del ROT_QUAD_INDEX, ROT_TRI_INDEX - - # So we can remove doubles with edges only. - if PREF_COLLAPSE_SIDES: - me.sel = False - - # Edges are done. extrude the single user edges. - for edge_face_data in edges.itervalues(): - if edge_face_data: # != None - f, f_v, i1, i2 = edge_face_data - v1i,v2i= f_v[i1].index, f_v[i2].index - - if PREF_COLLAPSE_SIDES: - # Collapse - cv1 = me.verts[v1i] - cv2 = me.verts[vert_mapping[v1i]] - - cv3 = me.verts[v2i] - cv4 = me.verts[vert_mapping[v2i]] - - cv1.co = cv2.co = (cv1.co+cv2.co)/2 - cv3.co = cv4.co = (cv3.co+cv4.co)/2 - - cv1.sel=cv2.sel=cv3.sel=cv4.sel=True - - - - else: - # Now make a new Face - # skin_side_faces.append( (v1i, v2i, vert_mapping[v2i], vert_mapping[v1i]) ) - skin_side_faces.append( (v2i, v1i, vert_mapping[v1i], vert_mapping[v2i]) ) - skin_side_faces_orig.append((f, len(me_faces) + len(skin_side_faces_orig), i1, i2)) - - if PREF_COLLAPSE_SIDES: - me.remDoubles(0.0001) - else: - me_faces.extend(skin_side_faces) - # Now assign properties. - """ - # Before MultiUVs - for i, origfData in enumerate(skin_side_faces_orig): - orig_f, new_f_idx, i1, i2 = origfData - new_f= me_faces[new_f_idx] - - new_f.mat= orig_f.mat - new_f.smooth= orig_f.smooth - if has_uv: - new_f.mode= orig_f.mode - new_f.flag= orig_f.flag - if orig_f.image: - new_f.image= orig_f.image - - uv1= orig_f.uv[i1] - uv2= orig_f.uv[i2] - new_f.uv= (uv1, uv2, uv2, uv1) - - if has_vcol: - col1= orig_f.col[i1] - col2= orig_f.col[i2] - new_f.col= (col1, col2, col2, col1) - """ - - for i, origfData in enumerate(skin_side_faces_orig): - orig_f, new_f_idx, i2, i1 = origfData - new_f= me_faces[new_f_idx] - - new_f.mat= orig_f.mat - new_f.smooth= orig_f.smooth - - for uvlayer in me.getUVLayerNames(): - me.activeUVLayer = uvlayer - for i, origfData in enumerate(skin_side_faces_orig): - orig_f, new_f_idx, i2, i1 = origfData - new_f= me_faces[new_f_idx] - - new_f.mode= orig_f.mode - new_f.flag= orig_f.flag - new_f.image= orig_f.image - - uv1= orig_f.uv[i1] - uv2= orig_f.uv[i2] - new_f.uv= (uv1, uv2, uv2, uv1) - - for collayer in me.getColorLayerNames(): - me.activeColorLayer = collayer - for i, origfData in enumerate(skin_side_faces_orig): - orig_f, new_f_idx, i2, i1 = origfData - new_f= me_faces[new_f_idx] - - col1= orig_f.col[i1] - col2= orig_f.col[i2] - new_f.col= (col1, col2, col2, col1) - - - if PREF_REM_ORIG: - me_faces.delete(0, faces_sel) - - - - -def main(): - scn = bpy.data.scenes.active - ob = scn.objects.active - - if not ob or ob.type != 'Mesh': - BPyMessages.Error_NoMeshActive() - return - - me = ob.getData(mesh=1) - if me.multires: - BPyMessages.Error_NoMeshMultiresEdit() - return - - # Create the variables. - PREF_THICK = Draw.Create(-0.1) - PREF_SKIN_SIDES= Draw.Create(1) - PREF_COLLAPSE_SIDES= Draw.Create(0) - PREF_REM_ORIG= Draw.Create(0) - - pup_block = [\ - ('Thick:', PREF_THICK, -10, 10, 'Skin thickness in mesh space.'),\ - ('Skin Sides', PREF_SKIN_SIDES, 'Skin between the original and new faces.'),\ - ('Collapse Sides', PREF_COLLAPSE_SIDES, 'Skin between the original and new faces.'),\ - ('Remove Original', PREF_REM_ORIG, 'Remove the selected faces after skinning.'),\ - ] - - if not Draw.PupBlock('Solid Skin Selection', pup_block): - return - - is_editmode = Window.EditMode() - if is_editmode: Window.EditMode(0) - - Window.WaitCursor(1) - - me = ob.getData(mesh=1) - solidify(me, PREF_THICK.val, PREF_SKIN_SIDES.val, PREF_REM_ORIG.val, PREF_COLLAPSE_SIDES.val) - - - Window.WaitCursor(0) - if is_editmode: Window.EditMode(1) - - Window.RedrawAll() - -if __name__ == '__main__': - main()
\ No newline at end of file diff --git a/release/scripts/mesh_unfolder.py b/release/scripts/mesh_unfolder.py deleted file mode 100644 index f5c19a92bd0..00000000000 --- a/release/scripts/mesh_unfolder.py +++ /dev/null @@ -1,1582 +0,0 @@ -#!BPY -""" -Name: 'Unfold' -Blender: 245 -Group: 'Mesh' -Tip: 'Unfold meshes to create nets' -Version: v2.5 -Author: Matthew Chadwick -""" -import Blender -from Blender import * -from Blender.Mathutils import * -try: - import sys - import traceback - import math - import re - from math import * - import sys - import random - import xml.sax, xml.sax.handler, xml.sax.saxutils - - # annoying but need so classes dont raise errors - xml_sax_handler_ContentHandler = xml.sax.handler.ContentHandler - -except: - Draw.PupMenu('Error%t|A full python installation is required to run this script.') - xml = None - xml_sax_handler_ContentHandler = type(0) - -__author__ = 'Matthew Chadwick' -__version__ = '2.5 06102007' -__url__ = ["http://celeriac.net/unfolder/", "blender", "blenderartist"] -__email__ = ["post at cele[remove this text]riac.net", "scripts"] -__bpydoc__ = """\ - -Mesh Unfolder - -Unfolds the selected mesh onto a plane to form a net - -Not all meshes can be unfolded - -Meshes must be free of holes, -isolated edges (not part of a face), twisted quads and other rubbish. -Nice clean triangulated meshes unfold best - -This program is free software; you can distribute it and/or modify it under the terms -of the GNU General Public License as published by the Free Software Foundation; version 2 -or later, currently at http://www.gnu.org/copyleft/gpl.html - -The idea came while I was riding a bike. -""" - -# ***** 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 ***** - -# Face lookup -class FacesAndEdges: - def __init__(self, mesh): - self.nfaces = 0 - # straight from the documentation - self.edgeFaces = dict([(edge.key, []) for edge in mesh.edges]) - for face in mesh.faces: - face.sel = False - for key in face.edge_keys: - self.edgeFaces[key].append(face) - def findTakenAdjacentFace(self, bface, edge): - return self.findAdjacentFace(bface, edge) - # find the first untaken (non-selected) adjacent face in the list of adjacent faces for the given edge (allows for manifold meshes too) - def findAdjacentFace(self, bface, edge): - faces = self.edgeFaces[edge.key()] - for i in xrange(len(faces)): - if faces[i] == bface: - j = (i+1) % len(faces) - while(faces[j]!=bface): - if faces[j].sel == False: - return faces[j] - j = (j+1) % len(faces) - return None - def returnFace(self, face): - face.sel = False - self.nfaces-=1 - def facesTaken(self): - return self.nfaces - def takeAdjacentFace(self, bface, edge): - if (edge==None): - return None - face = self.findAdjacentFace(bface, edge) - if(face!=None): - face.sel = True - self.nfaces+=1 - return face - def takeFace(self, bface): - if(bface!=None): - bface.sel= True - self.nfaces+=1 - - -# A fold between two faces with a common edge -class Fold: - ids = -1 - def __init__(self, parent, refPoly, poly, edge, angle=None): - Fold.ids+=1 - self.id = Fold.ids - self.refPoly = refPoly - self.poly = poly - self.srcFace = None - self.desFace = None - self.edge = edge - self.foldedEdge = edge - self.rm = None - self.parent = parent - self.tree = None - if(refPoly!=None): - self.refPolyNormal = refPoly.normal() - self.polyNormal = poly.normal() - if(angle==None): - self.angle = self.calculateAngle() - self.foldingPoly = poly.rotated(edge, self.angle) - else: - self.angle = angle - self.foldingPoly = poly - self.unfoldedEdge = self.edge - self.unfoldedNormal = None - self.animAngle = self.angle - self.cr = None - self.nancestors = None - def reset(self): - self.foldingPoly = self.poly.rotated(self.edge, self.dihedralAngle()) - def getID(self): - return self.id - def getParent(self): - return self.parent - def ancestors(self): - if(self.nancestors==None): - self.nancestors = self.computeAncestors() - return self.nancestors - def computeAncestors(self): - if(self.parent==None): - return 0 - else: - return self.parent.ancestors()+1 - def dihedralAngle(self): - return self.angle - def unfoldTo(self, f): - self.animAngle = self.angle*f - self.foldingPoly = self.poly.rotated(self.edge, self.animAngle) - def calculateAngle(self): - sangle = Mathutils.AngleBetweenVecs(self.refPolyNormal, self.polyNormal) - if(sangle!=sangle): - sangle=0.0 - ncp = self.refPolyNormal.cross(self.polyNormal) - dp = ncp.dot(self.edge.vector) - if(dp>0.0): - return +sangle - else: - return -sangle - def alignWithParent(self): - pass - def unfoldedNormal(self): - return self.unfoldedNormal - def getEdge(self): - return self.edge - def getFace(self): - return self.poly - def testFace(self): - return Poly.fromVectors([self.edge.v1, self.edge.v2, Vector([0,0,0])]) - def unfoldedFace(self): - return self.foldingPoly - def unfold(self): - if(self.parent!=None): - self.parent.foldFace(self) - def foldFace(self, child): - child.foldingPoly.rotate(self.edge, self.animAngle) - if(self.parent!=None): - self.parent.foldFace(child) - -class Cut(Fold): - pass - -# Trees build folds by traversing the mesh according to a local measure -class Tree: - def __init__(self, net, parent,fold,otherConstructor=None): - self.net = net - self.fold = fold - self.face = fold.srcFace - self.poly = Poly.fromBlenderFace(self.face) - self.generations = net.generations - self.growing = True - self.tooLong = False - self.parent = parent - self.grown = False - if not(otherConstructor): - self.edges = net.edgeIteratorClass(self) - def goodness(self): - return self.edges.goodness() - def compare(self, other): - if(self.goodness() > other.goodness()): - return +1 - else: - return -1 - def isGrowing(self): - return self.growing - def beGrowing(self): - self.growing = True - def grow(self): - self.tooLong = self.fold.ancestors()>self.generations - if(self.edges.hasNext() and self.growing): - edge = self.edges.next() - tface = self.net.facesAndEdges.takeAdjacentFace(self.face, edge) - if(tface!=None): - self.branch(tface, edge) - if(self.parent==None): - self.grow() - else: - self.grown = True - def isGrown(self): - return self.grown - def canGrow(self): - return (self.parent!=None and self.parent.grown) - def getNet(self): - return self.net - def getFold(self): - return self.fold - def getFace(self): - return self.face - def branch(self, tface, edge): - fold = Fold(self.fold, self.poly, Poly.fromBlenderFace(tface), edge) - fold.srcFace = tface - self.net.myFacesVisited+=1 - tree = Tree(self.net, self, fold) - fold.tree = tree - fold.unfold() - overlaps = self.net.checkOverlaps(fold) - nc = len(overlaps) - self.net.overlaps+=nc - if(nc>0 and self.net.avoidsOverlaps): - self.handleOverlap(fold, overlaps) - else: - self.addFace(fold) - def handleOverlap(self, fold, overlaps): - self.net.facesAndEdges.returnFace(fold.srcFace) - self.net.myFacesVisited-=1 - for cfold in overlaps: - ttree = cfold.tree - ttree.growing = True - ttree.grow() - def addFace(self, fold): - ff = fold.unfoldedFace() - fold.desFace = self.net.addFace(ff, fold.srcFace) - self.net.folds.append(fold) - self.net.addBranch(fold.tree) - fold.tree.growing = not(self.tooLong) - if(self.net.diffuse==False): - fold.tree.grow() - -# A Net is the result of the traversal of the mesh by Trees -class Net: - def __init__(self, src, des): - self.src = src - self.des = des - self.firstFace = None - self.firstPoly = None - self.refFold = None - self.edgeIteratorClass = RandomEdgeIterator - if(src!=None): - self.srcFaces = src.faces - self.facesAndEdges = FacesAndEdges(self.src) - self.myFacesVisited = 0 - self.facesAdded = 0 - self.folds = [] - self.cuts = [] - self.branches = [] - self.overlaps = 0 - self.avoidsOverlaps = True - self.frame = 1 - self.ff = 180.0 - self.firstFaceIndex = None - self.trees = 0 - self.foldIPO = None - self.perFoldIPO = None - self.IPOCurves = {} - self.generations = 128 - self.diffuse = True - self.noise = 0.0 - self.grownBranches = 0 - self.assignsUV = True - self.animates = False - self.showProgress = False - self.feedback = None - def setSelectedFaces(self, faces): - self.srcFaces = faces - self.facesAndEdges = FacesAndEdges(self.srcFaces) - def setShowProgress(self, show): - self.showProgress = show - # this method really needs work - def unfold(self): - selectedFaces = [face for face in self.src.faces if (self.src.faceUV and face.sel)] - if(self.avoidsOverlaps): - print "unfolding with overlap detection" - if(self.firstFaceIndex==None): - self.firstFaceIndex = random.randint(0, len(self.src.faces)-1) - else: - print "Using user-selected seed face ", self.firstFaceIndex - self.firstFace = self.src.faces[self.firstFaceIndex] - z = min([v.co.z for v in self.src.verts])-0.1 - ff = Poly.fromBlenderFace(self.firstFace) - if(len(ff.v)<3): - raise Exception("This mesh contains an isolated edge - it must consist only of faces") - testFace = Poly.fromVectors( [ Vector([0.0,0.0,0.0]), Vector([0.0,1.0,0.0]), Vector([1.0,1.0,0.0]) ] ) - # hmmm. I honestly can't remember why this needs to be done, but it does. - u=0 - v=1 - w=2 - if ff.v[u].x==ff.v[u+1].x and ff.v[u].y==ff.v[u+1].y: - u=1 - v=2 - w=0 - # here we make a couple of folds, not part of the net, which serve to get the net into the xy plane - xyFace = Poly.fromList( [ [ff.v[u].x,ff.v[u].y, z] , [ff.v[v].x,ff.v[v].y, z] , [ff.v[w].x+0.1,ff.v[w].y+0.1, z] ] ) - refFace = Poly.fromVectors([ ff.v[u], ff.v[v], xyFace.v[1], xyFace.v[0] ] ) - xyFold = Fold(None, xyFace, refFace, Edge(xyFace.v[0], xyFace.v[1] )) - self.refFold = Fold(xyFold, refFace, ff, Edge(refFace.v[0], refFace.v[1] )) - self.refFold.srcFace = self.firstFace - # prepare to grow the trees - trunk = Tree(self, None, self.refFold) - trunk.generations = self.generations - self.firstPoly = ff - self.facesAndEdges.takeFace(self.firstFace) - self.myFacesVisited+=1 - self.refFold.unfold() - self.refFold.tree = trunk - self.refFold.desFace = self.addFace(self.refFold.unfoldedFace(), self.refFold.srcFace) - self.folds.append(self.refFold) - trunk.grow() - i = 0 - # keep the trees growing while they can - while(self.myFacesVisited<len(self.src.faces) and len(self.branches) > 0): - if self.edgeIteratorClass==RandomEdgeIterator: - i = random.randint(0,len(self.branches)-1) - tree = self.branches[i] - if(tree.isGrown()): - self.branches.pop(i) - else: - tree.beGrowing() - if(tree.canGrow()): - tree.grow() - i = 0 - else: - i = (i + 1) % len(self.branches) - if self.src.faceUV: - for face in self.src.faces: - face.sel = False - for face in selectedFaces: - face.sel = True - self.src.update() - Window.RedrawAll() - def assignUVs(self): - for fold in self.folds: - self.assignUV(fold.srcFace, fold.unfoldedFace()) - print " assigned uv to ", len(self.folds), len(self.src.faces) - self.src.update() - def checkOverlaps(self, fold): - #return self.getOverlapsBetween(fold, self.folds) - return self.getOverlapsBetweenGL(fold, self.folds) - def getOverlapsBetween(self, fold, folds): - if(fold.parent==None): - return [] - mf = fold.unfoldedFace() - c = [] - for afold in folds: - mdf = afold.unfoldedFace() - if(afold!=fold): - # currently need to get agreement from both polys because - # a touch by a vertex of one the other's edge is acceptable & - # they disagree on that - intersects = mf.intersects2D(mdf) and mdf.intersects2D(mf) - inside = ( mdf.containsAnyOf(mf) or mf.containsAnyOf(mdf) ) - if( intersects or inside or mdf.overlays(mf)): - c.append(afold) - return c - def getOverlapsBetweenGL(self, fold, folds): - b = fold.unfoldedFace().bounds() - polys = len(folds)*4+16 # the buffer is nhits, mindepth, maxdepth, name - buffer = BGL.Buffer(BGL.GL_INT, polys) - BGL.glSelectBuffer(polys, buffer) - BGL.glRenderMode(BGL.GL_SELECT) - BGL.glInitNames() - BGL.glPushName(0) - BGL.glPushMatrix() - BGL.glMatrixMode(BGL.GL_PROJECTION) - BGL.glLoadIdentity() - BGL.glOrtho(b[0].x, b[1].x, b[1].y, b[0].y, 0.0, 10.0) - #clip = BGL.Buffer(BGL.GL_FLOAT, 4) - #clip.list = [0,0,0,0] - #BGL.glClipPlane(BGL.GL_CLIP_PLANE1, clip) - # could use clipping planes here too - BGL.glMatrixMode(BGL.GL_MODELVIEW) - BGL.glLoadIdentity() - bx = (b[1].x - b[0].x) - by = (b[1].y - b[0].y) - cx = bx / 2.0 - cy = by / 2.0 - for f in xrange(len(folds)): - afold = folds[f] - if(fold!=afold): - BGL.glLoadName(f) - BGL.glBegin(BGL.GL_LINE_LOOP) - for v in afold.unfoldedFace().v: - BGL.glVertex2f(v.x, v.y) - BGL.glEnd() - BGL.glPopMatrix() - BGL.glFlush() - hits = BGL.glRenderMode(BGL.GL_RENDER) - buffer = [buffer[i] for i in xrange(3, 4*hits, 4)] - o = [folds[buffer[i]] for i in xrange(len(buffer))] - return self.getOverlapsBetween(fold, o) - def colourFace(self, face, cr): - for c in face.col: - c.r = int(cr[0]) - c.g = int(cr[1]) - c.b = int(cr[2]) - c.a = int(cr[3]) - self.src.update() - def setAvoidsOverlaps(self, avoids): - self.avoidsOverlaps = avoids - def addBranch(self, branch): - self.branches.append(branch) - if self.edgeIteratorClass!=RandomEdgeIterator: - self.branches.sort(lambda b1, b2: b1.compare(b2)) - def srcSize(self): - return len(self.src.faces) - def nBranches(self): - return len(self.branches) - def facesCreated(self): - return len(self.des.faces) - def facesVisited(self): - return self.myFacesVisited - def getOverlaps(self): - return self.overlaps - def sortOutIPOSource(self): - print "Sorting out IPO" - if self.foldIPO!=None: - return - o = None - try: - o = Blender.Object.Get("FoldRate") - except: - o = Blender.Object.New("Empty", "FoldRate") - Blender.Scene.GetCurrent().objects.link(o) - if(o.getIpo()==None): - ipo = Blender.Ipo.New("Object", "FoldRateIPO") - z = ipo.addCurve("RotZ") - print " added RotZ IPO curve" - z.addBezier((1,0)) - # again, why is this 10x out ? - z.addBezier((180, self.ff/10.0)) - z.addBezier((361, 0.0)) - o.setIpo(ipo) - z.recalc() - z.setInterpolation("Bezier") - z.setExtrapolation("Cyclic") - self.setIPOSource(o) - print " added IPO source" - def setIPOSource(self, object): - try: - self.foldIPO = object - for i in xrange(self.foldIPO.getIpo().getNcurves()): - self.IPOCurves[self.foldIPO.getIpo().getCurves()[i].getName()] = i - print " added ", self.foldIPO.getIpo().getCurves()[i].getName() - except: - print "Problem setting IPO object" - print sys.exc_info()[1] - traceback.print_exc(file=sys.stdout) - def setFoldFactor(self, ff): - self.ff = ff - def sayTree(self): - for fold in self.folds: - if(fold.getParent()!=None): - print fold.getID(), fold.dihedralAngle(), fold.getParent().getID() - def report(self): - p = int(float(self.myFacesVisited)/float(len(self.src.faces)) * 100) - print str(p) + "% unfolded" - print "faces created:", self.facesCreated() - print "faces visited:", self.facesVisited() - print "originalfaces:", len(self.src.faces) - n=0 - if(self.avoidsOverlaps): - print "net avoided at least ", self.getOverlaps(), " overlaps ", - n = len(self.src.faces) - self.facesCreated() - if(n>0): - print "but was unable to avoid ", n, " overlaps. Incomplete net." - else: - print "- A complete net." - else: - print "net has at least ", self.getOverlaps(), " collision(s)" - return n - # fold all my folds to a fraction of their total fold angle - def unfoldToCurrentFrame(self): - self.unfoldTo(Blender.Scene.GetCurrent().getRenderingContext().currentFrame()) - def unfoldTo(self, frame): - frames = Blender.Scene.GetCurrent().getRenderingContext().endFrame() - if(self.foldIPO!=None and self.foldIPO.getIpo()!=None): - f = self.foldIPO.getIpo().EvaluateCurveOn(self.IPOCurves["RotZ"],frame) - # err, this number seems to be 10x less than it ought to be - fff = 1.0 - (f*10.0 / self.ff) - else: - fff = 1.0-((frame)/(frames*1.0)) - for fold in self.folds: - fold.unfoldTo(fff) - for fold in self.folds: - fold.unfold() - tface = fold.unfoldedFace() - bface = fold.desFace - i = 0 - for v in bface.verts: - v.co.x = tface.v[i].x - v.co.y = tface.v[i].y - v.co.z = tface.v[i].z - i+=1 - Window.Redraw(Window.Types.VIEW3D) - return None - def addFace(self, poly, originalFace=None): - originalLength = len(self.des.verts) - self.des.verts.extend([Vector(vv.x, vv.y, vv.z) for vv in poly.v]) - self.des.faces.extend([ range(originalLength, originalLength + poly.size()) ]) - newFace = self.des.faces[len(self.des.faces)-1] - newFace.uv = [vv for vv in poly.v] - if(originalFace!=None and self.src.vertexColors): - newFace.col = [c for c in originalFace.col] - if(self.feedback!=None): - pu = str(int(self.fractionUnfolded() * 100))+"% unfolded" - howMuchDone = str(self.myFacesVisited)+" of "+str(len(self.src.faces))+" "+pu - self.feedback.say(howMuchDone) - #Window.DrawProgressBar (p, pu) - if(self.showProgress): - Window.Redraw(Window.Types.VIEW3D) - return newFace - def fractionUnfolded(self): - return float(self.myFacesVisited)/float(len(self.src.faces)) - def assignUV(self, face, uv): - face.uv = [Vector(v.x, v.y) for v in uv.v] - def unfoldAll(feedback=None): - objects = Blender.Object.Get() - for object in objects: - if(object.getType()=='Mesh' and not(object.getName().endswith("_net")) and len(object.getData(False, True).faces)>1): - net = Net.createNet(object, feedback) - net.searchForUnfolding() - svg = SVGExporter(net, object.getName()+".svg") - svg.export() - unfoldAll = staticmethod(unfoldAll) - def searchForUnfolding(self, limit=-1): - overlaps = 1 - attempts = 0 - while(overlaps > 0 or attempts<limit): - self.unfold() - overlaps = self.report() - attempts+=1 - return attempts - def fromSelected(feedback=None, netName=None): - return Net.createNet(Blender.Object.GetSelected()[0], feedback, netName) - fromSelected = staticmethod(fromSelected) - def clone(self, object=None): - if(object==None): - object = self.object - net = Net.createNet(object, self.feedback) - net.avoidsOverlaps = net.avoidsOverlaps - return net - def createNet(ob, feedback=None, netName=None): - mesh = ob.getData(mesh=1) - netObject = None - if(netName==None): - netName = ob.name[0:16]+"_net" - try: - netObject = Blender.Object.Get(netName) - netMesh = netObject.getData(False, True) - if(netMesh!=None): - netMesh.verts = None # clear the mesh - else: - netObject = Blender.Object.New("Mesh", netName) - except: - if(netObject==None): - netObject = Blender.Object.New("Mesh", netName) - netMesh = netObject.getData(False, True) # True means "as a Mesh not an NMesh" - try: - Blender.Scene.GetCurrent().objects.link(netObject) - except: - pass - try: - netMesh.materials = mesh.materials - netMesh.vertexColors = True - except: - print "Problem setting materials here" - net = Net(mesh, netMesh) - if mesh.faceUV and mesh.activeFace>=0 and (mesh.faces[mesh.activeFace].sel): - net.firstFaceIndex = mesh.activeFace - net.object = ob - net.feedback = feedback - return net - createNet = staticmethod(createNet) - def importNet(filename): - netName = filename.rstrip(".svg").replace("\\","/") - netName = netName[netName.rfind("/")+1:] - try: - netObject = Blender.Object.Get(netName) - except: - netObject = Blender.Object.New("Mesh", netName) - netObject.getData(mesh=1).name = netName - try: - Blender.Scene.GetCurrent().objects.link(netObject) - except: - pass - net = Net(None, netObject.getData(mesh=1)) - handler = NetHandler(net) - xml.sax.parse(filename, handler) - Window.Redraw(Window.Types.VIEW3D) - return net - importNet = staticmethod(importNet) - def getSourceMesh(self): - return self.src - -# determines the order in which to visit faces according to a local measure -class EdgeIterator: - def __init__(self, branch, otherConstructor=None): - self.branch = branch - self.bface = branch.getFace() - self.edge = branch.getFold().getEdge() - self.net = branch.getNet() - self.n = len(self.bface) - self.edges = [] - self.i = 0 - self.gooodness = 0 - self.createEdges() - self.computeGoodness() - if(otherConstructor==None): - self.sequenceEdges() - def createEdges(self): - edge = None - e = Edge.edgesOfBlenderFace(self.net.getSourceMesh(), self.bface) - for edge in e: - if not(edge.isBlenderSeam() and edge!=self.edge): - self.edges.append(edge) - def sequenceEdges(self): - pass - def next(self): - edge = self.edges[self.i] - self.i+=1 - return edge - def size(self): - return len(self.edges) - def reset(self): - self.i = 0 - def hasNext(self): - return (self.i<len(self.edges)) - def goodness(self): - return self.gooodness - def computeGoodness(self): - self.gooodness = 0 - def rotate(self): - self.edges.append(self.edges.pop(0)) - -class RandomEdgeIterator(EdgeIterator): - def sequenceEdges(self): - random.seed() - random.shuffle(self.edges) - def goodness(self): - return random.randint(0, self.net.srcSize()) - - -class Largest(EdgeIterator): - def sequenceEdges(self): - for e in self.edges: - f = self.net.facesAndEdges.findAdjacentFace(self.bface, e) - if(f!=None): - e.setGoodness(f.area) - self.edges.sort(lambda e1, e2: -e1.compare(e2)) - def computeGoodness(self): - self.gooodness = self.bface.area - - -class Brightest(EdgeIterator): - def sequenceEdges(self): - for edge in self.edges: - f = self.net.facesAndEdges.findAdjacentFace(self.bface, edge) - if(f!=None): - b = 0 - if self.net.src.vertexColors: - for c in f.col: - b+=(c.g+c.r+c.b) - rc = float(random.randint(0, self.net.srcSize())) / float(self.net.srcSize()) / 100.0 - b+=rc - edge.setGoodness(b) - self.edges.sort(lambda e1, e2: e1.compare(e2)) - def computeGoodness(self): - g = 0 - if self.net.src.vertexColors: - for c in self.bface.col: - g+=(c.g+c.r+c.b) - self.gooodness = g - -class OddEven(EdgeIterator): - i = True - def sequenceEdges(self): - OddEven.i = not(OddEven.i) - if(OddEven.i): - self.edges.reverse() - -class Curvature(EdgeIterator): - def sequenceEdges(self): - p1 = Poly.fromBlenderFace(self.bface) - gg = 0.0 - for edge in self.edges: - f = self.net.facesAndEdges.findAdjacentFace(self.bface, edge) - if(f!=None): - p2 = Poly.fromBlenderFace(f) - fold = Fold(None, p1, p2, edge) - fold.srcFace = f - b = Tree(self.net, self.branch, fold, self) - c = Curvature(b, False) - g = c.goodness() - gg+=g - edge.setGoodness(g) - self.edges.sort(lambda e1, e2: e1.compare(e2)) - tg = (self.gooodness + gg) - rc = float(random.randint(0, self.net.srcSize())) / float(self.net.srcSize()) / 100.0 - if(tg!=0.0): - self.gooodness = self.gooodness + rc / tg - def computeGoodness(self): - g = 0 - for edge in self.edges: - f = self.net.facesAndEdges.findAdjacentFace(self.bface, edge) - if(f!=None): - p1 = Poly.fromBlenderFace(self.bface) - p2 = Poly.fromBlenderFace(f) - f = Fold(None, p1, p2, edge) - g += f.dihedralAngle() - self.gooodness = g - - -class Edge: - def __init__(self, v1=None, v2=None, mEdge=None, i=-1): - self.idx = i - if v1 and v2: - self.v1 = v1.copy() - self.v2 = v2.copy() - else: - self.v1 = mEdge.v1.co.copy() - self.v2 = mEdge.v2.co.copy() - self.v1n = -self.v1 - self.vector = self.v1-self.v2 - self.vector.resize3D() - self.vector.normalize() - self.bmEdge = mEdge - self.gooodness = 0.0 - def fromBlenderFace(mesh, bface, i): - if(i>len(bface)-1): - return None - if(i==len(bface)-1): - j = 0 - else: - j = i+1 - edge = Edge( bface.v[i].co.copy(), bface.v[j].co.copy() ) - edge.bEdge = mesh.findEdge(bface.v[i], bface.v[j]) - edge.idx = i - return edge - fromBlenderFace=staticmethod(fromBlenderFace) - def edgesOfBlenderFace(mesh, bmFace): - edges = [mesh.edges[mesh.findEdges(edge[0], edge[1])] for edge in bmFace.edge_keys] - v = bmFace.verts - e = [] - vi = v[0] - i=0 - for j in xrange(1, len(bmFace)+1): - vj = v[j%len(bmFace)] - for ee in edges: - if((ee.v1.index==vi.index and ee.v2.index==vj.index) or (ee.v2.index==vi.index and ee.v1.index==vj.index)): - e.append(Edge(vi.co, vj.co, ee, i)) - i+=1 - vi = vj - return e - edgesOfBlenderFace=staticmethod(edgesOfBlenderFace) - def isBlenderSeam(self): - return (self.bmEdge.flag & Mesh.EdgeFlags.SEAM) - def isInFGon(self): - return (self.bmEdge.flag & Mesh.EdgeFlags.FGON) - def mapTo(self, poly): - if(self.idx==len(poly.v)-1): - j = 0 - else: - j = self.idx+1 - return Edge(poly.v[self.idx], poly.v[j]) - def isDegenerate(self): - return self.vector.length==0 - def vertices(s): - return [ [s.v1.x, s.v1.y, s.v1.z], [s.v2.x, s.v2.y,s.v2.z] ] - def key(self): - return self.bmEdge.key - def goodness(self): - return self.gooodness - def setGoodness(self, g): - self.gooodness = g - def compare(self, other): - if(self.goodness() > other.goodness()): - return +1 - else: - return -1 - # Does the given segment intersect this, for overlap detection. - # endpoints are allowed to touch the line segment - def intersects2D(self, s): - if(self.matches(s)): - return False - else: - i = Geometry.LineIntersect2D(self.v1, self.v2, s.v1, s.v2) - if(i!=None): - i.resize4D() - i.z = self.v1.z # hack to put the point on the same plane as this edge for comparison - return(i!=None and not(self.endsWith(i))) - def matches(self, s): - return ( (self.v1==s.v1 and self.v2==s.v2) or (self.v2==s.v1 and self.v1==s.v2) ) - # Is the given point on the end of this segment ? 10-5 seems to an acceptable limit for closeness in Blender - def endsWith(self, aPoint, e=0.0001): - return ( (self.v1-aPoint).length < e or (self.v2-aPoint).length < e ) - - -class Poly: - ids = -1 - def __init__(self): - Poly.ids+=1 - self.v = [] - self.id = Poly.ids - self.boundz = None - self.edges = None - def getID(self): - return self.id - def normal(self): - a =self.v[0] - b=self.v[1] - c=self.v[2] - p = b-a - p.resize3D() - q = a-c - q.resize3D() - return p.cross(q) - def makeEdges(self): - self.edges = [] - for i in xrange(self.nPoints()): - self.edges.append(Edge( self.v[i % self.nPoints()], self.v[ (i+1) % self.nPoints()] )) - def edgeAt(self, i): - if(self.edges==None): - self.makeEdges() - return self.edges[i] - def intersects2D(self, poly): - for i in xrange(self.nPoints()): - edge = self.edgeAt(i) - for j in xrange(poly.nPoints()): - if edge.intersects2D(poly.edgeAt(j)): - return True - return False - def isBad(self): - badness = 0 - for vv in self.v: - if(vv.x!=vv.x or vv.y!=vv.y or vv.z!=vv.z): # Nan check - badness+=1 - return (badness>0) - def midpoint(self): - x=y=z = 0.0 - n = 0 - for vv in self.v: - x+=vv.x - y+=vv.y - z+=vv.z - n+=1 - return [ x/n, y/n, z/n ] - def centerAtOrigin(self): - mp = self.midpoint() - mp = -mp - toOrigin = TranslationMatrix(mp) - self.v = [(vv * toOrigin) for vv in self.v] - def move(self, tv): - mv = TranslationMatrix(tv) - self.v = [(vv * mv) for vv in self.v] - def scale(self, s): - mp = Vector(self.midpoint()) - fromOrigin = TranslationMatrix(mp) - mp = -mp - toOrigin = TranslationMatrix(mp) - sm = ScaleMatrix(s, 4) - # Todo, the 3 lines below in 1 LC - self.v = [(vv * toOrigin) for vv in self.v] - self.v = [(sm * vv) for vv in self.v] - self.v = [(vv * fromOrigin) for vv in self.v] - def nPoints(self): - return len(self.v) - def size(self): - return len(self.v) - def rotated(self, axis, angle): - p = self.clone() - p.rotate(axis, angle) - return p - def rotate(self, axis, angle): - rotation = RotationMatrix(angle, 4, "r", axis.vector) - toOrigin = TranslationMatrix(axis.v1n) - fromOrigin = TranslationMatrix(axis.v1) - # Todo, the 3 lines below in 1 LC - self.v = [(vv * toOrigin) for vv in self.v] - self.v = [(rotation * vv) for vv in self.v] - self.v = [(vv * fromOrigin) for vv in self.v] - def moveAlong(self, vector, distance): - t = TranslationMatrix(vector) - s = ScaleMatrix(distance, 4) - ts = t*s - self.v = [(vv * ts) for vv in self.v] - def bounds(self): - if(self.boundz == None): - vv = [vv for vv in self.v] - vv.sort(key=lambda v: v.x) - minx = vv[0].x - maxx = vv[len(vv)-1].x - vv.sort(key=lambda v: v.y) - miny = vv[0].y - maxy = vv[len(vv)-1].y - self.boundz = [Vector(minx, miny, 0), Vector(maxx, maxy, 0)] - return self.boundz - def fromBlenderFace(bface): - p = Poly() - for vv in bface.v: - vec = Vector([vv.co[0], vv.co[1], vv.co[2] , 1.0]) - p.v.append(vec) - return p - fromBlenderFace = staticmethod(fromBlenderFace) - def fromList(list): - p = Poly() - for vv in list: - vec = Vector( [vvv for vvv in vv] ) - vec.resize4D() - p.v.append(vec) - return p - fromList = staticmethod(fromList) - def fromVectors(vectors): - p = Poly() - p.v.extend([v.copy().resize4D() for v in vectors]) - return p - fromVectors = staticmethod(fromVectors) - def clone(self): - p = Poly() - p.v.extend(self.v) - return p - def hasVertex(self, ttv): - v = Mathutils.Vector(ttv) - v.normalize() - for tv in self.v: - vv = Mathutils.Vector(tv) - vv.normalize() - t = 0.00001 - if abs(vv.x-v.x)<t and abs(vv.y-v.y)<t: - return True - return False - def overlays(self, poly): - if len(poly.v)!=len(self.v): - return False - c = 0 - for point in poly.v: - if self.hasVertex(point): - c+=1 - return c==len(self.v) - def sharesVertexWith(self, poly): - for point in poly.v: - if(self.hasVertex(point)): - return True - return False - def containsAnyOf(self, poly): - for point in poly.v: - if(not(self.hasVertex(point))): - if self.contains(point): - return True - return False - def toString(self): - return self.v - # This is the BEST algorithm for point-in-polygon detection. - # It's by W. Randolph Franklin. - # returns 1 for inside, 1 or 0 for edges - def contains(self, tp): - c = 0 - j = len(self.v)-1 - for i in xrange(len(self.v)): - if(i>0): j=i-1 - cv = self.v[i] - nv = self.v[j] - if ((((cv.y<=tp.y) and (tp.y<nv.y)) or ((nv.y<=tp.y) and (tp.y<cv.y))) and (tp.x < (nv.x - cv.x) * (tp.y - cv.y) / (nv.y - cv.y) + cv.x)): - c = not(c) - return (c == 1) - -class SVGExporter: - def __init__(self, net, filename): - self.net = net - print self.net.des.name - self.object = self.net.object - print "Exporting ", self.object - self.filename = filename - self.file = None - self.e = None - self.width = 1024 - self.height = 768 - def start(self): - print "Exporting SVG to ", self.filename - self.file = open(self.filename, 'w') - self.e = xml.sax.saxutils.XMLGenerator(self.file, "UTF-8") - atts = {} - atts["width"] = "100%" - atts["height"] = "100%" - atts["viewBox"] = str(self.vxmin)+" "+str(self.vymin)+" "+str(self.vxmax-self.vxmin)+" "+str(self.vymax-self.vymin) - atts["xmlns:nets"] = "http://celeriac.net/unfolder/rdf#" - atts["xmlns:xlink"] = "http://www.w3.org/1999/xlink" - atts["xmlns"] ="http://www.w3.org/2000/svg" - a = xml.sax.xmlreader.AttributesImpl(atts) - self.e.startDocument() - self.e.startElement("svg", a) - self.e.startElement("defs", xml.sax.xmlreader.AttributesImpl({})) - atts = {} - atts["type"]="text/css" - self.e.startElement("style", atts) - # can't find a proper way to do this - self.file.write("<![CDATA[") - self.file.write("polygon.poly{fill:white;stroke:black;stroke-width: 0.001}") - self.file.write("g#foldLines line.valley{stroke:white;stroke-width:0.01;stroke-dasharray:0.02,0.01,0.02,0.05}") - self.file.write("g#foldLines line.mountain{stroke:white;stroke-width:0.01;stroke-dasharray:0.02,0.04}") - self.file.write("]]>") - self.e.endElement("style") - self.e.endElement("defs") - #self.addClipPath() - self.addMeta() - def addMeta(self): - self.e.startElement("metadata", xml.sax.xmlreader.AttributesImpl({})) - self.e.startElement("nets:net", xml.sax.xmlreader.AttributesImpl({})) - for i in xrange(1, len(self.net.folds)): - fold = self.net.folds[i] - # AttributesNSImpl - documentation is rubbish. using this hack. - atts = {} - atts["nets:id"] = "fold"+str(fold.getID()) - if(fold.parent!=None): - atts["nets:parent"] = "fold"+str(fold.parent.getID()) - else: - atts["nets:parent"] = "null" - atts["nets:da"] = str(fold.dihedralAngle()) - if(fold.parent!=None): - atts["nets:ofPoly"] = "poly"+str(fold.parent.foldingPoly.getID()) - else: - atts["nets:ofPoly"] = "" - atts["nets:toPoly"] = "poly"+str(fold.foldingPoly.getID()) - a = xml.sax.xmlreader.AttributesImpl(atts) - self.e.startElement("nets:fold", a) - self.e.endElement("nets:fold") - self.e.endElement("nets:net") - self.e.endElement("metadata") - def end(self): - self.e.endElement("svg") - self.e.endDocument() - print "grown." - def export(self): - self.net.unfoldTo(1) - bb = self.object.getBoundBox() - print bb - self.vxmin = bb[0][0] - self.vymin = bb[0][1] - self.vxmax = bb[7][0] - self.vymax = bb[7][1] - self.start() - atts = {} - atts["id"] = self.object.getName() - a = xml.sax.xmlreader.AttributesImpl(atts) - self.e.startElement("g", a) - #self.addUVImage() - self.addPolys() - self.addFoldLines() - #self.addCutLines() - self.e.endElement("g") - self.end() - def addClipPath(self): - atts = {} - atts["id"] = "netClip" - atts["clipPathUnits"] = "userSpaceOnUse" - atts["x"] = str(self.vxmin) - atts["y"] = str(self.vymin) - atts["width"] = "100%" - atts["height"] = "100%" - self.e.startElement("clipPath", atts) - self.addPolys() - self.e.endElement("clipPath") - def addUVImage(self): - image = Blender.Image.GetCurrent() #hmm - how to determine the desired image ? - if image==None: - return - ifn = image.getFilename() - ifn = self.filename.replace(".svg", ".jpg") - image.setFilename(ifn) - ifn = ifn[ifn.rfind("/")+1:] - image.save() - atts = {} - atts["clip-path"] = "url(#netClip)" - atts["xlink:href"] = ifn - self.e.startElement("image", atts) - self.e.endElement("image") - def addPolys(self): - atts = {} - atts["id"] = "polys" - a = xml.sax.xmlreader.AttributesImpl(atts) - self.e.startElement("g", a) - for i in xrange(len(self.net.folds)): - self.addPoly(self.net.folds[i]) - self.e.endElement("g") - def addFoldLines(self): - atts = {} - atts["id"] = "foldLines" - a = xml.sax.xmlreader.AttributesImpl(atts) - self.e.startElement("g", a) - for i in xrange( 1, len(self.net.folds)): - self.addFoldLine(self.net.folds[i]) - self.e.endElement("g") - def addFoldLine(self, fold): - edge = fold.edge.mapTo(fold.parent.foldingPoly) - if fold.dihedralAngle()>0: - foldType="valley" - else: - foldType="mountain" - atts={} - atts["x1"] = str(edge.v1.x) - atts["y1"] = str(edge.v1.y) - atts["x2"] = str(edge.v2.x) - atts["y2"] = str(edge.v2.y) - atts["id"] = "fold"+str(fold.getID()) - atts["class"] = foldType - a = xml.sax.xmlreader.AttributesImpl(atts) - self.e.startElement("line", a) - self.e.endElement("line") - def addCutLines(self): - atts = {} - atts["id"] = "cutLines" - a = xml.sax.xmlreader.AttributesImpl(atts) - self.e.startElement("g", a) - for i in xrange( 1, len(self.net.cuts)): - self.addCutLine(self.net.cuts[i]) - self.e.endElement("g") - def addCutLine(self, cut): - edge = cut.edge.mapTo(cut.parent.foldingPoly) - if cut.dihedralAngle()>0: - foldType="valley" - else: - foldType="mountain" - atts={} - atts["x1"] = str(edge.v1.x) - atts["y1"] = str(edge.v1.y) - atts["x2"] = str(edge.v2.x) - atts["y2"] = str(edge.v2.y) - atts["id"] = "cut"+str(cut.getID()) - atts["class"] = foldType - a = xml.sax.xmlreader.AttributesImpl(atts) - self.e.startElement("line", a) - self.e.endElement("line") - def addPoly(self, fold): - face = fold.foldingPoly - atts = {} - if fold.desFace.col: - col = fold.desFace.col[0] - rgb = "rgb("+str(col.r)+","+str(col.g)+","+str(col.b)+")" - atts["fill"] = rgb - atts["class"] = "poly" - atts["id"] = "poly"+str(face.getID()) - points = "" - first = True - for vv in face.v: - if(not(first)): - points+=',' - first = False - points+=str(vv[0]) - points+=' ' - points+=str(vv[1]) - atts["points"] = points - a = xml.sax.xmlreader.AttributesImpl(atts) - self.e.startElement("polygon", a) - self.e.endElement("polygon") - def fileSelected(filename): - try: - net = Registry.GetKey('unfolder')['net'] - exporter = SVGExporter(net, filename) - exporter.export() - except: - print "Problem exporting SVG" - traceback.print_exc(file=sys.stdout) - fileSelected = staticmethod(fileSelected) - -# for importing nets saved by the above exporter -class NetHandler(xml.sax.handler.ContentHandler): - def __init__(self, net): - self.net = net - self.first = (41==41) - self.currentElement = None - self.chars = None - self.currentAction = None - self.foldsPending = {} - self.polys = {} - self.actions = {} - self.actions["nets:fold"] = self.foldInfo - self.actions["line"] = self.cutOrFold - self.actions["polygon"] = self.createPoly - def setDocumentLocator(self, locator): - pass - def startDocument(self): - pass - def endDocument(self): - for fold in self.foldsPending.values(): - face = self.net.addFace(fold.unfoldedFace()) - fold.desFace = face - self.net.folds.append(fold) - self.net.addFace(self.first) - self.foldsPending = None - self.polys = None - def startPrefixMapping(self, prefix, uri): - pass - def endPrefixMapping(self, prefix): - pass - def startElement(self, name, attributes): - self.currentAction = None - try: - self.currentAction = self.actions[name] - except: - pass - if(self.currentAction!=None): - self.currentAction(attributes) - def endElement(self, name): - pass - def startElementNS(self, name, qname, attrs): - self.currentAction = self.actions[name] - if(self.currentAction!=None): - self.currentAction(attributes) - def endElementNS(self, name, qname): - pass - def characters(self, content): - pass - def ignorableWhitespace(self): - pass - def processingInstruction(self, target, data): - pass - def skippedEntity(self, name): - pass - def foldInfo(self, atts): - self.foldsPending[atts["nets:id"]] = atts - def createPoly(self, atts): - xy = re.split('[, ]' , atts["points"]) - vectors = [] - for i in xrange(0, len(xy)-1, 2): - v = Vector([float(xy[i]), float(xy[i+1]), 0.0]) - vectors.append(v) - poly = Poly.fromVectors(vectors) - if(self.first==True): - self.first = poly - self.polys[atts["id"]] = poly - def cutOrFold(self, atts): - fid = atts["id"] - try: - fi = self.foldsPending[fid] - except: - pass - p1 = Vector([float(atts["x1"]), float(atts["y1"]), 0.0]) - p2 = Vector([float(atts["x2"]), float(atts["y2"]), 0.0]) - edge = Edge(p1, p2) - parent = None - ofPoly = None - toPoly = None - try: - parent = self.foldsPending[fi["nets:parent"]] - except: - pass - try: - ofPoly = self.polys[fi["nets:ofPoly"]] - except: - pass - try: - toPoly = self.polys[fi["nets:toPoly"]] - except: - pass - fold = Fold(parent, ofPoly , toPoly, edge, float(fi["nets:da"])) - self.foldsPending[fid] = fold - def fileSelected(filename): - try: - net = Net.importNet(filename) - try: - Registry.GetKey('unfolder')['net'] = net - except: - Registry.SetKey('unfolder', {}) - Registry.GetKey('unfolder')['net'] = net - Registry.GetKey('unfolder')['lastpath'] = filename - except: - print "Problem importing SVG" - traceback.print_exc(file=sys.stdout) - fileSelected = staticmethod(fileSelected) - - -class GUI: - def __init__(self): - self.overlaps = Draw.Create(0) - self.ani = Draw.Create(0) - self.selectedFaces =0 - self.search = Draw.Create(0) - self.diffuse = True - self.ancestors = Draw.Create(0) - self.noise = Draw.Create(0.0) - self.shape = Draw.Create(0) - self.nOverlaps = 1==2 - self.iterators = [RandomEdgeIterator,Brightest,Curvature,EdgeIterator,OddEven,Largest] - self.iterator = RandomEdgeIterator - self.overlapsText = "*" - self.message = " " - def makePopupGUI(self): - useRandom = Draw.Create(0) - pub = [] - pub.append(("Search", self.search, "Search for non-overlapping net (maybe forever)")) - pub.append(("Random", useRandom, "Random style net")) - ok = True - while ok: - ok = Blender.Draw.PupBlock("Unfold", pub) - if ok: - if useRandom.val: - self.iterator = RandomEdgeIterator - else: - self.iterator = Curvature - self.unfold() - def makeStandardGUI(self): - Draw.Register(self.draw, self.keyOrMouseEvent, self.buttonEvent) - def installScriptLink(self): - print "Adding script link for animation" - s = Blender.Scene.GetCurrent().getScriptLinks("FrameChanged") - if(s!=None and s.count("frameChanged.py")>0): - return - try: - script = Blender.Text.Get("frameChanged.py") - except: - script = Blender.Text.New("frameChanged.py") - script.write("import Blender\n") - script.write("import mesh_unfolder as Unfolder\n") - script.write("u = Blender.Registry.GetKey('unfolder')\n") - script.write("if u!=None:\n") - script.write("\tn = u['net']\n") - script.write("\tif(n!=None and n.animates):\n") - script.write("\t\tn.unfoldToCurrentFrame()\n") - Blender.Scene.GetCurrent().addScriptLink("frameChanged.py", "FrameChanged") - def unfold(self): - anc = self.ancestors.val - n = 0.0 - s = True - self.nOverlaps = 0 - searchLimit = 10 - search = 1 - Draw.Redraw(1) - net = None - name = None - try: - self.say("Unfolding...") - Draw.Redraw(1) - while(s):# and search < searchLimit): - if(net!=None): - name = net.des.name - net = Net.fromSelected(self, name) - net.setAvoidsOverlaps(not(self.overlaps.val)) - print - print "Unfolding selected object" - net.edgeIteratorClass = self.iterator - print "Using ", net.edgeIteratorClass - net.animates = self.ani.val - self.diffuse = (self.ancestors.val==0) - net.diffuse = self.diffuse - net.generations = self.ancestors.val - net.noise = self.noise.val - print "even:", net.diffuse, " depth:", net.generations - net.unfold() - n = net.report() - t = "." - if(n<1.0): - t = "Overlaps>="+str(n) - else: - t = "A complete net." - self.nOverlaps = (n>=1) - if(self.nOverlaps): - self.say(self.message+" - unfolding failed - try again ") - elif(not(self.overlaps.val)): - self.say("Success. Complete net - no overlaps ") - else: - self.say("Unfolding complete") - self.ancestors.val = anc - s = (self.search.val and n>=1.0) - dict = Registry.GetKey('unfolder') - if(not(dict)): - dict = {} - dict['net'] = net - Registry.SetKey('unfolder', dict) - if(s): - net = net.clone() - search += 1 - except(IndexError): - self.say("Please select an object to unfold") - except: - self.say("Problem unfolding selected object - see console for details") - print "Problem unfolding selected object:" - print sys.exc_info()[1] - traceback.print_exc(file=sys.stdout) - if(self.ani): - if Registry.GetKey('unfolder')==None: - print "no net!" - return - Registry.GetKey('unfolder')['net'].sortOutIPOSource() - self.installScriptLink() - Draw.Redraw(1) - def keyOrMouseEvent(self, evt, val): - if (evt == Draw.ESCKEY and not val): - Draw.Exit() - def buttonEvent(self, evt): - if (evt == 1): - self.unfold() - if (evt == 5): - try: - Registry.GetKey('unfolder')['net'].setAvoidsOverlaps(self.overlaps.val) - except: - pass - if (evt == 2): - print "Trying to set IPO curve" - try: - s = Blender.Object.GetSelected() - if(s!=None): - Registry.GetKey('unfolder')['net'].setIPOSource( s[0] ) - print "Set IPO curve" - else: - print "Please select an object to use the IPO of" - except: - print "Problem setting IPO source" - Draw.Redraw(1) - if (evt == 6): - Draw.Exit() - if (evt == 7): - try: - if (Registry.GetKey('unfolder')['net']!=None): - Registry.GetKey('unfolder')['net'].animates = self.ani.val - if(self.ani): - Registry.GetKey('unfolder')['net'].sortOutIPOSource() - self.installScriptLink() - except: - print sys.exc_info()[1] - traceback.print_exc(file=sys.stdout) - Draw.Redraw(1) - if (evt == 19): - pass - if (evt == 87): - try: - if (Registry.GetKey('unfolder')['net']!=None): - Registry.GetKey('unfolder')['net'].assignUVs() - self.say("Assigned UVs") - except: - print sys.exc_info()[1] - traceback.print_exc(file=sys.stdout) - Draw.Redraw(1) - if(evt==91): - if( testOverlap() == True): - self.nOverlaps = 1 - else: - self.nOverlaps = 0 - Draw.Redraw(1) - if(evt==233): - f1 = Poly.fromBlenderFace(Blender.Object.GetSelected()[0].getData().faces[0]) - f2 = Poly.fromBlenderFace(Blender.Object.GetSelected()[1].getData().faces[0]) - print - print Blender.Object.GetSelected()[0].getName() - print Blender.Object.GetSelected()[1].getName() - print f1.intersects2D(f2) - print f2.intersects2D(f1) - if(evt==714): - Net.unfoldAll(self) - Draw.Redraw(1) - if(evt==713): - self.iterator = self.iterators[self.shape.val] - Draw.Redraw(1) - if(evt==92): - if( testContains() == True): - self.nOverlaps = 1 - else: - self.nOverlaps = 0 - Draw.Redraw(1) - if(evt==104): - try: - filename = "net.svg" - s = Blender.Object.GetSelected() - if(s!=None and len(s)>0): - filename = s[0].getName()+".svg" - else: - if (Registry.GetKey('unfolder')['net']!=None): - filename = Registry.GetKey('unfolder')['net'].des.name - if(filename==None): - filename="net.svg" - else: - filename=filename+".svg" - Window.FileSelector(SVGExporter.fileSelected, "Select filename", filename) - except: - print "Problem exporting SVG" - traceback.print_exc(file=sys.stdout) - if(evt==107): - try: - Window.FileSelector(NetHandler.fileSelected, "Select file") - except: - print "Problem importing SVG" - traceback.print_exc(file=sys.stdout) - def say(self, m): - self.message = m - Draw.Redraw(1) - Window.Redraw(Window.Types.SCRIPT) - def draw(self): - cw = 64 - ch = 16 - l = FlowLayout(32, cw, ch, 350, 64) - l.y = 70 - self.search = Draw.Toggle("search", 19, l.nx(), l.ny(), l.cw, l.ch, self.search.val, "Search for non-overlapping mesh (potentially indefinitely)") - self.overlaps = Draw.Toggle("overlaps", 5, l.nx(), l.ny(), l.cw, l.ch, self.overlaps.val, "Allow overlaps / avoid overlaps - if off, will not place overlapping faces") - self.ani = Draw.Toggle("ani", 7, l.nx(), l.ny(), l.cw, l.ch, self.ani.val, "Animate net") - Draw.Button("uv", 87, l.nx(), l.ny(), l.cw, l.ch, "Assign net as UV to source mesh (overwriting existing UV)") - Draw.Button("Unfold", 1, l.nx(), l.ny(), l.cw, l.ch, "Unfold selected mesh to net") - Draw.Button("save", 104, l.nx(), l.ny(), l.cw, l.ch, "Save net as SVG") - Draw.Button("load", 107, l.nx(), l.ny(), l.cw, l.ch, "Load net from SVG") - #Draw.Button("test", 233, l.nx(), l.ny(), l.cw, l.ch, "test") - # unfolding enthusiasts - try uncommenting this - self.ancestors = Draw.Number("depth", 654, l.nx(), l.ny(), cw, ch, self.ancestors.val, 0, 9999, "depth of branching 0=diffuse") - #self.noise = Draw.Number("noise", 631, l.nx(), l.ny(), cw, ch, self.noise.val, 0.0, 1.0, "noisyness of branching") - #Draw.Button("UnfoldAll", 714, l.nx(), l.ny(), l.cw, l.ch, "Unfold all meshes and save their nets") - options = "order %t|random %x0|brightest %x1|curvature %x2|winding %x3| 1010 %x4|largest %x5" - self.shape = Draw.Menu(options, 713, l.nx(), l.ny(), cw, ch, self.shape.val, "shape of net") - Draw.Button("exit", 6, l.nx(), l.ny(), l.cw, l.ch, "exit") - BGL.glClearColor(0.3, 0.3, 0.3, 1) - BGL.glColor3f(0.3,0.3,0.3) - l.newLine() - BGL.glRasterPos2i(32, 100) - Draw.Text(self.message) - -class FlowLayout: - def __init__(self, margin, cw, ch, w, h): - self.x = margin-cw-4 - self.y = margin - self.cw = cw - self.ch = ch - self.width = w - self.height = h - self.margin = margin - def nx(self): - self.x+=(self.cw+4) - if(self.x>self.width): - self.x = self.margin - self.y-=self.ch+4 - return self.x - def ny(self): - return self.y - def newLine(self): - self.y-=self.ch+self.margin - self.x = self.margin - -# if xml is None, then dont bother running the script -if xml: - try: - sys.setrecursionlimit(10000) - gui = GUI() - gui.makeStandardGUI() - #gui.makePopupGUI() - except: - traceback.print_exc(file=sys.stdout) diff --git a/release/scripts/mesh_wire.py b/release/scripts/mesh_wire.py deleted file mode 100644 index bd38c47a9b9..00000000000 --- a/release/scripts/mesh_wire.py +++ /dev/null @@ -1,290 +0,0 @@ -#!BPY -""" -Name: 'Solid Wireframe' -Blender: 243 -Group: 'Mesh' -Tooltip: 'Make a solid wireframe copy of this mesh' -""" - -# -------------------------------------------------------------------------- -# Solid Wireframe1.0 by Campbell Barton (AKA Ideasman42) -# -------------------------------------------------------------------------- -# ***** 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 ***** -# -------------------------------------------------------------------------- -import Blender -from Blender import Scene, Mesh, Window, sys -from Blender.Mathutils import AngleBetweenVecs, TriangleNormal -from BPyMesh import faceAngles # get angles for face cornders -#import BPyMesh -#reload(BPyMesh) -#faceAngles = BPyMesh.faceAngles - -# works out the distanbce to inset the corners based on angles -from BPyMathutils import angleToLength -#import BPyMathutils -#reload(BPyMathutils) -#angleToLength = BPyMathutils.angleToLength - -import mesh_solidify - -import BPyMessages -reload(BPyMessages) -import bpy - - -def solid_wire(ob_orig, me_orig, sce, PREF_THICKNESS, PREF_SOLID, PREF_SHARP, PREF_XSHARP): - if not PREF_SHARP and PREF_XSHARP: - PREF_XSHARP = False - - # This function runs out of editmode with a mesh - # error cases are alredy checked for - - inset_half = PREF_THICKNESS / 2 - del PREF_THICKNESS - - ob = ob_orig.copy() - me = me_orig.copy() - ob.link(me) - sce.objects.selected = [] - sce.objects.link(ob) - ob.sel = True - sce.objects.active = ob - - # Modify the object, should be a set - FGON= Mesh.EdgeFlags.FGON - edges_fgon = dict([(ed.key,None) for ed in me.edges if ed.flag & FGON]) - # edges_fgon.fromkeys([ed.key for ed in me.edges if ed.flag & FGON]) - - del FGON - - - - # each face needs its own verts - # orig_vert_count =len(me.verts) - new_vert_count = len(me.faces) * 4 - for f in me.faces: - if len(f) == 3: - new_vert_count -= 1 - - if PREF_SHARP == 0: - new_faces_edge= {} - - def add_edge(i1,i2, ni1, ni2): - - if i1>i2: - i1,i2 = i2,i1 - flip = True - else: - flip = False - new_faces_edge.setdefault((i1,i2), []).append((ni1, ni2, flip)) - - - new_verts = [] - new_faces = [] - vert_index = len(me.verts) - - for f in me.faces: - f_v_co = [v.co for v in f] - angles = faceAngles(f_v_co) - f_v_idx = [v.index for v in f] - - def new_vert(fi): - co = f_v_co[fi] - a = angles[fi] - if a > 180: - vert_inset = 1 * inset_half - else: - vert_inset = inset_half * angleToLength( abs((180-a) / 2) ) - - # Calculate the inset direction - co1 = f_v_co[fi-1] - co2 = fi+1 # Wrap this index back to the start - if co2 == len(f_v_co): co2 = 0 - co2 = f_v_co[co2] - - co1 = co1 - co - co2 = co2 - co - co1.normalize() - co2.normalize() - d = co1+co2 - # Done with inset direction - - d.length = vert_inset - return co+d - - new_verts.extend([new_vert(i) for i in xrange(len(f_v_co))]) - - if len(f_v_idx) == 4: - faces = [\ - (f_v_idx[1], f_v_idx[0], vert_index, vert_index+1),\ - (f_v_idx[2], f_v_idx[1], vert_index+1, vert_index+2),\ - (f_v_idx[3], f_v_idx[2], vert_index+2, vert_index+3),\ - (f_v_idx[0], f_v_idx[3], vert_index+3, vert_index),\ - ] - else: - faces = [\ - (f_v_idx[1], f_v_idx[0], vert_index, vert_index+1),\ - (f_v_idx[2], f_v_idx[1], vert_index+1, vert_index+2),\ - (f_v_idx[0], f_v_idx[2], vert_index+2, vert_index),\ - ] - - - if PREF_SHARP == 1: - if not edges_fgon: - new_faces.extend(faces) - else: - for nf in faces: - i1,i2 = nf[0], nf[1] - if i1>i2: i1,i2 = i2,i1 - - if edges_fgon and (i1,i2) not in edges_fgon: - new_faces.append(nf) - - - - elif PREF_SHARP == 0: - for nf in faces: - add_edge(*nf) - - vert_index += len(f_v_co) - - me.verts.extend(new_verts) - - if PREF_SHARP == 0: - def add_tri_flipped(i1,i2,i3): - try: - if AngleBetweenVecs(me.verts[i1].no, TriangleNormal(me.verts[i1].co, me.verts[i2].co, me.verts[i3].co)) < 90: - return i3,i2,i1 - else: - return i1,i2,i3 - except: - return i1,i2,i3 - - # This stores new verts that use this vert - # used for re-averaging this verts location - # based on surrounding verts. looks better but not needed. - vert_users = [set() for i in xrange(vert_index)] - - for (i1,i2), nf in new_faces_edge.iteritems(): - - if len(nf) == 2: - # Add the main face - if edges_fgon and (i1,i2) not in edges_fgon: - new_faces.append((nf[0][0], nf[0][1], nf[1][0], nf[1][1])) - - - if nf[0][2]: key1 = nf[0][1],nf[0][0] - else: key1 = nf[0][0],nf[0][1] - if nf[1][2]: key2 = nf[1][1],nf[1][0] - else: key2 = nf[1][0],nf[1][1] - - # CRAP, cont work out which way to flip so make it oppisite the verts normal. - - ###new_faces.append((i2, key1[0], key2[0])) # NO FLIPPING, WORKS THOUGH - ###new_faces.append((i1, key1[1], key2[1])) - new_faces.append(add_tri_flipped(i2, key1[0], key2[0])) - new_faces.append(add_tri_flipped(i1, key1[1], key2[1])) - - # Average vert loction so its not tooo pointy - # not realy needed but looks better - vert_users[i2].update((key1[0], key2[0])) - vert_users[i1].update((key1[1], key2[1])) - - if len(nf) == 1: - if nf[0][2]: new_faces.append((nf[0][0], nf[0][1], i2, i1)) # flipped - else: new_faces.append((i1,i2, nf[0][0], nf[0][1])) - - - # average points now. - for i, vusers in enumerate(vert_users): - if vusers: - co = me.verts[i].co - co.zero() - - for ii in vusers: - co += me.verts[ii].co - co /= len(vusers) - - me.faces.delete(1, range(len(me.faces))) - - me.faces.extend(new_faces) - - # External function, solidify - me.sel = True - if PREF_SOLID: - mesh_solidify.solidify(me, -inset_half*2, True, False, PREF_XSHARP) - - -def main(): - - # Gets the current scene, there can be many scenes in 1 blend file. - sce = bpy.data.scenes.active - - # Get the active object, there can only ever be 1 - # and the active object is always the editmode object. - ob_act = sce.objects.active - - if not ob_act or ob_act.type != 'Mesh': - BPyMessages.Error_NoMeshActive() - return - - # Saves the editmode state and go's out of - # editmode if its enabled, we cant make - # changes to the mesh data while in editmode. - is_editmode = Window.EditMode() - Window.EditMode(0) - - me = ob_act.getData(mesh=1) # old NMesh api is default - if len(me.faces)==0: - BPyMessages.Error_NoMeshFaces() - if is_editmode: Window.EditMode(1) - return - - # Create the variables. - PREF_THICK = Blender.Draw.Create(0.005) - PREF_SOLID = Blender.Draw.Create(1) - PREF_SHARP = Blender.Draw.Create(1) - PREF_XSHARP = Blender.Draw.Create(0) - - pup_block = [\ - ('Thick:', PREF_THICK, 0.0001, 2.0, 'Skin thickness in mesh space.'),\ - ('Solid Wire', PREF_SOLID, 'If Disabled, will use 6 sided wire segments'),\ - ('Sharp Wire', PREF_SHARP, 'Use the original mesh topology for more accurate sharp wire.'),\ - ('Extra Sharp', PREF_XSHARP, 'Use less geometry to create a sharper looking wire'),\ - ] - - if not Blender.Draw.PupBlock('Solid Wireframe', pup_block): - if is_editmode: Window.EditMode(1) - return - - Window.WaitCursor(1) - t = sys.time() - - # Run the mesh editing function - solid_wire(ob_act, me, sce, PREF_THICK.val, PREF_SOLID.val, PREF_SHARP.val, PREF_XSHARP.val) - - # Timing the script is a good way to be aware on any speed hits when scripting - print 'Solid Wireframe finished in %.2f seconds' % (sys.time()-t) - Window.WaitCursor(0) - if is_editmode: Window.EditMode(1) - - -# This lets you can import the script without running it -if __name__ == '__main__': - main() diff --git a/release/scripts/ms3d_import.py b/release/scripts/ms3d_import.py deleted file mode 100644 index c1438cbfc97..00000000000 --- a/release/scripts/ms3d_import.py +++ /dev/null @@ -1,487 +0,0 @@ -#!BPY -""" -Name: 'MilkShape3D (.ms3d)...' -Blender: 245 -Group: 'Import' -Tooltip: 'Import from MilkShape3D file format (.ms3d)' -""" -# -# Author: Markus Ilmola -# Email: markus.ilmola@pp.inet.fi -# -# 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. -# - -# import needed stuff -import os.path -import math -from math import * -import struct -import Blender -from Blender import Mathutils -from Blender.Mathutils import * - - -# trims a string by removing ending 0 and everything after it -def uku(s): - try: - return s[:s.index('\0')] - except: - return s - - -# Converts ms3d euler angles to a rotation matrix -def RM(a): - sy = sin(a[2]) - cy = cos(a[2]) - sp = sin(a[1]) - cp = cos(a[1]) - sr = sin(a[0]) - cr = cos(a[0]) - return Matrix([cp*cy, cp*sy, -sp], [sr*sp*cy+cr*-sy, sr*sp*sy+cr*cy, sr*cp],[cr*sp*cy+-sr*-sy, cr*sp*sy+-sr*cy, cr*cp]) - - -# Converts ms3d euler angles to a quaternion -def RQ(a): - angle = a[2] * 0.5; - sy = sin(angle); - cy = cos(angle); - angle = a[1] * 0.5; - sp = sin(angle); - cp = cos(angle); - angle = a[0] * 0.5; - sr = sin(angle); - cr = cos(angle); - return Quaternion(cr*cp*cy+sr*sp*sy, sr*cp*cy-cr*sp*sy, cr*sp*cy+sr*cp*sy, cr*cp*sy-sr*sp*cy) - - -# takes a texture filename and tries to load it -def loadImage(path, filename): - image = None - try: - image = Blender.Image.Load(os.path.abspath(filename)) - except IOError: - print "Warning: Failed to load image: " + filename + ". Trying short path instead...\n" - try: - image = Blender.Image.Load(os.path.dirname(path) + "/" + os.path.basename(filename)) - except IOError: - print "Warning: Failed to load image: " + os.path.basename(filename) + "!\n" - return image - - -# imports a ms3d file to the current scene -def import_ms3d(path): - # get scene - scn = Blender.Scene.GetCurrent() - if scn == None: - return "No scene to import to!" - - # open the file - try: - file = open(path, 'rb') - except IOError: - return "Failed to open the file!" - - # get the file size - file.seek(0, os.SEEK_END); - fileSize = file.tell(); - file.seek(0, os.SEEK_SET); - - # read id to check if the file is a MilkShape3D file - id = file.read(10) - if id!="MS3D000000": - return "The file is not a MS3D file!" - - # read version - version = struct.unpack("i", file.read(4))[0] - if version!=4: - return "The file has invalid version!" - - # Create the mesh - scn.objects.selected = [] - mesh = Blender.Mesh.New("MilkShape3D Mesh") - meshOb = scn.objects.new(mesh) - - # read the number of vertices - numVertices = struct.unpack("H", file.read(2))[0] - - # read vertices - coords = [] - boneIds = [] - for i in xrange(numVertices): - # skip flags - file.read(1) - - # read coords - coords.append(struct.unpack("fff", file.read(3*4))) - - # read bone ids - boneIds.append(struct.unpack("b", file.read(1))[0]) - - # skip refcount - file.read(1) - - # add the vertices to the mesh - mesh.verts.extend(coords) - - # read number of triangles - numTriangles = struct.unpack("H", file.read(2))[0] - - # read triangles - faces = [] - uvs = [] - for i in xrange(numTriangles): - # skip flags - file.read(2) - - # read indices (faces) - faces.append(struct.unpack("HHH", file.read(3*2))) - - # read normals - normals = struct.unpack("fffffffff", file.read(3*3*4)) - - # read texture coordinates - s = struct.unpack("fff", file.read(3*4)) - t = struct.unpack("fff", file.read(3*4)) - - # store texture coordinates - uvs.append([[s[0], 1-t[0]], [s[1], 1-t[1]], [s[2], 1-t[2]]]) - - if faces[-1][2] == 0: # Cant have zero at the third index - faces[-1] = faces[-1][1], faces[-1][2], faces[-1][0] - uvs[-1] = uvs[-1][1], uvs[-1][2], uvs[-1][0] - - # skip smooth group - file.read(1) - - # skip group - file.read(1) - - # add the faces to the mesh - mesh.faces.extend(faces) - - # set texture coordinates - for i in xrange(numTriangles): - mesh.faces[i].uv = [Vector(uvs[i][0]), Vector(uvs[i][1]), Vector(uvs[i][2])] - - # read number of groups - numGroups = struct.unpack("H", file.read(2))[0] - - # read groups - for i in xrange(numGroups): - # skip flags - file.read(1) - - # skip name - file.read(32) - - # read the number of triangles in the group - numGroupTriangles = struct.unpack("H", file.read(2))[0] - - # read the group triangles - if numGroupTriangles > 0: - triangleIndices = struct.unpack(str(numGroupTriangles) + "H", file.read(2*numGroupTriangles)); - - # read material - material = struct.unpack("b", file.read(1))[0] - if material>=0: - for j in xrange(numGroupTriangles): - mesh.faces[triangleIndices[j]].mat = material - - # read the number of materials - numMaterials = struct.unpack("H", file.read(2))[0] - - # read materials - for i in xrange(numMaterials): - # read name - name = uku(file.read(32)) - - # create the material - mat = Blender.Material.New(name) - mesh.materials += [mat] - - # read ambient color - ambient = struct.unpack("ffff", file.read(4*4))[0:3] - mat.setAmb((ambient[0]+ambient[1]+ambient[2])/3) - - # read diffuse color - diffuse = struct.unpack("ffff", file.read(4*4))[0:3] - mat.setRGBCol(diffuse) - - # read specular color - specular = struct.unpack("ffff", file.read(4*4))[0:3] - mat.setSpecCol(specular) - - # read emissive color - emissive = struct.unpack("ffff", file.read(4*4))[0:3] - mat.setEmit((emissive[0]+emissive[1]+emissive[2])/3) - - # read shininess - shininess = struct.unpack("f", file.read(4))[0] - - # read transparency - transparency = struct.unpack("f", file.read(4))[0] - mat.setAlpha(transparency) - if transparency < 1: - mat.mode |= Blender.Material.Modes.ZTRANSP - - # read mode - mode = struct.unpack("B", file.read(1))[0] - - # read texturemap - texturemap = uku(file.read(128)) - if len(texturemap)>0: - colorTexture = Blender.Texture.New(name + "_texture") - colorTexture.setType('Image') - colorTexture.setImage(loadImage(path, texturemap)) - mat.setTexture(0, colorTexture, Blender.Texture.TexCo.UV, Blender.Texture.MapTo.COL) - - # read alphamap - alphamap = uku(file.read(128)) - if len(alphamap)>0: - alphaTexture = Blender.Texture.New(name + "_alpha") - alphaTexture.setType('Image') - alphaTexture.setImage(loadImage(path, alphamap)) - mat.setTexture(1, alphaTexture, Blender.Texture.TexCo.UV, Blender.Texture.MapTo.ALPHA) - - # read animation - fps = struct.unpack("f", file.read(4))[0] - time = struct.unpack("f", file.read(4))[0] - frames = struct.unpack("i", file.read(4))[0] - - # read the number of joints - numJoints = struct.unpack("H", file.read(2))[0] - - # create the armature - armature = 0 - armOb = 0 - if numJoints > 0: - armOb = Blender.Object.New('Armature', "MilkShape3D Skeleton") - armature = Blender.Armature.New("MilkShape3D Skeleton") - armature.drawType = Blender.Armature.STICK - armOb.link(armature) - scn.objects.link(armOb) - armOb.makeParentDeform([meshOb]) - armature.makeEditable() - - # read joints - joints = [] - rotKeys = {} - posKeys = {} - for i in xrange(numJoints): - # skip flags - file.read(1) - - # read name - name = uku(file.read(32)) - joints.append(name) - - # create the bone - bone = Blender.Armature.Editbone() - armature.bones[name] = bone - - # read parent - parent = uku(file.read(32)) - if len(parent)>0: - bone.parent = armature.bones[parent] - - # read orientation - rot = struct.unpack("fff", file.read(3*4)) - - # read position - pos = struct.unpack("fff", file.read(3*4)) - - # set head - if bone.hasParent(): - bone.head = Vector(pos) * bone.parent.matrix + bone.parent.head - tempM = RM(rot) * bone.parent.matrix - tempM.transpose; - bone.matrix = tempM - else: - bone.head = Vector(pos) - bone.matrix = RM(rot) - - # set tail - bvec = bone.tail - bone.head - bvec.normalize() - bone.tail = bone.head + 0.01 * bvec - - # Create vertex group for this bone - mesh.addVertGroup(name) - vgroup = [] - for index, v in enumerate(boneIds): - if v==i: - vgroup.append(index) - mesh.assignVertsToGroup(name, vgroup, 1.0, 1) - - # read the number of rotation keys - numKeyFramesRot = struct.unpack("H", file.read(2))[0] - - # read the number of postions keys - numKeyFramesPos = struct.unpack("H", file.read(2))[0] - - # read rotation keys - rotKeys[name] = [] - for j in xrange(numKeyFramesRot): - # read time - time = fps * struct.unpack("f", file.read(4))[0] - # read data - rotKeys[name].append([time, struct.unpack("fff", file.read(3*4))]) - - # read position keys - posKeys[name] = [] - for j in xrange(numKeyFramesPos): - # read time - time = fps * struct.unpack("f", file.read(4))[0] - # read data - posKeys[name].append([time, struct.unpack("fff", file.read(3*4))]) - - # create action and pose - action = 0 - pose = 0 - if armature!=0: - armature.update() - pose = armOb.getPose() - action = armOb.getAction() - if not action: - action = Blender.Armature.NLA.NewAction() - action.setActive(armOb) - - # create animation key frames - for name, pbone in pose.bones.items(): - # create position keys - for key in posKeys[name]: - pbone.loc = Vector(key[1]) - pbone.insertKey(armOb, int(key[0]+0.5), Blender.Object.Pose.LOC, True) - - # create rotation keys - for key in rotKeys[name]: - pbone.quat = RQ(key[1]) - pbone.insertKey(armOb, int(key[0]+0.5), Blender.Object.Pose.ROT, True) - - # The old format ends here. If there is more data then the file is newer version - - # check to see if there are any comments - if file.tell()<fileSize: - - # read sub version - subVersion = struct.unpack("i", file.read(4))[0] - - # Is the sub version a supported one - if subVersion==1: - - # Group comments - numComments = struct.unpack("i", file.read(4))[0] - for i in range(numComments): - file.read(4) # index - size = struct.unpack("i", file.read(4))[0] # comment size - if size>0: - print "Group comment: " + file.read(size) - - # Material comments - numComments = struct.unpack("i", file.read(4))[0] - for i in range(numComments): - file.read(4) # index - size = struct.unpack("i", file.read(4))[0] # comment size - if size>0: - print "Material comment: " + file.read(size) - - # Joint comments - numComments = struct.unpack("i", file.read(4))[0] - for i in range(numComments): - file.read(4) # index - size = struct.unpack("i", file.read(4))[0] # comment size - if size>0: - print "Joint comment: " + file.read(size) - - # Model comments - numComments = struct.unpack("i", file.read(4))[0] - for i in range(numComments): - file.read(4) # index - size = struct.unpack("i", file.read(4))[0] # comment size - if size>0: - print "Model comment: " + file.read(size) - - # Unknown version give a warning - else: - print "Warning: Unknown version!" - - - # check to see if there is any extra vertex data - if file.tell()<fileSize: - - # read the subversion - subVersion = struct.unpack("i", file.read(4))[0] - - # is the version supported - if subVersion==2: - # read the extra data for each vertex - for i in xrange(numVertices): - # bone ids - ids = struct.unpack("bbb", file.read(3)) - # weights - weights = struct.unpack("BBB", file.read(3)) - # extra - extra = struct.unpack("I", file.read(4)) - # add extra vertices with weights to deform groups - if ids[0]>=0 or ids[1]>=0 or ids[2]>=0: - mesh.assignVertsToGroup(joints[boneIds[i]], [i], 0.01*weights[0], 1) - if ids[0]>=0: - mesh.assignVertsToGroup(joints[ids[0]], [i], 0.01*weights[1], 1) - if ids[1]>=0: - mesh.assignVertsToGroup(joints[ids[1]], [i], 0.01*weights[2], 1) - if ids[2]>=0: - mesh.assignVertsToGroup(joints[ids[2]], [i], 0.01*(100-(weights[0]+weights[1]+weights[2])), 1) - - elif subVersion==1: - # read extra data for each vertex - for i in xrange(numVertices): - # bone ids - ids = struct.unpack("bbb", file.read(3)) - # weights - weights = struct.unpack("BBB", file.read(3)) - # add extra vertices with weights to deform groups - if ids[0]>=0 or ids[1]>=0 or ids[2]>=0: - mesh.assignVertsToGroup(joints[boneIds[i]], [i], 0.01*weights[0], 1) - if ids[0]>=0: - mesh.assignVertsToGroup(joints[ids[0]], [i], 0.01*weights[1], 1) - if ids[1]>=0: - mesh.assignVertsToGroup(joints[ids[1]], [i], 0.01*weights[2], 1) - if ids[2]>=0: - mesh.assignVertsToGroup(joints[ids[2]], [i], 0.01*(100-(weights[0]+weights[1]+weights[2])), 1) - - # non supported subversion give a warning - else: - print "Warning: Unknown subversion!" - - # rest of the extra data in the file is not imported/used - - # refresh the view - Blender.Redraw() - - # close the file - file.close() - - # succes return empty error string - return "" - - -# load the model -def fileCallback(filename): - error = import_ms3d(filename) - if error!="": - Blender.Draw.PupMenu("An error occured during import: " + error + "|Not all data might have been imported succesfully.", 2) - -Blender.Window.FileSelector(fileCallback, 'Import') diff --git a/release/scripts/ms3d_import_ascii.py b/release/scripts/ms3d_import_ascii.py deleted file mode 100644 index d8c22a1ec99..00000000000 --- a/release/scripts/ms3d_import_ascii.py +++ /dev/null @@ -1,479 +0,0 @@ -#!BPY -""" -Name: 'MilkShape3D ASCII (.txt)...' -Blender: 245 -Group: 'Import' -Tooltip: 'Import from a MilkShape3D ASCII file format (.txt)' -""" -# -# Author: Markus Ilmola -# Email: markus.ilmola@pp.inet.fi -# -# 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. -# - -# import needed stuff -import os.path -import re -import math -from math import * -import Blender -from Blender import Mathutils -from Blender.Mathutils import * - - - -# Converts ms3d euler angles to a rotation matrix -def RM(a): - sy = sin(a[2]) - cy = cos(a[2]) - sp = sin(a[1]) - cp = cos(a[1]) - sr = sin(a[0]) - cr = cos(a[0]) - return Matrix([cp*cy, cp*sy, -sp], [sr*sp*cy+cr*-sy, sr*sp*sy+cr*cy, sr*cp],[cr*sp*cy+-sr*-sy, cr*sp*sy+-sr*cy, cr*cp]) - - -# Converts ms3d euler angles to a quaternion -def RQ(a): - angle = a[2] * 0.5; - sy = sin(angle); - cy = cos(angle); - angle = a[1] * 0.5; - sp = sin(angle); - cp = cos(angle); - angle = a[0] * 0.5; - sr = sin(angle); - cr = cos(angle); - return Quaternion(cr*cp*cy+sr*sp*sy, sr*cp*cy-cr*sp*sy, cr*sp*cy+sr*cp*sy, cr*cp*sy-sr*sp*cy) - - -# takes a texture filename and tries to load it -def loadImage(path, filename): - image = None - try: - image = Blender.Image.Load(os.path.abspath(filename)) - except IOError: - print "Warning: Failed to load image: " + filename + ". Trying short path instead...\n" - try: - image = Blender.Image.Load(os.path.dirname(path) + "/" + os.path.basename(filename)) - except IOError: - print "Warning: Failed to load image: " + os.path.basename(filename) + "!\n" - return image - - - -# returns the next non-empty, non-comment line from the file -def getNextLine(file): - ready = False - while ready==False: - line = file.readline() - if len(line)==0: - print "Warning: End of file reached." - return line - ready = True - line = line.strip() - if len(line)==0 or line.isspace(): - ready = False - if len(line)>=2 and line[0]=='/' and line[1]=='/': - ready = False - return line - - - -# imports a MilkShape3D ascii file to the current scene -def import_ms3d_ascii(path): - # limits - MAX_NUMMESHES = 1000 - MAX_NUMVERTS = 100000 - MAX_NUMNORMALS = 100000 - MAX_NUMTRIS = 100000 - MAX_NUMMATS = 16 - MAX_NUMBONES = 100 - MAX_NUMPOSKEYS = 1000 - MAX_NUMROTKEYS = 1000 - - # get scene - scn = Blender.Scene.GetCurrent() - if scn==None: - return "No scene to import to!" - - # open the file - try: - file = open(path, 'r') - except IOError: - return "Failed to open the file!" - - # Read frame info - try: - lines = getNextLine(file).split() - if len(lines) != 2 or lines[0] != "Frames:": - raise ValueError - lines = getNextLine(file).split() - if len(lines) != 2 or lines[0] != "Frame:": - raise ValueError - except ValueError: - return "Frame information is invalid!" - - # Create the mesh - meshOb = Blender.Object.New('Mesh', "MilkShape3D Object") - mesh = Blender.Mesh.New("MilkShape3D Mesh") - meshOb.link(mesh) - scn.objects.link(meshOb) - - # read the number of meshes - try: - lines = getNextLine(file).split() - if len(lines)!=2 or lines[0]!="Meshes:": - raise ValueError - numMeshes = int(lines[1]) - if numMeshes < 0 or numMeshes > MAX_NUMMESHES: - raise ValueError - except ValueError: - return "Number of meshes is invalid!" - - # read meshes - vertBase = 0 - faceBase = 0 - boneIds = [] - for i in range(numMeshes): - # read name, flags and material - try: - lines = re.findall(r'\".*\"|[^ ]+', getNextLine(file)) - if len(lines)!=3: - raise ValueError - material = int(lines[2]) - except ValueError: - return "Name, flags or material in mesh " + str(i+1) + " are invalid!" - - # read the number of vertices - try: - numVerts = int(getNextLine(file)) - if numVerts < 0 or numVerts > MAX_NUMVERTS: - raise ValueError - except ValueError: - return "Number of vertices in mesh " + str(i+1) + " is invalid!" - - # read vertices - coords = [] - uvs = [] - for j in xrange(numVerts): - try: - lines = getNextLine(file).split() - if len(lines)!=7: - raise ValueError - coords.append([float(lines[1]), float(lines[2]), float(lines[3])]) - uvs.append([float(lines[4]), 1-float(lines[5])]) - boneIds.append(int(lines[6])) - except ValueError: - return "Vertex " + str(j+1) + " in mesh " + str(i+1) + " is invalid!" - mesh.verts.extend(coords) - - # read number of normals - try: - numNormals = int(getNextLine(file)) - if numNormals < 0 or numNormals > MAX_NUMNORMALS: - raise ValueError - except ValueError: - return "Number of normals in mesh " + str(i+1) + " is invalid!" - - # read normals - normals = [] - for j in xrange(numNormals): - try: - lines = getNextLine(file).split() - if len(lines)!=3: - raise ValueError - normals.append([float(lines[0]), float(lines[1]), float(lines[2])]) - except ValueError: - return "Normal " + str(j+1) + " in mesh " + str(i+1) + " is invalid!" - - # read the number of triangles - try: - numTris = int(getNextLine(file)) - if numTris < 0 or numTris > MAX_NUMTRIS: - raise ValueError - except ValueError: - return "Number of triangles in mesh " + str(i+1) + " is invalid!" - - # read triangles - faces = [] - for j in xrange(numTris): - # read the triangle - try: - lines = getNextLine(file).split() - if len(lines)!=8: - raise ValueError - v1 = int(lines[1]) - v2 = int(lines[2]) - v3 = int(lines[3]) - faces.append([v1+vertBase, v2+vertBase, v3+vertBase]) - except ValueError: - return "Triangle " + str(j+1) + " in mesh " + str(i+1) + " is invalid!" - mesh.faces.extend(faces) - - # set texture coordinates and material - for j in xrange(faceBase, len(mesh.faces)): - face = mesh.faces[j] - face.uv = [Vector(uvs[face.verts[0].index-vertBase]), Vector(uvs[face.verts[1].index-vertBase]), Vector(uvs[face.verts[2].index-vertBase])] - if material>=0: - face.mat = material - - # increase vertex and face base - vertBase = len(mesh.verts) - faceBase = len(mesh.faces) - - # read the number of materials - try: - lines = getNextLine(file).split() - if len(lines)!=2 or lines[0]!="Materials:": - raise ValueError - numMats = int(lines[1]) - if numMats < 0 or numMats > MAX_NUMMATS: - raise ValueError - except ValueError: - return "Number of materials is invalid!" - - # read the materials - for i in range(numMats): - # read name - name = getNextLine(file)[1:-1] - - # create the material - mat = Blender.Material.New(name) - mesh.materials += [mat] - - # read ambient color - try: - lines = getNextLine(file).split() - if len(lines)!=4: - raise ValueError - amb = (float(lines[0])+float(lines[1])+float(lines[2]))/3 - mat.setAmb(amb) - except ValueError: - return "Ambient color in material " + str(i+1) + " is invalid!" - - # read diffuse color - try: - lines = getNextLine(file).split() - if len(lines)!=4: - raise ValueError - mat.setRGBCol([float(lines[0]), float(lines[1]), float(lines[2])]) - except ValueError: - return "Diffuse color in material " + str(i+1) + " is invalid!" - - # read specular color - try: - lines = getNextLine(file).split() - if len(lines)!=4: - raise ValueError - mat.setSpecCol([float(lines[0]), float(lines[1]), float(lines[2])]) - except ValueError: - return "Specular color in material " + str(i+1) + " is invalid!" - - # read emissive color - try: - lines = getNextLine(file).split() - if len(lines)!=4: - raise ValueError - emit = (float(lines[0])+float(lines[1])+float(lines[2]))/3 - mat.setEmit(emit) - except ValueError: - return "Emissive color in material " + str(i+1) + " is invalid!" - - # read shininess - try: - shi = float(getNextLine(file)) - #mat.setHardness(int(shi)) - except ValueError: - return "Shininess in material " + str(i+1) + " is invalid!" - - # read transparency - try: - alpha = float(getNextLine(file)) - mat.setAlpha(alpha) - if alpha < 1: - mat.mode |= Blender.Material.Modes.ZTRANSP - except ValueError: - return "Transparency in material " + str(i+1) + " is invalid!" - - # read texturemap - texturemap = getNextLine(file)[1:-1] - if len(texturemap)>0: - colorTexture = Blender.Texture.New(name + "_texture") - colorTexture.setType('Image') - colorTexture.setImage(loadImage(path, texturemap)) - mat.setTexture(0, colorTexture, Blender.Texture.TexCo.UV, Blender.Texture.MapTo.COL) - - # read alphamap - alphamap = getNextLine(file)[1:-1] - if len(alphamap)>0: - alphaTexture = Blender.Texture.New(name + "_alpha") - alphaTexture.setType('Image') - alphaTexture.setImage(loadImage(path, alphamap)) - mat.setTexture(1, alphaTexture, Blender.Texture.TexCo.UV, Blender.Texture.MapTo.ALPHA) - - # read the number of bones - try: - lines = getNextLine(file).split() - if len(lines)!=2 or lines[0]!="Bones:": - raise ValueError - numBones = int(lines[1]) - if numBones < 0 or numBones > MAX_NUMBONES: - raise ValueError - except: - return "Number of bones is invalid!" - - # create the armature - armature = None - armOb = None - if numBones > 0: - armOb = Blender.Object.New('Armature', "MilkShape3D Skeleton") - armature = Blender.Armature.New("MilkShape3D Skeleton") - armature.drawType = Blender.Armature.STICK - armOb.link(armature) - scn.objects.link(armOb) - armOb.makeParentDeform([meshOb]) - armature.makeEditable() - - # read bones - posKeys = {} - rotKeys = {} - for i in range(numBones): - # read name - name = getNextLine(file)[1:-1] - - # create the bone - bone = Blender.Armature.Editbone() - armature.bones[name] = bone - - # read parent - parent = getNextLine(file)[1:-1] - if len(parent)>0: - bone.parent = armature.bones[parent] - - # read position and rotation - try: - lines = getNextLine(file).split() - if len(lines) != 7: - raise ValueError - pos = [float(lines[1]), float(lines[2]), float(lines[3])] - rot = [float(lines[4]), float(lines[5]), float(lines[6])] - except ValueError: - return "Invalid position or orientation in a bone!" - - # set position and orientation - if bone.hasParent(): - bone.head = Vector(pos) * bone.parent.matrix + bone.parent.head - bone.tail = bone.head + Vector([1,0,0]) - tempM = RM(rot) * bone.parent.matrix - tempM.transpose; - bone.matrix = tempM - else: - bone.head = Vector(pos) - bone.tail = bone.head + Vector([1,0,0]) - bone.matrix = RM(rot) - - # Create vertex group for this bone - mesh.addVertGroup(name) - vgroup = [] - for index, v in enumerate(boneIds): - if v==i: - vgroup.append(index) - mesh.assignVertsToGroup(name, vgroup, 1.0, 1) - - # read the number of position key frames - try: - numPosKeys = int(getNextLine(file)) - if numPosKeys < 0 or numPosKeys > MAX_NUMPOSKEYS: - raise ValueError - except ValueError: - return "Invalid number of position key frames!" - - # read position key frames - posKeys[name] = [] - for j in range(numPosKeys): - # read time and position - try: - lines = getNextLine(file).split() - if len(lines) != 4: - raise ValueError - time = float(lines[0]) - pos = [float(lines[1]), float(lines[2]), float(lines[3])] - posKeys[name].append([time, pos]) - except ValueError: - return "Invalid position key frame!" - - # read the number of rotation key frames - try: - numRotKeys = int(getNextLine(file)) - if numRotKeys < 0 or numRotKeys > MAX_NUMROTKEYS: - raise ValueError - except ValueError: - return "Invalid number of rotation key frames!" - - # read rotation key frames - rotKeys[name] = [] - for j in range(numRotKeys): - # read time and rotation - try: - lines = getNextLine(file).split() - if len(lines) != 4: - raise ValueError - time = float(lines[0]) - rot = [float(lines[1]), float(lines[2]), float(lines[3])] - rotKeys[name].append([time, rot]) - except ValueError: - return "Invalid rotation key frame!" - - # create action and pose - action = None - pose = None - if armature != None: - armature.update() - pose = armOb.getPose() - action = armOb.getAction() - if not action: - action = Blender.Armature.NLA.NewAction() - action.setActive(armOb) - - # create animation key frames - for name, pbone in pose.bones.items(): - # create position keys - for key in posKeys[name]: - pbone.loc = Vector(key[1]) - pbone.insertKey(armOb, int(key[0]+0.5), Blender.Object.Pose.LOC, True) - - # create rotation keys - for key in rotKeys[name]: - pbone.quat = RQ(key[1]) - pbone.insertKey(armOb, int(key[0]+0.5), Blender.Object.Pose.ROT, True) - - # set the imported object to be the selected one - scn.objects.selected = [] - meshOb.sel= 1 - Blender.Redraw() - - # The import was a succes! - return "" - - -# load the model -def fileCallback(filename): - error = import_ms3d_ascii(filename) - if error!="": - Blender.Draw.PupMenu("An error occured during import: " + error + "|Not all data might have been imported succesfully.", 2) - -Blender.Window.FileSelector(fileCallback, 'Import') diff --git a/release/scripts/obdatacopier.py b/release/scripts/obdatacopier.py deleted file mode 100644 index 2f5617951de..00000000000 --- a/release/scripts/obdatacopier.py +++ /dev/null @@ -1,215 +0,0 @@ -#!BPY - -""" Registration info for Blender menus: <- these words are ignored -Name: 'Data Copier' -Blender: 232 -Group: 'Object' -Tip: 'Copy data from active object to other selected ones.' -""" - -__author__ = "Jean-Michel Soler (jms), Campbell Barton (Ideasman42)" -__url__ = ("blender", "blenderartists.org", -"Script's homepage, http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_lampdatacopier.htm", -"Communicate problems and errors, http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender") -__version__ = "0.1.2" - -__bpydoc__ = """\ -Use "Data Copier" to copy attributes from the active object to other selected ones of -its same type. - -This script is still in an early version but is already useful for copying -attributes for some types of objects like lamps and cameras. - -Usage: - -Select the objects that will be updated, select the object whose data will -be copied (they must all be of the same type, of course), then run this script. -Toggle the buttons representing the attributes to be copied and press "Copy". -""" - -# ---------------------------------------------------------- -# Object DATA copier 0.1.2 -# (c) 2004 jean-michel soler -# ----------------------------------------------------------- -#---------------------------------------------- -# Page officielle/official page du blender python Object DATA copier: -# http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_lampdatacopier.htm -# Communiquer les problemes et erreurs sur: -# To Communicate problems and errors on: -# http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender -#--------------------------------------------- -# Blender Artistic License -# http://download.blender.org/documentation/html/x21254.html -#--------------------------------------------- - -import Blender -from Blender import * -from Blender.Draw import * -from Blender.BGL import * - - -scn= Blender.Scene.GetCurrent() - -type_func_method= type(dir) -type_func= type(lambda:i) -type_dict= type({}) -# type_list= type([]) - -IGNORE_VARS = 'users', 'fakeUser', 'edges', 'faces', 'verts', 'elements' - -def renew(): - scn= Blender.Scene.GetCurrent() - act_ob= scn.objects.active - if act_ob==None: - return {} - - act_ob_type= act_ob.getType() - act_ob_data= act_ob.getData(mesh=1) - - if act_ob_data==None: # Surf? - return {} - - PARAM={} - evt=4 - doc='doc' - - for prop_name in dir(act_ob_data): - if not prop_name.startswith('__') and prop_name not in IGNORE_VARS: - # Get the type - try: exec 'prop_type= type(act_ob_data.%s)' % prop_name - except: prop_type= None - - if prop_type != None and prop_type not in (type_func_method, type_func, type_dict): - - # Now we know that the attribute can be listed in the UI Create a button and tooltip. - - # Tooltip - try: - if prop_name=='mode': - try: - exec "doc=str(%s.Modes)+' ; value : %s'"%( act_ob_type, str(act_ob_data.mode) ) - except: - exec """doc= '%s'+' value = '+ str(act_ob.getData(mesh=1).%s)"""%(prop_name, prop_name) - elif prop_name=='type': - try: - exec "doc=str(%s.Types)+' ; value : %s'"%( act_ob_type, str(act_ob_data.type) ) - except: - exec """doc= '%s'+' value = '+ str(act_ob.getData(mesh=1).%s)"""%(prop_name, prop_name) - else: - exec """doc= '%s'+' value = '+ str(act_ob_data.%s)"""%(prop_name, prop_name) - if doc.find('built-in')!=-1: - exec """doc= 'This is a function ! Doc = '+ str(act_ob_data.%s.__doc__)"""% prop_name - except: - doc='Doc...' - - # Button - PARAM[prop_name]= [Create(0), evt, doc] - evt+=1 - - return PARAM - -def copy(): - global PARAM - - scn= Blender.Scene.GetCurrent() - act_ob= scn.getActiveObject() - if act_ob==None: - Blender.Draw.PupMenu('Error|No Active Object.') - return - - act_ob_type= act_ob.getType() - - if act_ob_type in ('Empty', 'Surf'): - Blender.Draw.PupMenu('Error|Copying Empty or Surf object data isnt supported.') - return - - act_ob_data= act_ob.getData(mesh=1) - - print '\n\nStarting copy for object "%s"' % act_ob.name - some_errors= False - for ob in scn.objects.context: - if ob != act_ob and ob.getType() == act_ob_type: - ob_data= None - for prop_name, value in PARAM.iteritems(): - if value[0].val==1: - - # Init the object data if we havnt alredy - if ob_data==None: - ob_data= ob.getData(mesh=1) - - try: - exec "ob_data.%s = act_ob_data.%s"%(prop_name, prop_name) - except: - some_errors= True - print 'Cant copy property "%s" for type "%s"' % (prop_name, act_ob_type) - if some_errors: - Blender.Draw.PupMenu('Some attributes could not be copied, see console for details.') - -PARAM= renew() - -def EVENT(evt,val): - pass - -def BUTTON(evt): - global PARAM - if (evt==1): - Exit() - - if (evt==2): - copy() - Blender.Redraw() - - if (evt==3): - PARAM= renew() - Blender.Redraw() - -def DRAW(): - global PARAM - - scn= Blender.Scene.GetCurrent() - act_ob= scn.objects.active - - glColor3f(0.7, 0.7, 0.7) - glClear(GL_COLOR_BUFFER_BIT) - glColor3f(0.1, 0.1, 0.15) - - size=Buffer(GL_FLOAT, 4) - glGetFloatv(GL_SCISSOR_BOX, size) - size= size.list - for s in [0,1,2,3]: size[s]=int(size[s]) - ligne=20 - - Button("Exit",1,20,4,80,ligne) - Button("Copy",2,102,4,80,ligne) - Button("Renew",3,184,4,80,ligne) - - glRasterPos2f(20, ligne*2-8) - if act_ob: - Text(act_ob.getType()+" DATA copier") - else: - Text("Please select an object") - - - max=size[3] / 22 -2 - pos = 0 - decal = 20 - key=PARAM.keys() - key.sort() - for p in key: - if pos==max: - decal+=102 - pos=1 - else: - pos+=1 - - PARAM[p][0]=Toggle(p, - PARAM[p][1], - decal, - pos*22+22, - 100, - 20, - PARAM[p][0].val, - str(PARAM[p][2])) - - -Register(DRAW,EVENT,BUTTON) diff --git a/release/scripts/object_active_to_other.py b/release/scripts/object_active_to_other.py deleted file mode 100644 index 68aa6a3a039..00000000000 --- a/release/scripts/object_active_to_other.py +++ /dev/null @@ -1,58 +0,0 @@ -#!BPY -""" -Name: 'Copy Active to Selected' -Blender: 249 -Group: 'Object' -Tooltip: 'For every selected object, copy the active to their loc/size/rot' -""" - -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Script copyright (C) Campbell Barton -# -# 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 ***** -# -------------------------------------------------------------------------- - - -from Blender import Window, sys, Draw -import bpy - -def my_object_util(sce): - ob_act = sce.objects.active - - if not ob_act: - Draw.PupMenu('Error%t|No active object selected') - return - - mats = [(ob, ob.matrixWorld) for ob in sce.objects.context if ob != ob_act] - - for ob, m in mats: - ob_copy = ob_act.copy() - sce.objects.link(ob_copy) - ob_copy.setMatrix(m) - ob_copy.Layers = ob.Layers & (1<<20)-1 - - -def main(): - sce = bpy.data.scenes.active - - Window.WaitCursor(1) - my_object_util(sce) - Window.WaitCursor(0) - -if __name__ == '__main__': - main() diff --git a/release/scripts/object_apply_def.py b/release/scripts/object_apply_def.py deleted file mode 100644 index 006e97463d8..00000000000 --- a/release/scripts/object_apply_def.py +++ /dev/null @@ -1,178 +0,0 @@ -#!BPY - -""" -Name: 'Apply Deformation' -Blender: 242 -Group: 'Object' -Tooltip: 'Make copys of all the selected objects with modifiers, softbodies and fluid baked into a mesh' -""" - -__author__ = "Martin Poirier (theeth), Jean-Michel Soler (jms), Campbell Barton (ideasman)" -# This script is the result of merging the functionalities of two other: -# Martin Poirier's Apply_Def.py and -# Jean-Michel Soler's Fix From Everything - -__url__ = ("http://www.blender.org", "http://blenderartists.org", "http://jmsoler.free.fr") -__version__ = "1.6 07/07/2006" - -__bpydoc__ = """\ -This script creates "raw" copies of deformed meshes. - -Usage: - -Select any number of Objects and run this script. A fixed copy of each selected object -will be created, with the word "_def" appended to its name. If an object with -the same name already exists, it appends a number at the end as Blender itself does. - -Objects in Blender can be deformed by armatures, lattices, curve objects and subdivision, -but this will only change its appearance on screen and rendered -images -- the actual mesh data is still simpler, with vertices in an original -"rest" position and less vertices than the subdivided version. - -Use this script if you want a "real" version of the deformed mesh, so you can -directly manipulate or export its data. - -This script will work with object types: Mesh, Metaballs, Text3d, Curves and Nurbs Surface. -""" - - -# $Id$ -# -# -------------------------------------------------------------------------- -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Copyright (C) 2003: Martin Poirier, theeth@yahoo.com -# -# Thanks to Jonathan Hudson for help with the vertex groups part -# -# 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 ***** - - -import Blender -import bpy -import BPyMesh - -def copy_vgroups(source_ob, target_ob): - - source_me = source_ob.getData(mesh=1) - - vgroups= source_me.getVertGroupNames() - if vgroups: - ADD= Blender.Mesh.AssignModes.ADD - target_me = target_ob.getData(mesh=1) - for vgroupname in vgroups: - target_me.addVertGroup(vgroupname) - if len(target_me.verts) == len(source_me.verts): - try: # in rare cases this can raise an 'no deform groups assigned to mesh' error - vlist = source_me.getVertsFromGroup(vgroupname, True) - except: - vlist = [] - - try: - for vpair in vlist: - target_me.assignVertsToGroup(vgroupname, [vpair[0]], vpair[1], ADD) - except: - pass - - -def apply_deform(): - scn= bpy.data.scenes.active - #Blender.Window.EditMode(0) - - NAME_LENGTH = 19 - SUFFIX = "_def" - SUFFIX_LENGTH = len(SUFFIX) - # Get all object and mesh names - - - ob_list = list(scn.objects.context) - ob_act = scn.objects.active - - # Assume no soft body - has_sb= False - - # reverse loop so we can remove objects (metaballs in this case) - for ob_idx in xrange(len(ob_list)-1, -1, -1): - ob= ob_list[ob_idx] - - ob.sel = 0 # deselect while where checking the metaballs - - # Test for a softbody - if not has_sb and ob.isSB(): - has_sb= True - - # Remove all numbered metaballs because their disp list is only on the main metaball (un numbered) - if ob.type == 'MBall': - name= ob.name - # is this metaball numbered? - dot_idx= name.rfind('.') + 1 - if name[dot_idx:].isdigit(): - # Not the motherball, ignore it. - del ob_list[ob_idx] - - - if not ob_list: - Blender.Draw.PupMenu('No objects selected, nothing to do.') - return - - - if has_sb: - curframe=Blender.Get('curframe') - for f in xrange(curframe): - Blender.Set('curframe',f+1) - Blender.Window.RedrawAll() - - used_names = [ob.name for ob in Blender.Object.Get()] - used_names.extend(Blender.NMesh.GetNames()) - - - deformedList = [] - for ob in ob_list: - - # Get the mesh data - new_me= BPyMesh.getMeshFromObject(ob, vgroups=False) - - if not new_me: - continue # Object has no display list - - - name = ob.name - new_name = "%s_def" % name[:NAME_LENGTH-SUFFIX_LENGTH] - num = 0 - - while new_name in used_names: - new_name = "%s_def.%.3i" % (name[:NAME_LENGTH-(SUFFIX_LENGTH+SUFFIX_LENGTH)], num) - num += 1 - used_names.append(new_name) - - new_me.name= new_name - - new_ob= scn.objects.new(new_me) - new_ob.setMatrix(ob.matrixWorld) - - # Make the active duplicate also active - if ob == ob_act: - scn.objects.active = new_ob - - # Original object was a mesh? see if we can copy any vert groups. - if ob.type =='Mesh': - copy_vgroups(ob, new_ob) - - Blender.Window.RedrawAll() - -if __name__=='__main__': - apply_deform() diff --git a/release/scripts/object_batch_name_edit.py b/release/scripts/object_batch_name_edit.py deleted file mode 100644 index 4db3a6210db..00000000000 --- a/release/scripts/object_batch_name_edit.py +++ /dev/null @@ -1,274 +0,0 @@ -#!BPY -""" -Name: 'Batch Object Name Edit' -Blender: 240 -Group: 'Object' -Tooltip: 'Apply the chosen rule to rename all selected objects at once.' -""" -__author__ = "Campbell Barton" -__url__ = ("blender", "blenderartists.org") -__version__ = "1.0" - -__bpydoc__ = """\ -"Batch Object Name Edit" allows you to change multiple names of Blender -objects at once. It provides options to define if you want to: replace text -in the current names, truncate their beginnings or endings or prepend / append -strings to them. - -Usage: -Select the objects to be renamed and run this script from the Object->Scripts -menu of the 3d View. -""" -# $Id$ -# -# -------------------------------------------------------------------------- -# Batch Name Edit by Campbell Barton (AKA Ideasman) -# -------------------------------------------------------------------------- -# ***** 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 ***** -# -------------------------------------------------------------------------- -from Blender import * -import bpy - -global renameCount -renameCount = 0 -obsel = [ob for ob in bpy.data.scenes.active.objects.context if not ob.lib] - -def setDataNameWrapper(ob, newname): - if ob.getData(name_only=1) == newname: - return False - - data= ob.getData(mesh=1) - - if data and not data.lib: - data.name= newname - return True - return False - -def main(): - global renameCount - # Rename the datablocks that are used by the object. - def renameLinkedDataFromObject(): - - # Result 1, we want to rename data - for ob in obsel: - if ob.name == ob.getData(name_only=1): - return # Alredy the same name, dont bother. - - data = ob.getData(mesh=1) # use mesh so we dont have to update the nmesh. - if data and not data.lib: - data.name = ob.name - - - def new(): - global renameCount - NEW_NAME_STRING = Draw.Create('') - RENAME_LINKED = Draw.Create(0) - pup_block = [\ - ('New Name: ', NEW_NAME_STRING, 19, 19, 'New Name'),\ - ('Rename ObData', RENAME_LINKED, 'Renames objects data to match the obname'),\ - ] - - if not Draw.PupBlock('Replace in name...', pup_block): - return 0 - - NEW_NAME_STRING= NEW_NAME_STRING.val - - Window.WaitCursor(1) - for ob in obsel: - if ob.name != NEW_NAME_STRING: - ob.name = NEW_NAME_STRING - renameCount+=1 - - return RENAME_LINKED.val - - def replace(): - global renameCount - REPLACE_STRING = Draw.Create('') - WITH_STRING = Draw.Create('') - RENAME_LINKED = Draw.Create(0) - - pup_block = [\ - ('Replace: ', REPLACE_STRING, 19, 19, 'Text to find'),\ - ('With:', WITH_STRING, 19, 19, 'Text to replace with'),\ - ('Rename ObData', RENAME_LINKED, 'Renames objects data to match the obname'),\ - ] - - if not Draw.PupBlock('Replace in name...', pup_block) or\ - ((not REPLACE_STRING.val) and (not WITH_STRING)): - return 0 - - REPLACE_STRING = REPLACE_STRING.val - WITH_STRING = WITH_STRING.val - - Window.WaitCursor(1) - for ob in obsel: - newname = ob.name.replace(REPLACE_STRING, WITH_STRING) - if ob.name != newname: - ob.name = newname - renameCount+=1 - return RENAME_LINKED.val - - - def prefix(): - global renameCount - PREFIX_STRING = Draw.Create('') - RENAME_LINKED = Draw.Create(0) - - pup_block = [\ - ('Prefix: ', PREFIX_STRING, 19, 19, 'Name prefix'),\ - ('Rename ObData', RENAME_LINKED, 'Renames objects data to match the obname'),\ - ] - - if not Draw.PupBlock('Prefix...', pup_block) or\ - not PREFIX_STRING.val: - return 0 - - PREFIX_STRING = PREFIX_STRING.val - - Window.WaitCursor(1) - for ob in obsel: - ob.name = PREFIX_STRING + ob.name - renameCount+=1 # we knows these are different. - return RENAME_LINKED.val - - def suffix(): - global renameCount - SUFFIX_STRING = Draw.Create('') - RENAME_LINKED = Draw.Create(0) - - pup_block = [\ - ('Suffix: ', SUFFIX_STRING, 19, 19, 'Name suffix'),\ - ('Rename ObData', RENAME_LINKED, 'Renames objects data to match the obname'),\ - ] - - if not Draw.PupBlock('Suffix...', pup_block) or\ - not SUFFIX_STRING.val: - return 0 - - SUFFIX_STRING = SUFFIX_STRING.val - - Window.WaitCursor(1) - for ob in obsel: - ob.name = ob.name + SUFFIX_STRING - renameCount+=1 # we knows these are different. - return RENAME_LINKED.val - - def truncate_start(): - global renameCount - TRUNCATE_START = Draw.Create(0) - RENAME_LINKED = Draw.Create(0) - - pup_block = [\ - ('Truncate Start: ', TRUNCATE_START, 0, 19, 'Truncate chars from the start of the name'),\ - ('Rename ObData', RENAME_LINKED, 'Renames objects data to match the obname'),\ - ] - - if not Draw.PupBlock('Truncate Start...', pup_block) or\ - not TRUNCATE_START.val: - return 0 - - Window.WaitCursor(1) - TRUNCATE_START = TRUNCATE_START.val - for ob in obsel: - newname = ob.name[TRUNCATE_START: ] - ob.name = newname - renameCount+=1 - - return RENAME_LINKED.val - - def truncate_end(): - global renameCount - TRUNCATE_END = Draw.Create(0) - RENAME_LINKED = Draw.Create(0) - - pup_block = [\ - ('Truncate End: ', TRUNCATE_END, 0, 19, 'Truncate chars from the end of the name'),\ - ('Rename ObData', RENAME_LINKED, 'Renames objects data to match the obname'),\ - ] - - if not Draw.PupBlock('Truncate End...', pup_block) or\ - not TRUNCATE_END.val: - return 0 - - Window.WaitCursor(1) - TRUNCATE_END = TRUNCATE_END.val - for ob in obsel: - newname = ob.name[: -TRUNCATE_END] - ob.name = newname - renameCount+=1 - - return RENAME_LINKED.val - - def renameObjectFromLinkedData(): - global renameCount - Window.WaitCursor(1) - - for ob in obsel: - newname = ob.getData(name_only=1) - if newname != None and ob.name != newname: - ob.name = newname - renameCount+=1 - return 0 - - def renameObjectFromDupGroup(): - global renameCount - Window.WaitCursor(1) - - for ob in obsel: - group= ob.DupGroup - if group != None: - newname= group.name - if newname != ob.name: - ob.name = newname - renameCount+=1 - return 0 - - def renameLinkedDataFromObject(): - global renameCount - Window.WaitCursor(1) - - for ob in obsel: - if setDataNameWrapper(ob, ob.name): - renameCount+=1 - return 0 - - name = "Selected Object Names%t|New Name|Replace Text|Add Prefix|Add Suffix|Truncate Start|Truncate End|Rename Objects to Data Names|Rename Objects to DupGroup Names|Rename Data to Object Names" - result = Draw.PupMenu(name) - renLinked = 0 # Rename linked data to the object name? - if result == -1: - return - elif result == 1: renLinked= new() - elif result == 2: renLinked= replace() - elif result == 3: renLinked= prefix() - elif result == 4: renLinked= suffix() - elif result == 5: renLinked= truncate_start() - elif result == 6: renLinked= truncate_end() - elif result == 7: renameObjectFromLinkedData() - elif result == 8: renameObjectFromDupGroup() - elif result == 9: renameLinkedDataFromObject() - - if renLinked: - renameLinkedDataFromObject() - - Window.WaitCursor(0) - - Draw.PupMenu('renamed: %d objects.' % renameCount) - -if __name__=='__main__': - main() diff --git a/release/scripts/object_cookie_cutter.py b/release/scripts/object_cookie_cutter.py deleted file mode 100644 index 4950c18c0f4..00000000000 --- a/release/scripts/object_cookie_cutter.py +++ /dev/null @@ -1,667 +0,0 @@ -#!BPY -""" -Name: 'Cookie Cut from View' -Blender: 234 -Group: 'Object' -Tooltip: 'Cut from the view axis, (Sel 3d Curves and Meshes (only edges) into other meshes with faces)' -""" -__author__= "Campbell Barton" -__url__= ["blender", "blenderartist"] -__version__= "1.0" - -__bpydoc__= """\ -This script takes the selected mesh objects, divides them into 2 groups -Cutters and The objects to be cut. - -Cutters are meshes with no faces, just edge loops. and any meshes with faces will be cut. - -Usage: - -Select 2 or more meshes, one with no faces (a closed polyline) and one with faces to cut. - -Align the view on the axis you want to cut. -For shapes that have overlapping faces (from the view), hide any backfacing faces so they will be ignored during the cut. -Run the script. - -You can choose to make the cut verts lie on the face that they were cut from or on the edge that cut them. -This script supports UV coordinates and images. -""" - -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Script copyright (C) Campbell Barton -# -# 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 ***** -# -------------------------------------------------------------------------- - -import Blender -from math import sqrt -import BPyMesh -Vector= Blender.Mathutils.Vector -LineIntersect2D= Blender.Geometry.LineIntersect2D -PointInTriangle2D= Blender.Geometry.PointInTriangle2D - -# Auto class -def auto_class(slots): - exec('class container_class(object): __slots__=%s' % slots) - return container_class - - -bignum= 1<<30 -def bounds_xy(iter_item): - ''' - Works with types - MMesh.verts - MFace - MEdge - ''' - xmin= ymin= bignum - xmax= ymax= -bignum - for v in iter_item: - x= v.co.x - y= v.co.y - if x<xmin: xmin= x - if y<ymin: ymin= y - if x>xmax: xmax= x - if y>ymax: ymax= y - - return xmin, ymin, xmax, ymax - -def bounds_intersect(a,b): - ''' - each tuple is - xmin, ymin, xmax, ymax - ''' - if\ - a[0]>b[2] or\ - a[1]>b[3] or\ - a[2]<b[0] or\ - a[3]<b[1]: - return False - else: - return True - -def point_in_bounds(pt, bounds): - ''' - each tuple is - xmin, ymin, xmax, ymax - ''' - if bounds[0] < pt.x < bounds[2] and bounds[1] < pt.y < bounds[3]: - return True - else: - return False - -def point_in_poly2d(pt, fvco): - if PointInTriangle2D(pt, fvco[0], fvco[1], fvco[2]): - return True - if len(fvco) == 4: - if PointInTriangle2D(pt, fvco[0], fvco[2], fvco[3]): - return True - return False - -# reuse me more. -def sorted_edge_indicies(ed): - i1= ed.v1.index - i2= ed.v2.index - if i1>i2: - i1,i2= i2,i1 - return i1, i2 - -def sorted_indicies(i1, i2): - if i1>i2: - i1,i2= i2,i1 - return i1, i2 - -def fake_length2d(pt1, pt2): - ''' - Only used for comparison so don't sqrt - ''' - #return math.sqrt(abs(pow(x1-x2, 2)+ pow(y1-y2, 2))) - return pow(pt1[0]-pt2[0], 2) + pow(pt1[1]- pt2[1], 2) - -def length2d(pt1, pt2): - ''' - Only used for comparison so don't sqrt - ''' - #return math.sqrt(abs(pow(x1-x2, 2)+ pow(y1-y2, 2))) - return sqrt(pow(pt1[0]-pt2[0], 2) + pow(pt1[1]- pt2[1], 2)) - - - -def tri_area_2d(v1, v2, v3): - e1 = length2d(v1, v2) - e2 = length2d(v2, v3) - e3 = length2d(v3, v1) - p = e1+e2+e3 - return 0.25 * sqrt(abs(p*(p-2*e1)*(p-2*e2)*(p-2*e3))) - -def tri_pt_find_z_2d(pt, tri): - """ Takes a face and 3d vector and assigns the vectors Z to its on the face""" - - l1= tri_area_2d(tri[1], tri[2], pt) - l2= tri_area_2d(tri[0], tri[2], pt) - l3= tri_area_2d(tri[0], tri[1], pt) - - tot= l1+l2+l3 - # Normalize - l1=l1/tot - l2=l2/tot - l3=l3/tot - - z1= tri[0].z*l1 - z2= tri[1].z*l2 - z3= tri[2].z*l3 - - return z1+z2+z3 - - -def tri_pt_find_uv_2d(pt, tri, uvs): - """ Takes a face and 3d vector and assigns the vectors Z to its on the face""" - - l1= tri_area_2d(tri[1], tri[2], pt) - l2= tri_area_2d(tri[0], tri[2], pt) - l3= tri_area_2d(tri[0], tri[1], pt) - - tot= l1+l2+l3 - if not tot: # No area, just return the first uv - return Vector(uvs[0]) - - # Normalize - l1=l1/tot - l2=l2/tot - l3=l3/tot - - uv1= uvs[0]*l1 - uv2= uvs[1]*l2 - uv3= uvs[2]*l3 - - return uv1+uv2+uv3 - - - - -def mesh_edge_dict(me): - ed_dict= {} - for f in me.faces: - if not f.hide: - for edkey in f.edge_keys: - ed_dict.setdefault(edkey, []).append(f) - - return ed_dict - - - -def terrain_cut_2d(t, c, PREF_Z_LOC): - ''' - t is the terrain - c is the cutter - - PREF_Z_LOC: 0 - from terrain face - 1 - from cutter edge - - returns nothing - ''' - - # do we have a 2d intersection - if not bounds_intersect(t.bounds, c.bounds): - return - - # Local vars - me_t= t.mesh - me_c= c.mesh - - has_uv= me_t.faceUV - - Blender.Mesh.Mode(Blender.Mesh.SelectModes['VERTEX']) - ''' - first assign a face terrain face for each cutter verticie - ''' - cut_verts_temp= list(me_c.verts) - cut_vert_terrain_faces= [None] * len(me_c.verts) - vert_z_level= [-10.0] * len(me_c.verts) - - for v in me_c.verts: - v_index= v.index - v_co= v.co - for fidx, f in enumerate(me_t.faces): - if not f.hide: - if point_in_bounds(v_co, t.face_bounds[fidx]): - f_v= [vv.co for vv in f] - if point_in_poly2d(v_co, f_v): - - - if PREF_Z_LOC==0: - ''' - Get the z location from the face. - ''' - - if len(f_v)==3: - vert_z_level[v_index]= tri_pt_find_z_2d(v_co, (f_v[0], f_v[1], f_v[2]) ) - else: - # Quad, which side are we on? - a1= tri_area_2d(f_v[0], f_v[1], v_co) - a2= tri_area_2d(f_v[1], f_v[2], v_co) - - a3= tri_area_2d(f_v[0], f_v[1], f_v[2]) - - if a1+a2<a3: - vert_z_level[v_index]= tri_pt_find_z_2d(v_co, (f_v[0], f_v[1], f_v[2]) ) - else: - vert_z_level[v_index]= tri_pt_find_z_2d(v_co, (f_v[0], f_v[2], f_v[3]) ) - - else: # PREF_Z_LOC==1 - ''' - Get the z location from the vert - ''' - vert_z_level[v_index]= v_co.z - - # Non overlapping faces in terrain mean we can break - cut_vert_terrain_faces[v_index]= f - break - - del cut_verts_temp - - - - edge_intersections= [] - edge_isect_type= auto_class(['point', 'ed_terrain', 'ed_cut']) - - # intersect cutter faces with terrain edges. - for ei_t, ed_t in enumerate(me_t.edges): - - eb_t= t.edge_bounds[ei_t] - if bounds_intersect(eb_t, c.bounds): # face/cutter bounds intersect? - # Loop through the cutter edges. - for ei_c, ed_c in enumerate(me_c.edges): - # If the cutter edge has 2 verts inside the same face then we can ignore it - # Both are different faces or None - if cut_vert_terrain_faces[ed_c.v1.index] != cut_vert_terrain_faces[ed_c.v2.index] or\ - cut_vert_terrain_faces[ed_c.v1.index] == cut_vert_terrain_faces[ed_c.v2.index] == None: - eb_c= c.edge_bounds[ei_c] - if bounds_intersect(eb_t, eb_c): # face/edge bounds intersect? - # Now we know the 2 edges might intersect, we'll do a proper test - - x= LineIntersect2D(ed_t.v1.co, ed_t.v2.co, ed_c.v1.co, ed_c.v2.co) - if x: - ed_isect= edge_isect_type() - ed_isect.point= x.resize3D() # fake 3d - - # Find the interpolation Z point - - if PREF_Z_LOC==0: - ''' - Terrains edge - ''' - l1= length2d(ed_isect.point, ed_t.v1.co) - l2= length2d(ed_isect.point, ed_t.v2.co) - ed_isect.point.z= ((l2*ed_t.v1.co.z) + (l1*ed_t.v2.co.z)) / (l1+l2) - else: - ''' - Cutters edge - ''' - l1= length2d(ed_isect.point, ed_c.v1.co) - l2= length2d(ed_isect.point, ed_c.v2.co) - ed_isect.point.z= ((l2*ed_c.v1.co.z) + (l1*ed_c.v2.co.z)) / (l1+l2) - - ed_isect.ed_terrain= ed_t - ed_isect.ed_cut= ed_c - - edge_intersections.append(ed_isect) - - if not edge_intersections: - return - - # Now we have collected intersections we need to apply them - - # Find faces that have intersections, these faces will need to be cut. - faces_intersecting= {} # face index as key, list of edges as values - for ed_isect in edge_intersections: - - try: - faces= t.edge_dict[ sorted_edge_indicies(ed_isect.ed_terrain) ] - except: - # If the faces are hidden then the faces wont exist. - faces= [] - - for f in faces: - faces_intersecting.setdefault(f.index, []).append(ed_isect) - - # this list is used to store edges that are totally inside a face ( no intersections with terrain) - # we can remove these as we - face_containing_edges= [[] for i in xrange(len(me_t.faces))] - for ed_c in me_c.edges: - if cut_vert_terrain_faces[ed_c.v1.index]==cut_vert_terrain_faces[ed_c.v2.index] != None: - # were inside a face. - face_containing_edges[cut_vert_terrain_faces[ed_c.v1.index].index].append(ed_c) - - # New Mesh for filling faces only - new_me= Blender.Mesh.New() - scn= Blender.Scene.GetCurrent() - ob= Blender.Object.New('Mesh') - ob.link(new_me) - scn.link(ob) - ob.sel= True - - new_faces= [] - new_faces_props= [] - new_uvs= [] - new_verts= [] - - # Loop through inter - for fidx_t, isect_edges in faces_intersecting.iteritems(): - f= me_t.faces[fidx_t] - f_v= f.v - fidxs_s= [v.index for v in f_v] - - # Make new fake edges for each edge, each starts as a list of 2 verts, but more verts can be added - # This list will then be sorted so the edges are in order from v1 to v2 of the edge. - face_new_verts= [ (f_v[i], [], f_v[i-1]) for i in xrange(len(f_v)) ] - # if len(face_new_verts) < 3: raise 'weirdo' - - face_edge_dict = dict( [(sorted_indicies(fidxs_s[i], fidxs_s[i-1]), i) for i in xrange(len(f_v))] ) - - for ed_isect in isect_edges: - edge_index_in_face = face_edge_dict[ sorted_edge_indicies(ed_isect.ed_terrain) ] - # Add this intersection to the face - face_new_verts[edge_index_in_face][1].append(ed_isect) - - # Now sort the intersections - for new_edge in face_new_verts: - if len(new_edge[1]) > 1: - # We have 2+ verts to sort - edv1= tuple(new_edge[0].co) # 3d but well only use the 2d part - new_edge[1].sort(lambda a,b: cmp(fake_length2d(a.point, edv1), fake_length2d(b.point, edv1) )) - - # now build up a new face by getting edges - random_face_edges= [] - unique_verts= [] # store vert - rem_double_edges= {} - - def add_edge(p1, p2): - k1= tuple(p1) - k2= tuple(p2) - - # Adds new verts where needed - try: - i1= rem_double_edges[k1] - except: - i1= rem_double_edges[k1]= len(rem_double_edges) - unique_verts.append(k1) - - try: - i2= rem_double_edges[k2] - except: - i2= rem_double_edges[k2]= len(rem_double_edges) - unique_verts.append(k2) - - random_face_edges.append( (i1, i2) ) - - - - # edges that don't have a vert in the face have to span between to intersection points - # since we don't know the other point at any 1 time we need to remember edges that - # span a face and add them once we'v collected both - # first add outline edges - edge_span_face= {} - for new_edge in face_new_verts: - new_edge_subdiv= len(new_edge[1]) - if new_edge_subdiv==0: - # no subdiv edges, just add - add_edge(new_edge[0].co, new_edge[2].co) - elif new_edge_subdiv==1: - add_edge(new_edge[0].co, new_edge[1][0].point) - add_edge(new_edge[1][0].point, new_edge[2].co) - else: - # 2 or more edges - add_edge(new_edge[0].co, new_edge[1][0].point) - add_edge(new_edge[1][-1].point, new_edge[2].co) - - # now add multiple - for i in xrange(new_edge_subdiv-1): - add_edge(new_edge[1][i].point, new_edge[1][i+1].point) - - # done adding outline - # while looping through the edge subdivs, add the edges that intersect - - - for ed_isect in new_edge[1]: - ed_cut= ed_isect.ed_cut - if cut_vert_terrain_faces[ed_cut.v1.index]==f: - # our first vert is inside the face - point= Vector(ed_cut.v1.co) - point.z= vert_z_level[ed_cut.v1.index] - - add_edge(point, ed_isect.point) - elif cut_vert_terrain_faces[ed_cut.v2.index]==f: - # assume second vert is inside the face - point= Vector(ed_cut.v2.co) - point.z= vert_z_level[ed_cut.v2.index] - add_edge(point, ed_isect.point) - else: - # this edge has no verts in the face so it will need to be clipped in 2 places - try: - point= edge_span_face[ed_cut] - - # if were here it worked ;) - add_edge(point, ed_isect.point) - - except: - # add the first intersecting point - edge_span_face[ed_cut]= ed_isect.point - - # now add all edges that are inside the the face - for ed_c in face_containing_edges[fidx_t]: - point1= Vector(ed_c.v1.co) - point2= Vector(ed_c.v2.co) - point1.z= vert_z_level[ed_c.v1.index] - point2.z= vert_z_level[ed_c.v2.index] - add_edge(point1, point2) - - new_me.verts.extend(unique_verts) - new_me.edges.extend(random_face_edges) - new_me.sel= 1 - - # backup the z values, fill and restore - - backup_z= [v.co.z for v in new_me.verts] - for v in new_me.verts: v.co.z= 0 - #raise 'as' - new_me.fill() - for i, v in enumerate(new_me.verts): v.co.z= backup_z[i] - - - # ASSIGN UV's - if has_uv: - f_uv= f_uv_mod= f.uv - f_vco= f_vco_mod= [v.co for v in f] - - # f is the face, get the uv's from that. - - uvs= [None] * len(new_me.verts) - for i, v in enumerate(new_me.verts): - v_co= v.co - f_uv_mod= f_uv - f_vco_mod= f_vco - - if len(f_v)==4: - # Quad, which side are we on? - a1= tri_area_2d(f_vco[0], f_vco[1], v_co) - a2= tri_area_2d(f_vco[1], f_vco[2], v_co) - - a3= tri_area_2d(f_vco[0], f_vco[1], f_vco[2]) - if a1+a2 > a3: - # 0,2,3 - f_uv_mod= f_uv[0], f_uv[2], f_uv[3] - f_vco_mod= f_vco[0], f_vco[2], f_vco[3] - # else - side of 0,1,2 - don't modify the quad - - uvs[i]= tri_pt_find_uv_2d(v_co, f_vco_mod, f_uv_mod) - - new_uvs.extend(uvs) - new_faces_props.extend( [f.image] * len(new_me.faces) ) - - # collect the fill results - new_verts_len= len(new_verts) + len(me_t.verts) - new_faces.extend( [[v.index+new_verts_len for v in ff] for ff in new_me.faces] ) - - - - new_verts.extend(unique_verts) - - new_me.verts= None - #raise 'error' - - # Finished filling - scn.unlink(ob) - - - # Remove faces - face_len = len(me_t.faces) - verts_len = len(me_t.verts) - me_t.verts.extend(new_verts) - me_t.faces.extend(new_faces) - - for i in xrange(len(new_faces)): - f= me_t.faces[face_len+i] - - if has_uv: - img= new_faces_props[i] - if img: f.image= img - - f_uv= f.uv - for ii, v in enumerate(f): - v_index= v.index-verts_len - new_uv= new_uvs[v_index] - uv= f_uv[ii] - uv.x= new_uv.x - uv.y= new_uv.y - - me_t.faces.delete(1, faces_intersecting.keys()) - me_t.sel= 1 - me_t.remDoubles(0.0000001) - - -def main(): - PREF_Z_LOC= Blender.Draw.PupMenu('Cut Z Location%t|Original Faces|Cutting Polyline') - - if PREF_Z_LOC==-1: - return - PREF_Z_LOC-=1 - - Blender.Window.WaitCursor(1) - - print '\nRunning Cookie Cutter' - time= Blender.sys.time() - scn = Blender.Scene.GetCurrent() - obs= [ob for ob in scn.objects.context if ob.type in ('Mesh', 'Curve')] - MULTIRES_ERROR = False - - # Divide into 2 lists- 1 with faces, one with only edges - terrains= [] #[me for me in mes if me.faces] - cutters= [] #[me for me in mes if not me.faces] - - terrain_type= auto_class(['mesh', 'bounds', 'face_bounds', 'edge_bounds', 'edge_dict', 'cutters', 'matrix']) - - for ob in obs: - if ob.type == 'Mesh': - me= ob.getData(mesh=1) - elif ob.data.flag & 1: # Is the curve 3D? else don't use. - me= BPyMesh.getMeshFromObject(ob) # get the curve - else: - continue - - # a new terrain instance - if me.multires: - MULTIRES_ERROR = True - else: - t= terrain_type() - - t.matrix= ob.matrixWorld * Blender.Window.GetViewMatrix() - - # Transform the object by its matrix - me.transform(t.matrix) - - # Set the terrain bounds - t.bounds= bounds_xy(me.verts) - t.edge_bounds= [bounds_xy(ed) for ed in me.edges] - t.mesh= me - - if me.faces: # Terrain. - t.edge_dict= mesh_edge_dict(me) - t.face_bounds= [bounds_xy(f) for f in me.faces] - t.cutters= [] # Store cutting objects that cut us here - terrains.append(t) - elif len(me.edges)>2: # Cutter - cutters.append(t) - - totcuts= len(terrains)*len(cutters) - if not totcuts: - Blender.Window.WaitCursor(0) - Blender.Draw.PupMenu('ERROR%t|Select at least 1 closed loop mesh (edges only)|as the cutter...|and 1 or more meshes to cut into') - - crazy_point= Vector(100000, 100000) - - for t in terrains: - for c in cutters: - # Main curring function - terrain_cut_2d(t, c, PREF_Z_LOC) - - # Was the terrain touched? - if len(t.face_bounds) != len(t.mesh.faces): - t.edge_dict= mesh_edge_dict(t.mesh) - # remake the bounds - t.edge_bounds= [bounds_xy(ed) for ed in t.mesh.edges] - t.face_bounds= [bounds_xy(f) for f in t.mesh.faces] - t.cutters.append(c) - - print '\t%i remaining' % totcuts - totcuts-=1 - - # SELECT INTERNAL FACES ONCE THIS TERRAIN IS CUT - Blender.Mesh.Mode(Blender.Mesh.SelectModes['FACE']) - t.mesh.sel= 0 - for c in t.cutters: - edge_verts_c= [(ed_c.v1.co, ed_c.v2.co) for ed_c in c.mesh.edges] - for f in t.mesh.faces: - # How many edges do we intersect on our way to the faces center - if not f.hide and not f.sel: # Not alredy selected - c= f.cent - if point_in_bounds(c, t.bounds): - isect_count= 0 - for edv1, edv2 in edge_verts_c: - isect_count += (LineIntersect2D(c, crazy_point, edv1, edv2) != None) - - if isect_count%2: - f.sel= 1 - Blender.Mesh.Mode(Blender.Mesh.SelectModes['FACE']) - - # Restore the transformation - for data in (terrains, cutters): - for t in data: - if t.mesh.users: # it may have been a temp mesh from a curve. - t.mesh.transform(t.matrix.copy().invert()) - - Blender.Window.WaitCursor(0) - - if MULTIRES_ERROR: - Blender.Draw.PupMenu('Error%t|One or more meshes meshes not cut because they are multires.') - - print 'terrains:%i cutters %i %.2f secs taken' % (len(terrains), len(cutters), Blender.sys.time()-time) - - -if __name__=='__main__': - main() diff --git a/release/scripts/object_drop.py b/release/scripts/object_drop.py deleted file mode 100644 index 19cc1f8d15a..00000000000 --- a/release/scripts/object_drop.py +++ /dev/null @@ -1,253 +0,0 @@ -#!BPY -""" -Name: 'Drop Onto Ground' -Blender: 249 -Group: 'Object' -Tooltip: 'Drop the selected objects onto "ground" objects' -""" -__author__= "Campbell Barton" -__url__= ["blender.org", "blenderartists.org"] -__version__= "1.1" - -__bpydoc__= """ -""" - -# -------------------------------------------------------------------------- -# Drop Objects v1.0 by Campbell Barton (AKA Ideasman42) -# -------------------------------------------------------------------------- -# ***** 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 ***** -# -------------------------------------------------------------------------- - - -from Blender import Draw, Geometry, Mathutils, Window -from Blender.Mathutils import Vector, AngleBetweenVecs, RotationMatrix -import bpy - - -GLOBALS = {} -GLOBALS['GROUND_SOURCE'] = [Draw.Create(1), Draw.Create(0)] -GLOBALS['GROUND_GROUP_NAME'] = Draw.Create('terrain') -GLOBALS['DROP_AXIS'] = [Draw.Create(1), Draw.Create(0)] # on what axis will we drop? -GLOBALS['DROP_OVERLAP_CHECK'] = Draw.Create(1) # is the terrain a single skin? -GLOBALS['DROP_ORIENT'] = Draw.Create(1) -GLOBALS['DROP_ORIENT_VALUE'] = Draw.Create(100.0) -GLOBALS['EVENT'] = 2 -GLOBALS['MOUSE'] = None - -def collect_terrain_triangles(obs_terrain): - terrain_tris = [] - me = bpy.data.meshes.new() - - for ob in obs_terrain: - def blend_face_to_terrain_tris(f): - no = f.no - cos = [v.co for v in f] - if len(cos) == 4: return [(cos[0], cos[1], cos[2], no), (cos[0], cos[2], cos[3], no)] - else: return [(cos[0], cos[1], cos[2], no), ] - - # Clear - me.verts = None - try: me.getFromObject(ob) - except: pass - - me.transform(ob.matrixWorld) - for f in me.faces: # may be [], thats ok - terrain_tris.extend( blend_face_to_terrain_tris(f) ) - - me.verts = None # clear to save ram - return terrain_tris - -def calc_drop_loc(ob, terrain_tris, axis): - pt = Vector(ob.loc) - - isect = None - isect_best = None - isect_best_no = None - isect_best_len = 0.0 - - for t1,t2,t3, no in terrain_tris: - #if Geometry.PointInTriangle2D(pt, t1,t2,t3): - isect = Mathutils.Intersect(t1, t2, t3, axis, pt, 1) # 1==clip - if isect: - if not GLOBALS['DROP_OVERLAP_CHECK'].val: - # Find the first location - return isect, no - else: - if isect_best: - isect_len = (pt-isect).length - if isect_len < isect_best_len: - isect_best_len = isect_len - isect_best = isect - isect_best_no = no - - else: - isect_best_len = (pt-isect).length - isect_best = isect; - isect_best_no = no - - return isect_best, isect_best_no - - -def error_nogroup(): - Draw.PupMenu('The Group name does not exist') -def error_noact(): - Draw.PupMenu('There is no active object') -def error_noground(): - Draw.PupMenu('No triangles could be found to drop the objects onto') -def error_no_obs(): - Draw.PupMenu('No objects selected to drop') - -# event and value arnt used -def terrain_clamp(event, value): - - sce = bpy.data.scenes.active - if GLOBALS['GROUND_SOURCE'][0].val: - obs_terrain = [sce.objects.active] - if not obs_terrain[0]: - error_noact() - return - else: - try: obs_terrain = bpy.data.groups[ GLOBALS['GROUND_GROUP_NAME'].val ].objects - except: - error_nogroup() - return - - obs_clamp = [ob for ob in sce.objects.context if ob not in obs_terrain and not ob.lib] - if not obs_clamp: - error_no_obs() - return - - terrain_tris = collect_terrain_triangles(obs_terrain) - if not terrain_tris: - error_noground() - return - - - - if GLOBALS['DROP_AXIS'][0].val: - axis = Vector(0,0,-1) - else: - axis = Vector(Window.GetViewVector()) - - do_orient = GLOBALS['DROP_ORIENT'].val - do_orient_val = GLOBALS['DROP_ORIENT_VALUE'].val/100.0 - if not do_orient_val: do_orient = False - - for ob in obs_clamp: - loc, no = calc_drop_loc(ob, terrain_tris, axis) - if loc: - if do_orient: - try: ang = AngleBetweenVecs(no, axis) - except:ang = 0.0 - if ang > 90.0: - no = -no - ang = 180.0-ang - - if ang > 0.0001: - ob_matrix = ob.matrixWorld * RotationMatrix(ang * do_orient_val, 4, 'r', axis.cross(no)) - ob.setMatrix(ob_matrix) - - ob.loc = loc - - # to make the while loop exist - GLOBALS['EVENT'] = EVENT_EXIT - - -# UI STUFF ------------------------ -def do_axis_z(e,v): - GLOBALS['DROP_AXIS'][0].val = 1 - GLOBALS['DROP_AXIS'][1].val = 0 - GLOBALS['EVENT'] = e - -def do_axis_view(e,v): - GLOBALS['DROP_AXIS'][0].val = 0 - GLOBALS['DROP_AXIS'][1].val = 1 - GLOBALS['EVENT'] = e - -def do_ground_source_act(e,v): - GLOBALS['GROUND_SOURCE'][0].val = 1 - GLOBALS['GROUND_SOURCE'][1].val = 0 - GLOBALS['EVENT'] = e - -def do_ground_source_group(e,v): - GLOBALS['GROUND_SOURCE'][0].val = 0 - GLOBALS['GROUND_SOURCE'][1].val = 1 - GLOBALS['EVENT'] = e - -def do_ground_group_name(e,v): - try: g = bpy.data.groups[v] - except: g = None - if not g: error_nogroup() - GLOBALS['EVENT'] = e - -def do_dummy(e,v): - GLOBALS['EVENT'] = e - -EVENT_NONE = 0 -EVENT_EXIT = 1 -EVENT_REDRAW = 2 -def terain_clamp_ui(): - - # Only to center the UI - x,y = GLOBALS['MOUSE'] - x-=40 - y-=70 - - Draw.Label('Drop Axis', x-70,y+120, 60, 20) - Draw.BeginAlign() - GLOBALS['DROP_AXIS'][0] = Draw.Toggle('Z', EVENT_REDRAW, x+20, y+120, 30, 20, GLOBALS['DROP_AXIS'][0].val, 'Drop down on the global Z axis', do_axis_z) - GLOBALS['DROP_AXIS'][1] = Draw.Toggle('View Z', EVENT_REDRAW, x+50, y+120, 70, 20, GLOBALS['DROP_AXIS'][1].val, 'Drop allong the view vector', do_axis_view) - Draw.EndAlign() - - # Source - Draw.Label('Drop on to...', x-70,y+90, 120, 20) - Draw.BeginAlign() - GLOBALS['GROUND_SOURCE'][0] = Draw.Toggle('Active Object', EVENT_REDRAW, x-70, y+70, 110, 20, GLOBALS['GROUND_SOURCE'][0].val, '', do_ground_source_act) - GLOBALS['GROUND_SOURCE'][1] = Draw.Toggle('Group', EVENT_REDRAW, x+40, y+70, 80, 20, GLOBALS['GROUND_SOURCE'][1].val, '', do_ground_source_group) - if GLOBALS['GROUND_SOURCE'][1].val: - GLOBALS['GROUND_GROUP_NAME'] = Draw.String('GR:', EVENT_REDRAW+1001, x-70, y+50, 190, 20, GLOBALS['GROUND_GROUP_NAME'].val, 21, '', do_ground_group_name) - Draw.EndAlign() - - GLOBALS['DROP_OVERLAP_CHECK'] = Draw.Toggle('Overlapping Terrain', EVENT_NONE, x-70, y+20, 190, 20, GLOBALS['DROP_OVERLAP_CHECK'].val, "Check all terrain triangles and use the top most (slow)") - - Draw.BeginAlign() - GLOBALS['DROP_ORIENT'] = Draw.Toggle('Orient Normal', EVENT_REDRAW, x-70, y-10, 110, 20, GLOBALS['DROP_ORIENT'].val, "Rotate objects to the face normal", do_dummy) - if GLOBALS['DROP_ORIENT'].val: - GLOBALS['DROP_ORIENT_VALUE'] = Draw.Number('', EVENT_NONE, x+40, y-10, 80, 20, GLOBALS['DROP_ORIENT_VALUE'].val, 0.0, 100.0, "Percentage to orient 0.0 - 100.0") - Draw.EndAlign() - - Draw.PushButton('Drop Objects', EVENT_EXIT, x+20, y-40, 100, 20, 'Drop the selected objects', terrain_clamp) - - # So moving the mouse outside the popup exits the while loop - GLOBALS['EVENT'] = EVENT_EXIT - -def main(): - - # This is to set the position if the popup - GLOBALS['MOUSE'] = Window.GetMouseCoords() - - # hack so the toggle buttons redraw. this is not nice at all - while GLOBALS['EVENT'] == EVENT_REDRAW: - Draw.UIBlock(terain_clamp_ui, 0) - -if __name__ == '__main__': - main() - -GLOBALS.clear() - diff --git a/release/scripts/object_find.py b/release/scripts/object_find.py deleted file mode 100644 index f12af07e3e4..00000000000 --- a/release/scripts/object_find.py +++ /dev/null @@ -1,222 +0,0 @@ -#!BPY -""" -Name: 'Find by Data Use' -Blender: 242 -Group: 'Object' -Tooltip: 'Find an object by the data it uses' -""" -__author__= "Campbell Barton" -__url__= ["blender.org", "blenderartists.org"] -__version__= "1.0" - -__bpydoc__= """ -""" - -# -------------------------------------------------------------------------- -# Find by Data Use v0.1 by Campbell Barton (AKA Ideasman42) -# -------------------------------------------------------------------------- -# ***** 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 ***** -# -------------------------------------------------------------------------- - -from Blender import Image, sys, Draw, Window, Scene, Group -import bpy -import BPyMessages - - -def get_object_images(ob): - # Could optimize this - if ob.type != 'Mesh': - return [] - - me = ob.getData(mesh=1) - - if not me.faceUV: - return [] - - unique_images = {} - - orig_uvlayer = me.activeUVLayer - - for uvlayer in me.getUVLayerNames(): - me.activeUVLayer = uvlayer - for f in me.faces: - i = f.image - if i: unique_images[i.name] = i - - me.activeUVLayer = orig_uvlayer - - - # Now get material images - for mat in me.materials: - if mat: - for mtex in mat.getTextures(): - if mtex: - tex = mtex.tex - i = tex.getImage() - if i: unique_images[i.name] = i - - return unique_images.values() - - - - # Todo, support other object types, materials - return [] - - - -def main(): - - NAME_DATA= Draw.Create('') - NAME_INGROUP= Draw.Create('') - NAME_DUPGROUP= Draw.Create('') - NAME_IMAGE= Draw.Create('') - NAME_MATERIAL= Draw.Create('') - NAME_TEXTURE= Draw.Create('') - - - PREF_CASESENS= Draw.Create(False) - PREF_PART_MATCH= Draw.Create(True) - - - # Get USER Options - pup_block= [\ - ('ObData:', NAME_DATA, 0, 32, 'Match with the objects data name'),\ - ('InGroup:', NAME_INGROUP, 0, 32, 'Match with the group name to find one of its objects'),\ - ('DupGroup:', NAME_DUPGROUP, 0, 32, 'Match with the group name to find an object that instances this group'),\ - ('Image:', NAME_IMAGE, 0, 32, 'Match with the image name to find an object that uses this image'),\ - ('Material:', NAME_MATERIAL, 0, 32, 'Match with the material name to find an object that uses this material'),\ - ('Texture:', NAME_TEXTURE, 0, 32, 'Match with the texture name to find an object that uses this texture'),\ - ('Case Sensitive', PREF_CASESENS, 'Do a case sensitive comparison?'),\ - ('Partial Match', PREF_PART_MATCH, 'Match when only a part of the text is in the data name'),\ - ] - - if not Draw.PupBlock('Find object using dataname...', pup_block): - return - - NAME_DATA = NAME_DATA.val - NAME_INGROUP = NAME_INGROUP.val - NAME_DUPGROUP = NAME_DUPGROUP.val - NAME_IMAGE = NAME_IMAGE.val - NAME_MATERIAL = NAME_MATERIAL.val - NAME_TEXTURE = NAME_TEXTURE.val - - PREF_CASESENS = PREF_CASESENS.val - PREF_PART_MATCH = PREF_PART_MATCH.val - - if not PREF_CASESENS: - NAME_DATA = NAME_DATA.lower() - NAME_INGROUP = NAME_INGROUP.lower() - NAME_DUPGROUP = NAME_DUPGROUP.lower() - NAME_IMAGE = NAME_IMAGE.lower() - NAME_MATERIAL = NAME_MATERIAL.lower() - NAME_TEXTURE = NAME_TEXTURE.lower() - - def activate(ob, scn): - bpy.data.scenes.active = scn - scn.objects.selected = [] - scn.Layers = ob.Layers & (1<<20)-1 - ob.sel = 1 - - def name_cmp(name_search, name_found): - if name_found == None: return False - if not PREF_CASESENS: name_found = name_found.lower() - if PREF_PART_MATCH: - if name_search in name_found: - # print name_found, name_search - return True - else: - if name_found == name_search: - # print name_found, name_search - return True - - return False - - - if NAME_INGROUP: - # Best we speed this up. - bpy.data.objects.tag = False - - ok = False - for group in bpy.data.groups: - if name_cmp(NAME_INGROUP, group.name): - for ob in group.objects: - ob.tag = True - ok = True - if not ok: - Draw.PupMenu('No Objects Found') - return - - for scn in bpy.data.scenes: - for ob in scn.objects: - if NAME_DATA: - if name_cmp(NAME_DATA, ob.getData(1)): - activate(ob, scn) - return - if NAME_INGROUP: - # Crap and slow but not much we can do about that - ''' - for group in bpy.data.groups: - if name_cmp(NAME_INGROUP, group.name): - for ob_group in group.objects: - if ob == ob_group: - activate(ob, scn) - return - ''' - # Use speedup, this is in a group whos name matches. - if ob.tag: - activate(ob, scn) - return - - if NAME_DUPGROUP: - if ob.DupGroup and name_cmp(NAME_DUPGROUP, ob.DupGroup.name): - activate(ob, scn) - return - - if NAME_IMAGE: - for img in get_object_images(ob): - if name_cmp(NAME_IMAGE, img.name) or name_cmp(NAME_IMAGE, img.filename.split('\\')[-1].split('/')[-1]): - activate(ob, scn) - return - if NAME_MATERIAL or NAME_TEXTURE: - try: materials = ob.getData(mesh=1).materials - except: materials = [] - - # Add object materials - materials.extend(ob.getMaterials()) - - for mat in materials: - if mat: - if NAME_MATERIAL: - if name_cmp(NAME_MATERIAL, mat.name): - activate(ob, scn) - return - if NAME_TEXTURE: - for mtex in mat.getTextures(): - if mtex: - tex = mtex.tex - if tex: - if name_cmp(NAME_TEXTURE, tex.name): - activate(ob, scn) - return - - - Draw.PupMenu('No Objects Found') - -if __name__ == '__main__': - main() diff --git a/release/scripts/object_random_loc_sz_rot.py b/release/scripts/object_random_loc_sz_rot.py deleted file mode 100644 index 1af0dc7218a..00000000000 --- a/release/scripts/object_random_loc_sz_rot.py +++ /dev/null @@ -1,129 +0,0 @@ -#!BPY - -""" -Name: 'Randomize Loc Size Rot' -Blender: 241 -Group: 'Object' -Tooltip: 'Randomize the selected objects Loc Size Rot' -""" - -__bpydoc__=\ -''' -This script randomizes the selected objects location/size/rotation. -''' - -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Script copyright (C) Campbell Barton -# -# 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 ***** -# -------------------------------------------------------------------------- - -''' -30 Jun 07 - ZanQdo: - - Properly coded axis toggles for Loc random (didn't work at all) - - Made Rot input values meaningful (45 will give max 45 degres of rotation) - - Pumped up the Scale value limit - - Made Scale input values meaningful (15 will give max 15 units bigger model) -''' - -from Blender import Draw, Scene -from Blender.Mathutils import Rand - -def rnd(flag): - Random = Rand() - if flag == "LOC": - return (Random - 0.5) * 2 - elif flag == "ROT": - return (Random - 0.5) * 0.035 - elif flag == "SIZE": - return (Random - 0.5) * 1.8 - -def randomize(sel, PREF_LOC, PREF_SIZE, PREF_ROT, PREF_LINK_AXIS, PREF_X_AXIS, PREF_Y_AXIS, PREF_Z_AXIS): - for ob in sel: - if PREF_LOC: - if PREF_LINK_AXIS: - rand = PREF_LOC*rnd("LOC") - ob.loc = (ob.LocX+(rand*PREF_X_AXIS), ob.LocY+(rand*PREF_Y_AXIS), ob.LocZ+(rand*PREF_Z_AXIS)) - else: - if PREF_X_AXIS: x= PREF_LOC*rnd("LOC") - else: x= 0 - if PREF_Y_AXIS: y= PREF_LOC*rnd("LOC") - else: y= 0 - if PREF_Z_AXIS: z= PREF_LOC*rnd("LOC") - else: z= 0 - ob.loc = (ob.LocX+x, ob.LocY+y, ob.LocZ+z) - - if PREF_SIZE: - if PREF_LINK_AXIS: - rand = PREF_SIZE*rnd("SIZE") - if PREF_X_AXIS: x= rand - else: x= 0 - if PREF_Y_AXIS: y= rand - else: y= 0 - if PREF_Z_AXIS: z= rand - else: z= 0 - - else: - if PREF_X_AXIS: x= PREF_SIZE*rnd("SIZE") - else: x= 0 - if PREF_Y_AXIS: y= PREF_SIZE*rnd("SIZE") - else: y= 0 - if PREF_Z_AXIS: z= PREF_SIZE*rnd("SIZE") - else: z= 0 - - ob.size = (abs(ob.SizeX+x), abs(ob.SizeY+y), abs(ob.SizeZ+z)) - - if PREF_ROT: - if PREF_LINK_AXIS: - rand = PREF_ROT*rnd("ROT") - ob.rot = (ob.RotX+rand, ob.RotY+rand, ob.RotZ+rand) - else: - ob.rot = (ob.RotX+(PREF_X_AXIS*PREF_ROT*rnd("ROT")), ob.RotY+(PREF_Y_AXIS*PREF_ROT*rnd("ROT")), ob.RotZ+(PREF_Z_AXIS*PREF_ROT*rnd("ROT"))) - - -def main(): - scn = Scene.GetCurrent() - if not scn.objects.context: - return - - PREF_LOC= Draw.Create(0.0) - PREF_SIZE= Draw.Create(0.0) - PREF_ROT= Draw.Create(0.0) - PREF_LINK_AXIS= Draw.Create(0) - PREF_X_AXIS= Draw.Create(1) - PREF_Y_AXIS= Draw.Create(1) - PREF_Z_AXIS= Draw.Create(1) - - pup_block = [\ - ('loc:', PREF_LOC, 0.0, 100.0, 'Amount to randomize the location'),\ - ('size:', PREF_SIZE, 0.0, 100.0, 'Amount to randomize the size'),\ - ('rot:', PREF_ROT, 0.0, 360.0, 'Amount to randomize the rotation'),\ - '',\ - ('Link Axis', PREF_LINK_AXIS, 'Use the same random value for each objects XYZ'),\ - ('X Axis', PREF_X_AXIS, 'Enable X axis randomization'),\ - ('Y Axis', PREF_Y_AXIS, 'Enable Y axis randomization'),\ - ('Z Axis', PREF_Z_AXIS, 'Enable Z axis randomization'),\ - ] - - if not Draw.PupBlock('Object Randomize', pup_block): - return - - randomize(scn.objects.context, PREF_LOC.val, PREF_SIZE.val, PREF_ROT.val, PREF_LINK_AXIS.val, PREF_X_AXIS.val, PREF_Y_AXIS.val, PREF_Z_AXIS.val) - -if __name__ == '__main__': - main()
\ No newline at end of file diff --git a/release/scripts/object_sel2dupgroup.py b/release/scripts/object_sel2dupgroup.py deleted file mode 100644 index 1b8067e07fb..00000000000 --- a/release/scripts/object_sel2dupgroup.py +++ /dev/null @@ -1,84 +0,0 @@ -#!BPY - -""" -Name: 'Selection to DupliGroup' -Blender: 243 -Group: 'Object' -Tooltip: 'Turn the selection into a dupliGroup using the active objects transformation, objects are moved into a new scene' -""" - -__bpydoc__=\ -''' -''' - -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Script copyright (C) Campbell Barton -# -# 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 ***** -# -------------------------------------------------------------------------- - - -from Blender import * - -def main(): - scn = Scene.GetCurrent() - ob_act = scn.objects.active - - if not ob_act: - Draw.PupMenu('Error%t|No active object') - - dup_name = ob_act.name - - obsel = list(scn.objects.context) - - # Sanity check - for ob in obsel: - parent = ob.parent - if parent: - if not parent.sel or parent not in obsel: - Draw.PupMenu('Error%t|Objects "'+ob.name+'" parent "'+parent.name+'" is not in the selection') - return - - mat_act = ob_act.matrixWorld - - # new group - grp = Group.New(dup_name) - grp.objects = obsel - - # Create the new empty object to be the dupli - ob_dup = scn.objects.new('Empty') - ob_dup.setMatrix(mat_act) - ob_dup.name = dup_name + '_dup' - - ob_dup.enableDupGroup = True - ob_dup.DupGroup = grp - - scn_new = Scene.New(dup_name) - - # Transform the objects to remove the active objects matrix. - mat_act_inv = mat_act.copy().invert() - for ob in obsel: - if not ob.parent: - ob.setMatrix(ob.matrixWorld * mat_act_inv) - - scn_new.objects.link(ob) - scn.objects.unlink(ob) - - -if __name__ == '__main__': - main() diff --git a/release/scripts/object_timeofs_follow_act.py b/release/scripts/object_timeofs_follow_act.py deleted file mode 100644 index 83863da7d8f..00000000000 --- a/release/scripts/object_timeofs_follow_act.py +++ /dev/null @@ -1,107 +0,0 @@ -#!BPY -""" -Name: 'TimeOffset follow Active' -Blender: 245 -Group: 'Object' -Tooltip: 'ActObs animated loc sets TimeOffset on other objects at closest frame' -""" -__author__= "Campbell Barton" -__url__= ["blender.org", "blenderartists.org"] -__version__= "1.0" - -__bpydoc__= """ -""" - -# -------------------------------------------------------------------------- -# TimeOffset follow Active v1.0 by Campbell Barton (AKA Ideasman42) -# -------------------------------------------------------------------------- -# ***** 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 ***** -# -------------------------------------------------------------------------- - -import Blender -from Blender import Image, sys, Draw, Window, Scene, Group -import bpy -import BPyMessages - - -def main(): - - sce = Scene.GetCurrent() - - ob_act = sce.objects.active - - if not ob_act: - Draw.PupMenu("Error%t|no active object") - return - - objects = list(sce.objects.context) - - try: objects.remove(ob_act) - except: pass - - if not objects: - Draw.PupMenu("Error%t|no objects selected") - return - - curframe = Blender.Get('curframe') - - FRAME_START= Draw.Create( Blender.Get('staframe') ) - FRAME_END= Draw.Create( Blender.Get('endframe') ) - - # Get USER Options - pup_block= [\ - ('Start:', FRAME_START, 1, 300000, 'Use the active objects position starting at this frame'),\ - ('End:', FRAME_END, 1, 300000, 'Use the active objects position starting at this frame'),\ - ] - - if not Draw.PupBlock('Set timeoffset...', pup_block): - return - - FRAME_START = FRAME_START.val - FRAME_END = FRAME_END.val - - if FRAME_START >= FRAME_END: - Draw.PupMenu("Error%t|frames are not valid") - - - # Ok - all error checking - locls_act = [] - for f in xrange((FRAME_END-FRAME_START)): - i = FRAME_START+f - Blender.Set('curframe', i) - locls_act.append(ob_act.matrixWorld.translationPart()) - - for ob in objects: - loc = ob.matrixWorld.translationPart() - best_frame = -1 - best_dist = 100000000 - for i, loc_act in enumerate(locls_act): - dist = (loc_act-loc).length - if dist < best_dist: - best_dist = dist - best_frame = i + FRAME_START - - ob.timeOffset = float(best_frame) - - # Set the original frame - Blender.Set('curframe', curframe) - -if __name__ == '__main__': - main() - diff --git a/release/scripts/off_export.py b/release/scripts/off_export.py deleted file mode 100644 index 6aac3ff885b..00000000000 --- a/release/scripts/off_export.py +++ /dev/null @@ -1,106 +0,0 @@ -#!BPY - -""" -Name: 'DEC Object File Format (.off)...' -Blender: 232 -Group: 'Export' -Tooltip: 'Export selected mesh to DEC Object File Format (*.off)' -""" - -__author__ = "Anthony D'Agostino (Scorpius)" -__url__ = ("blender", "blenderartists.org", -"Author's homepage, http://www.redrival.com/scorpius") -__version__ = "Part of IOSuite 0.5" - -__bpydoc__ = """\ -This script exports meshes to DEC Object File Format. - -The DEC (Digital Equipment Corporation) OFF format is very old and -almost identical to Wavefront's OBJ. I wrote this so I could get my huge -meshes into Moonlight Atelier. (DXF can also be used but the file size -is five times larger than OFF!) Blender/Moonlight users might find this -script to be very useful. - -Usage:<br> - Select meshes to be exported and run this script from "File->Export" menu. - -Notes:<br> - Only exports a single selected mesh. -""" - -# $Id: -# -# +---------------------------------------------------------+ -# | Copyright (c) 2002 Anthony D'Agostino | -# | http://www.redrival.com/scorpius | -# | scorpius@netzero.com | -# | February 3, 2001 | -# | Read and write Object File Format (*.off) | -# +---------------------------------------------------------+ - -# ***** 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 ***** - -import Blender -import BPyMessages - -# Python 2.3 has no reversed. -try: - reversed -except: - def reversed(l): return l[::-1] - -# ============================== -# ====== Write OFF Format ====== -# ============================== -def write(filename): - file = open(filename, 'wb') - scn= Blender.Scene.GetCurrent() - object= scn.objects.active - if not object or object.type != 'Mesh': - BPyMessages.Error_NoMeshActive() - return - - Blender.Window.WaitCursor(1) - mesh = object.getData(mesh=1) - - # === OFF Header === - file.write('OFF\n') - file.write('%d %d %d\n' % (len(mesh.verts), len(mesh.faces), 0)) - - # === Vertex List === - for i, v in enumerate(mesh.verts): - file.write('%.6f %.6f %.6f\n' % tuple(v.co)) - - # === Face List === - for i, f in enumerate(mesh.faces): - file.write('%i' % len(f)) - for v in reversed(f.v): - file.write(' %d' % v.index) - file.write('\n') - - file.close() - Blender.Window.WaitCursor(0) - message = 'Successfully exported "%s"' % Blender.sys.basename(filename) - - -def fs_callback(filename): - if not filename.lower().endswith('.off'): filename += '.off' - write(filename) - -Blender.Window.FileSelector(fs_callback, "Export OFF", Blender.sys.makename(ext='.off')) diff --git a/release/scripts/off_import.py b/release/scripts/off_import.py deleted file mode 100644 index e8ab96c51c5..00000000000 --- a/release/scripts/off_import.py +++ /dev/null @@ -1,177 +0,0 @@ -#!BPY - -""" -Name: 'DEC Object File Format (.off)...' -Blender: 242 -Group: 'Import' -Tooltip: 'Import DEC Object File Format (*.off)' -""" - -__author__ = "Anthony D'Agostino (Scorpius), Campbell Barton (Ideasman)" -__url__ = ("blender", "blenderartists.org", -"Author's homepage, http://www.redrival.com/scorpius") -__version__ = "Part of IOSuite 0.5" - -__bpydoc__ = """\ -This script imports DEC Object File Format files to Blender. - -The DEC (Digital Equipment Corporation) OFF format is very old and -almost identical to Wavefront's OBJ. I wrote this so I could get my huge -meshes into Moonlight Atelier. (DXF can also be used but the file size -is five times larger than OFF!) Blender/Moonlight users might find this -script to be very useful. - -Usage:<br> - Execute this script from the "File->Import" menu and choose an OFF file to -open. - -Notes:<br> - UV Coordinate support has been added. - Scorpius - FGON support has been added. - Cam - New Mesh module now used. - Cam -""" - -# $Id: -# -# +---------------------------------------------------------+ -# | Copyright (c) 2002 Anthony D'Agostino | -# | http://www.redrival.com/scorpius | -# | scorpius@netzero.com | -# | February 3, 2001 | -# | Read and write Object File Format (*.off) | -# +---------------------------------------------------------+ - -# ***** 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 ***** - -import Blender - - -# ============================= -# ====== Read OFF Format ====== -# ============================= -def read(filename): - start = Blender.sys.time() - file = open(filename, "rb") - - verts = [] # verts and uvs are aligned - uvs = [] - - faces = [] - - # === OFF Header === - # Skip the comments - offheader= file.readline() - while offheader.startswith('#') or offheader.lower().startswith('off'): - offheader = file.readline() - - numverts, numfaces, numedges= map(int, offheader.split()) - if offheader.find('ST') >= 0: - has_uv = True - Vector= Mathutils.Vector - else: - has_uv = False - - # === Vertex List === - for i in xrange(numverts): - if has_uv: - x, y, z, u, v = map(float, file.readline().split()) - uvs.append(Vector(u, v)) - else: - x, y, z = map(float, file.readline().split()) - verts.append((x, y, z)) - - # === Face List === - def fan_face(face): - # 'Elp, Only fan fill- if were keen we could use our trusty BPyMesh.ngon function - # So far I havnt seen any big ngons in on off file - Cam - return [ (face[0], face[i-1], face[i]) for i in xrange(2,len(face))] - - for i in xrange(numfaces): - line = file.readline().split() # ignore the first value, its just the face count but we can work that out anyway - - # appends all the indicies in reverse order except 0 - # xrange(len(line)-1, -1, -1) # normal reverse loop - # xrange(len(line)-1, 0, -1) # ignoring index 0 because its only a count - # face= [int(line[j]) for j in xrange(len(line)-1, 0, -1)] - - # Some OFF files have floats on the end of the face. what are these for? - face= [int(line[j]) for j in xrange(int(line[0]), 0, -1)] - - - if len(face)>4: - faces.extend( fan_face(face) ) - else: - faces.append(face) - - scn= Blender.Scene.GetCurrent() - name= filename.split('/')[-1].split('\\')[-1].split('.')[0] - me= Blender.Mesh.New(name) - me.verts.extend(verts) - me.faces.extend(faces) - - # Now edges if we have them, render fgon - if numedges: - FGON_FLAG= Blender.Mesh.EdgeFlags.FGON - - edge_dict= {} - # Set all edges to be fgons by default - for ed in me.edges: - ed.flag |= FGON_FLAG - edge_dict[ed.key]= ed - - # Now make known edges visible - has_edges = True - for i in xrange(numedges): - try: - i1,i2= file.readline().split() - except: - has_edges = False - break # some files dont define edges :/ - - i1= int(i1) - i2= int(i2) - if i1>i2: - i1,i2= i2,i1 - - # We know this edge is seen so unset the fgon flag - edge_dict[i1,i2].flag &= ~FGON_FLAG - - if not has_edges: - # dang, we'v turned all the edges into fgons and then the file didnt define any edges. - # oh well, just enable them all - for ed in me.edges: - ed.flag &= ~FGON_FLAG - - # Assign uvs from vert index - if has_uv: - for f in me.faces: - f_uv= f.uv - for i, v in enumerate(f): # same as f.v - f_uv[i]= uvs[v.index] - - for ob in scn.objects: - ob.sel=0 - - scn.objects.active = scn.objects.new(me, name) - Blender.Window.RedrawAll() - print 'Off "%s" imported in %.4f seconds.' % (name, Blender.sys.time()-start) - - -if __name__=='__main__': - Blender.Window.FileSelector(read, 'Import OFF', '*.off') diff --git a/release/scripts/paths_import.py b/release/scripts/paths_import.py deleted file mode 100644 index b35d7fe5c65..00000000000 --- a/release/scripts/paths_import.py +++ /dev/null @@ -1,96 +0,0 @@ -#!BPY -# coding: utf-8 -""" -Name: 'Paths (.svg, .ps, .eps, .ai, Gimp)' -Blender: 233 -Group: 'Import' -Submenu: 'Gimp 1.0 - 1.2.5' Gimp_1_0 -Submenu: 'Gimp 2.0' Gimp_2_0 -Submenu: 'Illustrator (.ai) PS-Adobe-2.0' AI -Submenu: 'InkScape (.svg)' SVG -Submenu: 'Postscript (.eps/.ps) PS-Adobe-2.0' EPS -Tip: 'Import a path from any of a set of formats (still experimental)' -""" - -__author__ = "Jean-Michel Soler (jms)" -__url__ = ("blender", "blenderartists.org", -"AI importer's homepage, http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_import_ai.htm", -"Communicate problems and errors, http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender") -__version__ = "0.1.1" - -__bpydoc__ = """\ -Paths Import imports paths from a selection of different formats: - -- Gimp 1.0 -> 1.2.5;<br> -- Gimp 2.0;<br> -- AI PS-Adobe 2.0;<br> -- Inkscape (svg);<br> -- Postscript (ps/eps) - -Usage: - Run the script from "File->Import", select the desired format from the -pop-up menu and select the file to open. - -Notes:<br> - If the imported curve looks "messy", you may need to enter edit mode with the imported curve selected and toggle cyclic mode for it, by selecting all its points and pressing "c" or using the Curve menu in the 3d view header. -""" - -#---------------------------------------------- -# (c) jm soler juillet 2004, released under GPL -# for the Blender 2.45 Python Scripts Bundle. -#---------------------------------------------- -""" -Ce programme est libre, vous pouvez le redistribuer et/ou -le modifier selon les termes de la Licence Publique Générale GNU -publiée par la Free Software Foundation (version 2 ou bien toute -autre version ultérieure choisie par vous). - -Ce programme est distribué car potentiellement utile, mais SANS -AUCUNE GARANTIE, ni explicite ni implicite, y compris les garanties -de commercialisation ou d'adaptation dans un but spécifique. -Reportez-vous à la Licence Publique Générale GNU pour plus de détails. - -Vous devez avoir reçu une copie de la Licence Publique Générale GNU -en même temps que ce programme ; si ce n'est pas le cas, écrivez à la -Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, -MA 02111-1307, États-Unis. - - -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 St, Fifth Floor, Boston, MA 02110-1301 USA -""" -import Blender - -argv=__script__['arg'] - -if argv=='SVG': - from paths_svg2obj import * - fonctionSELECT = functionSELECT # can they all be called function? - -elif argv=='AI': - from paths_ai2obj import * - -elif argv=='EPS': - from paths_eps2obj import * - -elif argv=='Gimp_1_0': - from paths_gimp2obj import * - -elif argv=='Gimp_2_0': - from paths_svg2obj import * - fonctionSELECT = functionSELECT # can they all be called function? - -text = 'Import %s' % argv -Blender.Window.FileSelector (fonctionSELECT, text) - diff --git a/release/scripts/ply_import.py b/release/scripts/ply_import.py deleted file mode 100644 index 29e8ce48361..00000000000 --- a/release/scripts/ply_import.py +++ /dev/null @@ -1,354 +0,0 @@ -#!BPY - -""" -Name: 'Stanford PLY (*.ply)...' -Blender: 248 -Group: 'Import' -Tip: 'Import a Stanford PLY file' -""" - -__author__ = 'Bruce Merry' -__version__ = '0.93' -__bpydoc__ = """\ -This script imports Stanford PLY files into Blender. It supports per-vertex -normals, and per-face colours and texture coordinates. - -Usage: - -Run this script from "File->Import" and select the desired PLY file. -""" - -# Copyright (C) 2004, 2005: Bruce Merry, bmerry@cs.uct.ac.za -# -# 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. - - -# 20th Oct 2008, 0.93 - Updated by Campbell Barton AKA ideasman42, use Mesh rather then NMesh, dont import normals, vcolors work again. -# Updated by Campbell Barton AKA Ideasman42, 10% faster code. - -# Portions of this code are taken from mod_meshtools.py in Blender -# 2.32. - -import Blender -try: - import re, struct -except: - struct= None - -class element_spec(object): - __slots__ = 'name', 'count', 'properties' - def __init__(self, name, count): - self.name = name - self.count = count - self.properties = [] - - def load(self, format, stream): - if format == 'ascii': - stream = re.split('\s+', stream.readline()) - return map(lambda x: x.load(format, stream), self.properties) - - def index(self, name): - for i, p in enumerate(self.properties): - if p.name == name: return i - return -1 - -class property_spec(object): - __slots__ = 'name', 'list_type', 'numeric_type' - def __init__(self, name, list_type, numeric_type): - self.name = name - self.list_type = list_type - self.numeric_type = numeric_type - - def read_format(self, format, count, num_type, stream): - if format == 'ascii': - if (num_type == 's'): - ans = [] - for i in xrange(count): - s = stream[i] - if len(s) < 2 or s[0] != '"' or s[-1] != '"': - print 'Invalid string', s - print 'Note: ply_import.py does not handle whitespace in strings' - return None - ans.append(s[1:-1]) - stream[:count] = [] - return ans - if (num_type == 'f' or num_type == 'd'): - mapper = float - else: - mapper = int - ans = map(lambda x: mapper(x), stream[:count]) - stream[:count] = [] - return ans - else: - if (num_type == 's'): - ans = [] - for i in xrange(count): - fmt = format + 'i' - data = stream.read(struct.calcsize(fmt)) - length = struct.unpack(fmt, data)[0] - fmt = '%s%is' % (format, length) - data = stream.read(struct.calcsize(fmt)) - s = struct.unpack(fmt, data)[0] - ans.append(s[:-1]) # strip the NULL - return ans - else: - fmt = '%s%i%s' % (format, count, num_type) - data = stream.read(struct.calcsize(fmt)); - return struct.unpack(fmt, data) - - def load(self, format, stream): - if (self.list_type != None): - count = int(self.read_format(format, 1, self.list_type, stream)[0]) - return self.read_format(format, count, self.numeric_type, stream) - else: - return self.read_format(format, 1, self.numeric_type, stream)[0] - -class object_spec(object): - __slots__ = 'specs' - 'A list of element_specs' - def __init__(self): - self.specs = [] - - def load(self, format, stream): - return dict([(i.name,[i.load(format, stream) for j in xrange(i.count) ]) for i in self.specs]) - - ''' - # Longhand for above LC - answer = {} - for i in self.specs: - answer[i.name] = [] - for j in xrange(i.count): - if not j % 100 and meshtools.show_progress: - Blender.Window.DrawProgressBar(float(j) / i.count, 'Loading ' + i.name) - answer[i.name].append(i.load(format, stream)) - return answer - ''' - - -def read(filename): - format = '' - version = '1.0' - format_specs = {'binary_little_endian': '<', - 'binary_big_endian': '>', - 'ascii': 'ascii'} - type_specs = {'char': 'b', - 'uchar': 'B', - 'int8': 'b', - 'uint8': 'B', - 'int16': 'h', - 'uint16': 'H', - 'ushort': 'H', - 'int': 'i', - 'int32': 'i', - 'uint': 'I', - 'uint32': 'I', - 'float': 'f', - 'float32': 'f', - 'float64': 'd', - 'double': 'd', - 'string': 's'} - obj_spec = object_spec() - - try: - file = open(filename, 'rU') # Only for parsing the header, not binary data - signature = file.readline() - - if not signature.startswith('ply'): - print 'Signature line was invalid' - return None - - while 1: - tokens = re.split(r'[ \n]+', file.readline()) - - if (len(tokens) == 0): - continue - if (tokens[0] == 'end_header'): - break - elif (tokens[0] == 'comment' or tokens[0] == 'obj_info'): - continue - elif (tokens[0] == 'format'): - if (len(tokens) < 3): - print 'Invalid format line' - return None - if (tokens[1] not in format_specs): # .keys()): # keys is implicit - print 'Unknown format', tokens[1] - return None - if (tokens[2] != version): - print 'Unknown version', tokens[2] - return None - format = tokens[1] - elif (tokens[0] == 'element'): - if (len(tokens) < 3): - print 'Invalid element line' - return None - obj_spec.specs.append(element_spec(tokens[1], int(tokens[2]))) - elif (tokens[0] == 'property'): - if (not len(obj_spec.specs)): - print 'Property without element' - return None - if (tokens[1] == 'list'): - obj_spec.specs[-1].properties.append(property_spec(tokens[4], type_specs[tokens[2]], type_specs[tokens[3]])) - else: - obj_spec.specs[-1].properties.append(property_spec(tokens[2], None, type_specs[tokens[1]])) - - if format != 'ascii': - file.close() # was ascii, now binary - file = open(filename, 'rb') - - # skip the header... - while not file.readline().startswith('end_header'): - pass - - obj = obj_spec.load(format_specs[format], file) - - except IOError, (errno, strerror): - try: file.close() - except: pass - - return None - try: file.close() - except: pass - - return (obj_spec, obj); - -def load_ply(filename): - t = Blender.sys.time() - obj_spec, obj = read(filename) - if obj == None: - print 'Invalid file' - return - - uvindices = colindices = None - # noindices = None # Ignore normals - - for el in obj_spec.specs: - if el.name == 'vertex': - vindices = vindices_x, vindices_y, vindices_z = (el.index('x'), el.index('y'), el.index('z')) - # noindices = (el.index('nx'), el.index('ny'), el.index('nz')) - # if -1 in noindices: noindices = None - uvindices = (el.index('s'), el.index('t')) - if -1 in uvindices: uvindices = None - colindices = (el.index('red'), el.index('green'), el.index('blue')) - if -1 in colindices: colindices = None - elif el.name == 'face': - findex = el.index('vertex_indices') - - mesh_faces = [] - mesh_uvs = [] - mesh_colors = [] - - def add_face(vertices, indices, uvindices, colindices): - mesh_faces.append(indices) - if uvindices: mesh_uvs.append([ (vertices[index][uvindices[0]], 1.0 - vertices[index][uvindices[1]]) for index in indices]) - if colindices: mesh_colors.append([ (vertices[index][colindices[0]], vertices[index][colindices[1]], vertices[index][colindices[2]]) for index in indices]) - - - if uvindices or colindices: - # If we have Cols or UVs then we need to check the face order. - add_face_simple = add_face - - # EVIL EEKADOODLE - face order annoyance. - def add_face(vertices, indices, uvindices, colindices): - if len(indices)==4: - if indices[2]==0 or indices[3]==0: - indices= indices[2], indices[3], indices[0], indices[1] - elif len(indices)==3: - if indices[2]==0: - indices= indices[1], indices[2], indices[0] - - add_face_simple(vertices, indices, uvindices, colindices) - - verts = obj['vertex'] - - if 'face' in obj: - for f in obj['face']: - ind = f[findex] - len_ind = len(ind) - if len_ind <= 4: - add_face(verts, ind, uvindices, colindices) - else: - # Fan fill the face - for j in xrange(len_ind - 2): - add_face(verts, (ind[0], ind[j + 1], ind[j + 2]), uvindices, colindices) - - mesh = Blender.Mesh.New() - - mesh.verts.extend([(v[vindices_x], v[vindices_y], v[vindices_z]) for v in obj['vertex']]) - - if mesh_faces: - mesh.faces.extend(mesh_faces, smooth=True, ignoreDups=True) - - if uvindices or colindices: - if uvindices: mesh.faceUV = True - if colindices: mesh.vertexColors = True - - for i, f in enumerate(mesh.faces): - if uvindices: - ply_uv = mesh_uvs[i] - for j, uv in enumerate(f.uv): - uv[:] = ply_uv[j] - - if colindices: - ply_col = mesh_colors[i] - for j, col in enumerate(f.col): - col.r, col.g, col.b = ply_col[j] - - mesh.calcNormals() - - - objname = Blender.sys.splitext(Blender.sys.basename(filename))[0] - scn= Blender.Scene.GetCurrent() - scn.objects.selected = [] - - mesh.name= objname - scn.objects.active = scn.objects.new(mesh) - - Blender.Redraw() - Blender.Window.DrawProgressBar(1.0, '') - print '\nSuccessfully imported "%s" in %.3f sec' % (filename, Blender.sys.time()-t) - -def main(): - if not struct: - msg = 'This importer requires a full python install' - if Blender.mode == 'background': print msg - else: Blender.Draw.PupMenu(msg) - return - - Blender.Window.FileSelector(load_ply, 'Import PLY', '*.ply') - -if __name__=='__main__': - main() - -''' -import bpy -import os -files = os.popen('find /fe/ply -iname "*.ply"').readlines() - - -files.sort() -tot = len(files) -for i, f in enumerate(files): - if i < 26 or i > 1000000: - continue - #if i != 12686: - # continue - - f = f.strip() - print f, i, tot - sce = bpy.data.scenes.new(f.split('/')[-1]) - bpy.data.scenes.active = sce - # Window. - load_ply(f) -'''
\ No newline at end of file diff --git a/release/scripts/raw_export.py b/release/scripts/raw_export.py deleted file mode 100644 index e3c588cac10..00000000000 --- a/release/scripts/raw_export.py +++ /dev/null @@ -1,100 +0,0 @@ -#!BPY - -""" -Name: 'Raw Faces (.raw)...' -Blender: 245 -Group: 'Export' -Tooltip: 'Export selected mesh to Raw Format (.raw)' -""" - -__author__ = "Anthony D'Agostino (Scorpius)" -__url__ = ("blender", "blenderartists.org", -"Author's homepage, http://www.redrival.com/scorpius") -__version__ = "Part of IOSuite 0.5" - -__bpydoc__ = """\ -This script exports meshes to Raw file format. - -The raw triangle format is very simple; it has no verts or faces lists. -It's just a simple ascii text file with the vertices of each triangle or quad -listed on each line. There were some very old utilities (when the PovRay -forum was in existence on CompuServe) that preformed operations on these -files. - -Usage:<br> - Select meshes to be exported and run this script from "File->Export" menu. -""" - -# $Id$ -# -# +---------------------------------------------------------+ -# | Copyright (c) 2002 Anthony D'Agostino | -# | http://www.redrival.com/scorpius | -# | scorpius@netzero.com | -# | April 28, 2002 | -# | Read and write RAW Triangle File Format (*.raw) | -# +---------------------------------------------------------+ - -# ***** 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 ***** - -import Blender -import BPyMesh - -# ================================= -# === Write RAW Triangle Format === -# ================================= -def write(filename): - start = Blender.sys.time() - if not filename.lower().endswith('.raw'): - filename += '.raw' - - scn= Blender.Scene.GetCurrent() - ob= scn.objects.active - if not ob: - Blender.Draw.PupMenu('Error%t|Select 1 active object') - return - - file = open(filename, 'wb') - - mesh = BPyMesh.getMeshFromObject(ob, None, True, False, scn) - if not mesh: - Blender.Draw.PupMenu('Error%t|Could not get mesh data from active object') - return - - mesh.transform(ob.matrixWorld) - - - file = open(filename, "wb") - for f in mesh.faces: - for v in f: - file.write('%.6f %.6f %.6f ' % tuple(v.co)) - file.write('\n') - file.close() - - end = Blender.sys.time() - message = 'Successfully exported "%s" in %.4f seconds' % ( Blender.sys.basename(filename), end-start) - print message - - -def main(): - Blender.Window.FileSelector(write, 'RAW Export', Blender.sys.makename(ext='.raw')) - - -if __name__=='__main__': - main() diff --git a/release/scripts/raw_import.py b/release/scripts/raw_import.py deleted file mode 100644 index 76c03c77337..00000000000 --- a/release/scripts/raw_import.py +++ /dev/null @@ -1,120 +0,0 @@ -#!BPY - -""" -Name: 'Raw Faces (.raw)...' -Blender: 242 -Group: 'Import' -Tooltip: 'Import Raw Triangle File Format (.raw)' -""" - -__author__ = "Anthony D'Agostino (Scorpius)" -__url__ = ("blender", "blenderartists.org", -"Author's homepage, http://www.redrival.com/scorpius") -__version__ = "Part of IOSuite 0.5" - -__bpydoc__ = """\ -This script imports Raw Triangle File format files to Blender. - -The raw triangle format is very simple; it has no verts or faces lists. -It's just a simple ascii text file with the vertices of each triangle -listed on each line. There were some very old utilities (when the PovRay -forum was in existence on CompuServe) that preformed operations on these -files. - -Usage:<br> - Execute this script from the "File->Import" menu and choose a Raw file to -open. - -Notes:<br> - Generates the standard verts and faces lists, but without duplicate -verts. Only *exact* duplicates are removed, there is no way to specify a -tolerance. -""" - -# $Id$ -# -# +---------------------------------------------------------+ -# | Copyright (c) 2002 Anthony D'Agostino | -# | http://www.redrival.com/scorpius | -# | scorpius@netzero.com | -# | April 28, 2002 | -# | Read and write RAW Triangle File Format (*.raw) | -# +---------------------------------------------------------+ - -# ***** 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 ***** - -import Blender - -# ================================ -# === Read RAW Triangle Format === -# ================================ -def read(filename): - t = Blender.sys.time() - file = open(filename, "rb") - - # Collect data from RAW format - def line_to_face(line): - # Each triplet is an xyz float - line_split= map(float, line.split()) - if len(line_split)==9: # Tri - f1, f2, f3, f4, f5, f6, f7, f8, f9 = line_split - return [(f1, f2, f3), (f4, f5, f6), (f7, f8, f9)] - if len(line_split)==12: # Quad - f1, f2, f3, f4, f5, f6, f7, f8, f9, A, B, C = line_split - return [(f1, f2, f3), (f4, f5, f6), (f7, f8, f9), (A, B, C)] - - faces = [ line_to_face(line) for line in file.readlines()] - file.close() - - # Generate verts and faces lists, without duplicates - verts = [] - coords = {} - index = 0 - - for f in faces: - if f: # Line might be blank - for i, v in enumerate(f): - try: - f[i]= coords[v] - except: - f[i]= coords[v] = index - index += 1 - verts.append(v) - - me= Blender.Mesh.New() - me.verts.extend(verts) - me.faces.extend(faces) - - - scn= Blender.Scene.GetCurrent() - for obj in scn.objects: - obj.sel= 0 - - me.name= Blender.sys.splitext(Blender.sys.basename(filename))[0] - ob = scn.objects.new(me) - Blender.Redraw() - - print 'Successfully imported "%s" in %.4f seconds' % (Blender.sys.basename(filename), Blender.sys.time()-t) - - -def main(): - Blender.Window.FileSelector(read, 'RAW Import', Blender.sys.makename(ext='.raw')) - -if __name__=='__main__': - main() diff --git a/release/scripts/renameobjectbyblock.py b/release/scripts/renameobjectbyblock.py deleted file mode 100644 index eeea815c650..00000000000 --- a/release/scripts/renameobjectbyblock.py +++ /dev/null @@ -1,178 +0,0 @@ -#!BPY - -""" Registration info for Blender menus: <- these words are ignored -Name: 'Object Name Editor' -Blender: 232 -Group: 'Object' -Tip: 'GUI to select and rename objects.' -""" - -__author__ = "Jean-Michel Soler (jms)" -__url__ = ("blender", "blenderartists.org", -"Script's homepage, http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_renameobjectgui.htm", -"Communicate problems and errors, http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender") -__version__ = "233" - -__bpydoc__ = """\ -This script offers a GUI to rename selected objects according to a given -rule. - -Usage: - -Open it from the 3d View's "Object->Scripts" menu and select the objects to -rename and the rule from the buttons in its GUI. -""" - -# ---------------------------------------------------------- -# Name OBJECT changer -# (c) 2004 jean-michel soler -# ----------------------------------------------------------- -#---------------------------------------------- -# Page officielle/offcial page du blender python Name OBJECT changer: -# http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_renameobjectgui.htm -# Communiquer les problemes et erreurs sur: -# To Communicate problems and errors on: -# http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender -#--------------------------------------------- -# Blender Artistic License -# http://download.blender.org/documentation/html/x21254.html -#--------------------------------------------- - -CVS=0 - -import Blender -from Blender import * -from Blender.Draw import * -from Blender.BGL import * - - - -O = list(Scene.GetCurrent().objects) -stringlist=[[],[]] - - -def renew(): - global O - - #O = Object.Get() - O = list(Scene.GetCurrent().objects) - #param= [ [p.name, i, p.getType()] for i, p in enumerate(O) ] - - PARAM={} - evt=9 - stringlist=[[],[],[]] - for i, ob in enumerate(O): - obname= ob.name - PARAM[obname] = [Create(ob.sel), evt, i, ob.getType(), Create(obname), evt+1, ob] - - stringlist[0].append(evt+1) - stringlist[1].append(obname) - stringlist[2].append(evt) - evt+=2 - return PARAM,stringlist - -NEWNAME=Create('Name') - -alignment={'BEGIN' : [Create(1),5], - 'END' : [Create(0),6], - 'POINT' : [Create(0),7], - 'FULL' : [Create(0),8]} - -def rename(): - global NEWNAME, alignment, O, PARAM, stringlist - newname= NEWNAME.val - for obname, value in PARAM.iteritems(): - if value[0].val: # Selected - if alignment['END'][0].val: - value[6].setName(obname+newname) - elif alignment['BEGIN'][0].val: - value[6].setName(newname+obname) - elif alignment['FULL'][0].val: - value[6].setName(newname) - PARAM, stringlist = renew() - -PARAM, stringlist = renew() - -def EVENT(evt,val): - pass - -def BUTTON(evt): - global PARAM , alignment, O, stringlist, CVS - if (evt==1): - Exit() - elif (evt==2): - rename() - elif (evt==3): - PARAM, stringlist = renew() - - elif (evt in [5,6,7,8]): - for k in alignment.iterkeys(): - if alignment[k][1]!=evt: - alignment[k][0].val=0 - - - elif (evt in stringlist[0]): - O[PARAM[stringlist[1][(evt-9)/2]][2]].setName(PARAM[stringlist[1][(evt-9)/2]][4].val) - PARAM, stringlist = renew() - - elif (evt in stringlist[2]): - try: - O[PARAM[stringlist[1][(evt-9)/2]][2]].select(PARAM[stringlist[1][(evt-9)/2]][0].val) - except: - pass - - Blender.Redraw() - -def DRAW(): - global PARAM, O, NEWNAME, alignment - - - #glColor3f(0.7, 0.7, 0.7) - glClear(GL_COLOR_BUFFER_BIT) - glColor3f(0.1, 0.1, 0.15) - - size=Buffer(GL_FLOAT, 4) - glGetFloatv(GL_SCISSOR_BOX, size) - size= size.list - for s in [0,1,2,3]: size[s]=int(size[s]) - ligne=20 - - Button ("Exit",1,20,1,80,ligne) - Button ("Rename",2,102,1,80,ligne) - Button ("Renew",3,184,1,80,ligne) - - glRasterPos2f(20, ligne*2-10) - Text("Object Name Editor") - NEWNAME=String('Add String: ', 4, 150, ligne*2-16, 150, 18, NEWNAME.val,120 ) - - key= alignment.keys() - key.sort() - n=150+150+4 - for k in key: - alignment[k][0]= Toggle(k,alignment[k][1],n,ligne*2-16, 40, 18, alignment[k][0].val) - n+=40+4 - - max=size[3] / 22 -2 - pos = 0 - decal = 20 - - keys=[[PARAM[k][1],k] for k in PARAM.iterkeys()] - keys.sort() - - - for p_ in keys: - p=p_[1] - if pos==max: - decal+=152 - pos=1 - else: - pos+=1 - PARAM[p][0]=Toggle('S',PARAM[p][1],decal,pos*22+22,20,20, PARAM[p][0].val,"Select this one for a group renaming") - PARAM[p][4]=String('',PARAM[p][5],decal+20,pos*22+22,90,20, PARAM[p][4].val,200, "string button to rename immediately but only this object") - - glRasterPos2f(decal+115,pos*22+24) - Text(PARAM[p][3][:4]) - -if __name__=='__main__': - Register(DRAW,EVENT,BUTTON) - diff --git a/release/scripts/render_save_layers.py b/release/scripts/render_save_layers.py deleted file mode 100644 index c91fcce7948..00000000000 --- a/release/scripts/render_save_layers.py +++ /dev/null @@ -1,120 +0,0 @@ -#!BPY - -""" -Name: 'Save Render Layers...' -Blender: 245 -Group: 'Render' -Tooltip: 'Save current renderlayers as a BPython script' -""" - -__author__ = "Campbell Barton" -__url__ = ("blender", "blenderartists.org") -__version__ = "1.0" - -__bpydoc__ = """\ -""" - -# -------------------------------------------------------------------------- -# The scripts generated by this script are put under Public Domain by -# default, but you are free to edit the ones you generate with this script -# and change their license to another one of your choice. -# -------------------------------------------------------------------------- -# ***** 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 ***** -# -------------------------------------------------------------------------- - -import Blender -from Blender.Window import Theme, FileSelector -from Blender import Scene - -sce = Scene.GetCurrent() -rend = sce.render - -# default filename: filename + scenename + '_renderlayer.py' in user's scripts dir: -default_fname = Blender.Get("scriptsdir") -if not default_fname: - default_fname = Blender.Get("uscriptsdir") - -if default_fname: - default_fname = Blender.sys.join(default_fname, sce.name + '_renderlayer.py') - default_fname = default_fname.replace(' ','_') - -def write_renderlayers(filename): - "Write the current renderlayer as a bpython script" - - if not filename.endswith('.py'): filename += '.py' - - fout = file(filename, "w") - - fout.write("""#!BPY - -# \"\"\" -# Name: '%s' -# Blender: 245 -# Group: 'Render' -# Tooltip: '' -# \"\"\" - -__%s__ = "????" -__%s__ = "2.43" -__%s__ = ["blender"] -__%s__ = \"\"\"\\ -You can edit this section to write something about your script that can -be read then with the Scripts Help Browser script in Blender. - -Remember to also set author, version and possibly url(s) above. You can also -define an __email__ tag, check some bundled script's source for examples. -\"\"\" - -# This script was automatically generated by the render_save_layers.py bpython script. -# By default, these generated scripts are released as Public Domain, but you -# are free to change the license of the scripts you generate with -# render_save_layers.py before releasing them. - -import Blender -from Blender import Scene - -sce = Scene.GetCurrent() -rend = sce.render -""" % (sce.name, "author", "version", "url", "bpydoc")) - - for lay in rend.renderLayers: # - fout.write("\nlay = rend.addRenderLayer()\n") - fout.write("lay.name = \"%s\"\n" % lay.name) - - exec("vars = dir(lay)") - - for var in vars: - if var.startswith('_'): - continue - - v = "lay.%s" % var - exec("value = %s" % v) - if type(value) == str: - fout.write("%s = '%s'\n" % (v, value)) - else: - fout.write("%s = %s\n" % (v, value)) - - fout.write('\nBlender.Redraw(-1)') - fout.close() - try: - Blender.UpdateMenus() - except: - Blender.Draw.PupMenu("Warning - check console!%t|Menus could not be automatically updated") - -FileSelector(write_renderlayers, "Save RenderLayers", default_fname) diff --git a/release/scripts/rvk1_torvk2.py b/release/scripts/rvk1_torvk2.py deleted file mode 100644 index d013343c05c..00000000000 --- a/release/scripts/rvk1_torvk2.py +++ /dev/null @@ -1,341 +0,0 @@ -#!BPY -# coding: utf-8 -""" Registration info for Blender menus: <- these words are ignored -Name: 'Deformed mesh to Rvk' -Blender: 248 -Group: 'Mesh' -Tip: 'Copy deform data (not surf. subdiv) of active obj to rvk of the 2nd selected obj' -""" - -__author__ = "Jean-Michel Soler (jms)" -__url__ = ("blender", "blenderartists.org", -"Script's homepage, http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_rvk1versrvk2.htm", -"Communicate problems and errors, http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender") -__version__ = "2009/05/18" - -__bpydoc__ = """\ -"DEFORM to RVK2" copies deformed data (except all data with not exactly -the same number of vertices like EDGESPLIT,DECIMATE,SUBSURF, BOOLEAN, -BUILD, MIRROR, ARRAY) of the active object to the RVK (relative vertex -key, now called Shapes key) of the other selected object. - -It is presupposed that the second mesh object is built exactly like the first -one. In fact, it is better to use a true copy with at least one basic shape -key. If there is no other object selected, the script can create a copy. - -The new version of this scrit (Blender 2.43) manages the modifier changes. -There are a lot of modifiers but only the ones which just deforms the shape -can be used : LATTICE, CURVE, WAVE, ARMATURE, CAST, DISPLACE, SMOOTH. -SIMPLEDEFORM and SHRINKWRAP are not correctly seen before Blender 2.49, but -they can be copied too. You can unset one or more of these modifiers from -the script. - -Usage: - -Select the object that will receive the rvk info, then select the deformed -object, enter Edit Mode and run this script from the "Mesh->Scripts" menu of -the 3d View. If the active object has subsurf turned on and nonzero subdiv -level, the script will ask if it should change that. Before copying data to -the rvk it will also ask whether it should replace or add a new vertex group. - - -""" -#---------------------------------------------- -# jm soler (c) 2004-2009 : 'Deformed mesh to Rvk' -# released under GPL licence -#---------------------------------------------- -""" -Ce programme est libre, vous pouvez le redistribuer et/ou -le modifier selon les termes de la Licence Publique Générale GNU -publiée par la Free Software Foundation (version 2 ou bien toute -autre version ultérieure choisie par vous). - -Ce programme est distribué car potentiellement utile, mais SANS -AUCUNE GARANTIE, ni explicite ni implicite, y compris les garanties -de commercialisation ou d'adaptation dans un but spécifique. -Reportez-vous à la Licence Publique Générale GNU pour plus de détails. - -Vous devez avoir reçu une copie de la Licence Publique Générale GNU -en même temps que ce programme ; si ce n'est pas le cas, écrivez à la -Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, -MA 02111-1307, États-Unis. - - -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 St, Fifth Floor, Boston, MA 02110-1301 USA -""" -#---------------------------------------------- -# official Page : -# http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_rvk1versrvk2.htm -# download the script : -# http://jmsoler.free.fr/util/blenderfile/py/rvk1_torvk2.py -# Communicate upon problems or errors: -# http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender -#---------------------------------------------- -# Page officielle : -# http://jmsoler.free.fr/util/blenderfile/py/rvk1_torvk2.py -# Communiquer les problemes et erreurs sur: -# http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender -#--------------------------------------------- - -import Blender -from Blender import NMesh,Draw,Object,Modifier - -DEBUG=0 - -def Value(t): - exec "t=Modifier.Types.%s"%t - return t - -def copy_shapes(RVK1,RVK2): - POSSMOD_list=['EDGESPLIT', - 'DECIMATE', - 'SUBSURF', - 'BOOLEAN', - 'BUILD', - 'MIRROR', - 'ARRAY', - 'BEVEL', - 'EXPLODE'] - - AUTHMOD_list=['LATTICE', - 'CURVE', - 'WAVE', - 'ARMATURE', - 'SMOOTH', - 'SIMPLEDEFORM', - 'SHRINKWRAP', - 'CAST', - 'DISPLACE', - 'MESHDEFORM'] - - - BMOD=[['Possible Modifiers'], - ['Allowed Modifiers']] - # ============================================================= - # must be 2 meshes ============================================ - # ============================================================= - if RVK1.getType()=='Mesh' and RVK2.getType()=='Mesh': - #MODIFIERS=0 - FRAME=Blender.Get('curframe') - DATA2=RVK2.getData() - if DEBUG: print DATA2.getKey() - # ============================================================ - # at least the second must have a shape key ================== - # ============================================================ - def select_modifier(RVK1, RVK2, DATA2): - # ====================================================== - # in case of modifiers, use ============================= - # ====================================================== - if RVK1.modifiers: - #MODIFIERS=1 - POSSMOD=[Value(t) for t in POSSMOD_list] - AUTHMOD=[Value(t) for t in AUTHMOD_list] - if DEBUG: print 'POSSMOD:',POSSMOD,'\nAUTHMOD:', AUTHMOD - MODRVK1=RVK1.modifiers - block = [] - # =================================================== - # === Bloc Menu Modifiers ===1 doc ================= - # =================================================== - m=0 - for mod in MODRVK1: - if DEBUG: print mod.type - if mod.type in POSSMOD: - BMOD[0].append([Draw.Create(0),mod.type, - m, - POSSMOD_list[POSSMOD.index(mod.type)], - mod[Modifier.Settings.RENDER]==1, - mod[Modifier.Settings.EDITMODE]==1 - ]) - elif mod.type in AUTHMOD: - BMOD[1].append([Draw.Create(1), - mod.type, - m, - AUTHMOD_list[AUTHMOD.index(mod.type)], - mod[Modifier.Settings.RENDER]==1, - mod[Modifier.Settings.EDITMODE]==1 - ]) - m+=1 - # =================================================== - # === Bloc Menu Modifiers ===2 display ============= - # =================================================== - block.append(BMOD[1][0]) - for B in BMOD[1][1:]: - block.append((B[3],B[0],"")) - block.append(BMOD[0][0]) - block.append("not alredy implemented") - block.append("in this script.") - for B in BMOD[0][1:]: - block.append((B[3],B[0],"")) - retval = Blender.Draw.PupBlock("MESH 2 RVK", block) - # =================================================== - # === unset Modifiers ============================= - # =================================================== - for B in BMOD[0][1:]: - if DEBUG: print B[2] - MODRVK1[B[2]][Modifier.Settings.RENDER]=0 - for B in BMOD[1]: - if not B[1]: - MODRVK1[B[2]][Modifier.Settings.RENDER]=0 - # =================================================== - # === update Modifiers ============================= - # =================================================== - #RVK1.makeDisplayList() - # ======================================================= - # === get deformed mesh ================================ - # ======================================================= - RVK1NAME=Object.GetSelected()[0].getName() - meshrvk1=NMesh.GetRawFromObject(RVK1NAME) - if DEBUG: print len(meshrvk1.verts) - # ======================================================= - # === get normal mesh for vertex group ================= - # ======================================================= - DATA1=RVK1.getData() - # ======================================================= - # === get destination mesh ============================ - # ======================================================= - DATA2=RVK2.getData() - if DEBUG: print len(meshrvk1.verts) - if DEBUG: print len(DATA2.verts) - # ======================================================== - # ===== is there the same number of vertices ============= - # ======================================================== - if len(meshrvk1.verts)==len(DATA2.verts): - name = "Do you want to replace or add vertex groups ? %t| YES %x1| NO ? %x2 " - result = Draw.PupMenu(name) - if result==1: - # ===================================================== - # ===== Do we save vertex groups ? =================== - # ===================================================== - GROUPNAME2=DATA2.getVertGroupNames() - if len(GROUPNAME2)!=0: - for GROUP2 in GROUPNAME2: - DATA2.removeVertGroup(GROUP2) - GROUPNAME1=DATA1.getVertGroupNames() - if len(GROUPNAME1)!=0: - for GROUP1 in GROUPNAME1: - DATA2.addVertGroup(GROUP1) - DATA2.assignVertsToGroup(GROUP1,DATA1.getVertsFromGroup(GROUP1),1.0,'replace') - # ======================================================== - # ===== now copy the vertices coords ===================== - # ======================================================== - for v in meshrvk1.verts: - i= meshrvk1.verts.index(v) - v1=DATA2.verts[i] - for n in [0,1,2]: - v1.co[n]=v.co[n] - DATA2.update() - DATA2.insertKey(FRAME,'relative') - DATA2.update() - RVK2.makeDisplayList() - - if RVK1.modifiers: - # =================================================== - # === unset Modifiers ============================= - # =================================================== - for B in BMOD[0][1:]: - MODRVK1[B[2]][Modifier.Settings.RENDER]|=B[-2] - for B in BMOD[1]: - if not B[1]: - MODRVK1[B[2]][Modifier.Settings.RENDER]|=B[-2] - - else: - name = "Meshes Objects must have the same number of vertices %t|Ok. %x1" - result = Draw.PupMenu(name) - return - if DATA2.getKey(): - select_modifier(RVK1, RVK2, DATA2) - else: - name = "Second Object must have at least a shape key %t| Ok. %x1| Add one ? %x2" - result = Draw.PupMenu(name) - if result : - RVK2.insertShapeKey() - DATA2=RVK2.getData() - select_modifier(RVK1, RVK2, DATA2) - else: - return - else: - name = "Object must be Meshes %t| Ok. %x1" - result = Draw.PupMenu(name) - return - -def deform2rvk(): - scn = Blender.Scene.GetCurrent() - # ================================================================= - # at leat 2 objects =============================================== - # ================================================================= - if len(scn.objects.selected) >1 : - RVK1 = Object.GetSelected()[0] - RVK2=Object.GetSelected()[1] - if RVK2.getType()=='Mesh' : - copy_shapes(RVK1,RVK2) - # ================================================================= - # ... but if only one...=========================================== - # ================================================================= - elif len(scn.objects.selected)==1: - name = "At least 2 Meshes must be selected %t| Ok. %x1| Add one ? %x2" - result = Draw.PupMenu(name) - RVK1 = Object.GetSelected()[0] - if result and RVK1.getType()=='Mesh' : - Blender.Object.Duplicate(mesh=1) - RVK2=scn.objects.active - mod = RVK2.modifiers - for m in mod : - RVK2.modifiers.remove(m) - RVK2.LocX+=2.0 - copy_shapes(RVK1,RVK2) - scn.objects.selected=[] - RVK2.sel=1 - RVK1.sel=1 - # ================================================================ - # ... and not a mesh...=========================================== - # ================================================================ - elif result: - name = "Selected object must be a mesh %t| Ok. %x1" - result = Draw.PupMenu(name) - return - else : - return - # ================================================================ - # ... if not object at all. ===================================== - # ================================================================ - else: - name = "At least one Mesh object must be selected %t| Ok. %x1" - result = Draw.PupMenu(name) - return - - Blender.Redraw() - -EDITMODE=Blender.Window.EditMode() -Blender.Window.EditMode(0) -END = 0 -DEFAULT= Blender.Get('curframe') - -while not END: - deform2rvk() - name = "Do you want to copy at a new frame %t| Yes ? %x1| No ? %x2" - result = Draw.PupMenu(name) - if result == 1: - msg = "Frame :" - inputresult = Draw.PupIntInput(msg, DEFAULT , Blender.Get('staframe'), Blender.Get('endframe')) - print inputresult - if inputresult != None: - Blender.Set('curframe',inputresult) - Blender.Window.RedrawAll() - else: - END = 1 - else: - END = 1 - -Blender.Window.EditMode(EDITMODE) diff --git a/release/scripts/save_theme.py b/release/scripts/save_theme.py deleted file mode 100644 index 1d23b12403a..00000000000 --- a/release/scripts/save_theme.py +++ /dev/null @@ -1,143 +0,0 @@ -#!BPY - -""" -Name: 'Save Current Theme...' -Blender: 242 -Group: 'Export' -Tooltip: 'Save current theme as a BPython script' -""" - -__author__ = "Willian P. Germano" -__url__ = ("blender", "blenderartists.org") -__version__ = "2.43 2006/12/30" - -__bpydoc__ = """\ -This script saves the current Theme in Blender as a Blender Python script. - -Usage: - -Use Blender's Theme tab in the User Preferences window to create and name your -theme, then run this script from the File->Export menu to save it. - -It is saved as a bpython script, meaning that you can simply run it to change -the current theme. By default it is currently saved under the -"Misc" group, available only from the Scripts window "Scripts->Misc" menu. - -To appear in the menu, a theme saved with this script must be put in your -Blender's scripts dir, that's what happens by default when you save one by -yourself. If you don't know where this dir is, running - -import Blender<br>print Blender.Get("scriptsdir") - -on the Text Editor window (use menu or ALT+P to run it) will write the path on -the console. - -Remember to edit your exported theme's source file to put your name and -some information on it before sharing it with others. -""" - -# $Id$ -# -# -------------------------------------------------------------------------- -# Copyright (C) 2004: Willian P. Germano, wgermano _at_ ig com br -# -------------------------------------------------------------------------- -# The scripts generated by this script are put under Public Domain by -# default, but you are free to edit the ones you generate with this script -# and change their license to another one of your choice. -# -------------------------------------------------------------------------- -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Copyright (C) 2005: Willian P. Germano, wgermano _at_ ig.com.br -# -# 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 ***** -# -------------------------------------------------------------------------- - -import Blender -from Blender.Window import Theme, FileSelector - -theme = Theme.Get()[0] # get current theme - -# default filename: theme's name + '_theme.py' in user's scripts dir: -default_fname = Blender.Get("scriptsdir") -if (default_fname): - default_fname = Blender.sys.join(default_fname, theme.name + '_theme.py') -else: - default_fname = theme.name + '_theme.py' - -default_fname = default_fname.replace(' ','_') - -def write_theme(filename): - "Write the current theme as a bpython script" - - if not filename.endswith('.py'): filename += '.py' - - fout = file(filename, "w") - - fout.write("""#!BPY - -# \"\"\" -# Name: '%s' -# Blender: 242 -# Group: 'Themes' -# Tooltip: 'Change current theme' -# \"\"\" - -__%s__ = "????" -__%s__ = "2.43" -__%s__ = ["blender"] -__%s__ = \"\"\"\\ -You can edit this section to write something about your script that can -be read then with the Scripts Help Browser script in Blender. - -Remember to also set author, version and possibly url(s) above. You can also -define an __email__ tag, check some bundled script's source for examples. -\"\"\" - -# This script was automatically generated by the save_theme.py bpython script. -# By default, these generated scripts are released as Public Domain, but you -# are free to change the license of the scripts you generate with -# save_theme.py before releasing them. - -import Blender -from Blender.Window import Theme - -theme = Theme.New('%s') -""" % (theme.name, "author", "version", "url", "bpydoc", theme.name)) - - for tsp in theme.get(): # - command = "\n%s = theme.get('%s')" % (tsp, tsp) - fout.write(command + "\n") - exec(command) - exec("vars = dir(%s)" % tsp) - vars.remove('theme') - - for var in vars: - v = "%s.%s" % (tsp, var) - exec("value = %s" % v) - if type(value) == str: - fout.write("%s = '%s'\n" % (v, value)) - else: - fout.write("%s = %s\n" % (v, value)) - - fout.write('\nBlender.Redraw(-1)') - fout.close() - try: - Blender.UpdateMenus() - except: - Blender.Draw.PupMenu("Warning - check console!%t|Menus could not be automatically updated") - -FileSelector(write_theme, "Save Current Theme", default_fname) diff --git a/release/scripts/scripttemplate_background_job.py b/release/scripts/scripttemplate_background_job.py deleted file mode 100644 index 86b58991849..00000000000 --- a/release/scripts/scripttemplate_background_job.py +++ /dev/null @@ -1,124 +0,0 @@ -#!BPY -""" -Name: 'Background Job Example' -Blender: 248 -Group: 'ScriptTemplate' -Tooltip: 'Script template for automating tasks from the command line with blender' -""" - -from Blender import Window -import bpy - -script_data = \ -'''# This script is an example of how you can run blender from the command line (in background mode with no interface) -# to automate tasks, in this example it creates a text object, camera and light, then renders and/or saves it. -# This example also shows how you can parse command line options to python scripts. -# -# Example usage for this test. -# blender -b -P $HOME/background_job.py -- --text="Hello World" --render="/tmp/hello" --save="/tmp/hello.blend" -# -# Notice all python args are after the '--' argument. - -import Blender -import bpy - -def example_function(body_text, save_path, render_path): - - sce= bpy.data.scenes.active - - txt_data= bpy.data.curves.new('MyText', 'Text3d') - - # Text Object - txt_ob = sce.objects.new(txt_data) # add the data to the scene as an object - txt_data.setText(body_text) # set the body text to the command line arg given - txt_data.setAlignment(Blender.Text3d.MIDDLE)# center text - - # Camera - cam_data= bpy.data.cameras.new('MyCam') # create new camera data - cam_ob= sce.objects.new(cam_data) # add the camera data to the scene (creating a new object) - sce.objects.camera= cam_ob # set the active camera - cam_ob.loc= 0,0,10 - - # Lamp - lamp_data= bpy.data.lamps.new('MyLamp') - lamp_ob= sce.objects.new(lamp_data) - lamp_ob.loc= 2,2,5 - - if save_path: - try: - f= open(save_path, 'w') - f.close() - ok= True - except: - print 'Cannot save to path "%s"' % save_path - ok= False - - if ok: - Blender.Save(save_path, 1) - - if render_path: - render= sce.render - render.extensions= True - render.renderPath = render_path - render.sFrame= 1 - render.eFrame= 1 - render.renderAnim() - - - -import sys # to get command line args -import optparse # to parse options for us and print a nice help message - -script_name= 'background_job.py' - -def main(): - - # get the args passed to blender after "--", all of which are ignored by blender specifically - # so python may receive its own arguments - argv= sys.argv - - if '--' not in argv: - argv = [] # as if no args are passed - else: - argv = argv[argv.index('--')+1: ] # get all args after "--" - - # When --help or no args are given, print this help - usage_text = 'Run blender in background mode with this script:\n' - usage_text += ' blender -b -P ' + script_name + ' -- [options]' - - parser = optparse.OptionParser(usage = usage_text) - - - # Example background utility, add some text and renders or saves it (with options) - # Possible types are: string, int, long, choice, float and complex. - parser.add_option('-t', '--text', dest='body_text', help='This text will be used to render an image', type='string') - - parser.add_option('-s', '--save', dest='save_path', help='Save the generated file to the specified path', metavar='FILE') - parser.add_option('-r', '--render', dest='render_path', help='Render an image to the specified path', metavar='FILE') - - options, args = parser.parse_args(argv) # In this example we wont use the args - - if not argv: - parser.print_help() - return - - if not options.body_text: - print 'Error: --text="some string" argument not given, aborting.\n' - parser.print_help() - return - - # Run the example function - example_function(options.body_text, options.save_path, options.render_path) - - print 'batch job finished, exiting' - - -if __name__ == '__main__': - main() -''' - -new_text = bpy.data.texts.new('background_job.py') -new_text.write(script_data) -bpy.data.texts.active = new_text -Window.RedrawAll() - diff --git a/release/scripts/scripttemplate_camera_object.py b/release/scripts/scripttemplate_camera_object.py deleted file mode 100644 index cacc35ed1a5..00000000000 --- a/release/scripts/scripttemplate_camera_object.py +++ /dev/null @@ -1,104 +0,0 @@ -#!BPY -""" -Name: 'Camera/Object Example' -Blender: 245 -Group: 'ScriptTemplate' -Tooltip: 'Script template for setting the camera direction' -""" - -from Blender import Window -import bpy - -script_data = \ -'''#!BPY -""" -Name: 'My Camera script' -Blender: 245 -Group: 'Object' -Tooltip: 'Rotate the camera to center on the active object' -""" - -import Blender -from Blender import Window, Scene, Draw, Mathutils - -# Rotate the camera in such a way that it centers on the currently active object -def RotCamToOb(cam, ob): - - # Get the camera matrix - camMat = cam.getMatrix('worldspace'); - - # Get the location of the camera and object and make sure they're vectors - camLoc = Mathutils.Vector(cam.loc) - obLoc = Mathutils.Vector(ob.loc) - - # Get the vector (direction) from the camera to the object - newVec = obLoc - camLoc - - # Make a quaternion that points the camera along the vector - newQuat = newVec.toTrackQuat('-z', 'y') - - # Convert the new quaternion to a rotation matrix (and resize it to 4x4 so it matches the other matrices) - rotMat = newQuat.toMatrix().resize4x4() - - # Make a matrix with only the current location of the camera - transMat = Mathutils.TranslationMatrix(camMat.translationPart()); - - # Multiply the rotation and translation matrixes to make 1 matrix with all data - newMat = rotMat * transMat - - # Now we make this matrix the camera matrix and voila done! - cam.setMatrix(newMat) - -#Make sure blender and the objects are in the right state and start doing stuff -def SceneCheck(): - - # Show a neat waitcursor whilst the script runs - Window.WaitCursor(1) - - # If we are in edit mode, go out of edit mode and store the status in a var - emode = int(Window.EditMode()) - if emode: Window.EditMode(0) - - # Get the scene, the camera and the currently active object - scn = Scene.GetCurrent() - cam = scn.getCurrentCamera() - ob = scn.getActiveObject() - - # Lets do some checks to make sure we have everything - # And if we don't then call a return which stops the entire script - if not cam: - Draw.PupMenu('Error, no active camera, aborting.') - return - - if not ob: - Draw.PupMenu('Error, no active object, aborting.') - return - - if cam == ob: - Draw.PupMenu('Error, select an object other than the camera, aborting.') - return - - # Start the main function of the script if we didn't encounter any errors - RotCamToOb(cam, ob) - - # Update the scene - scn.update() - - # Redraw the 3d view so we can instantly see what was changed - Window.Redraw(Window.Types.VIEW3D) - - # If we were in edit mode when the script started, go back into edit mode - if emode: Window.EditMode(1) - - # Remove the waitcursor - Window.WaitCursor(0) - -# Start the script -SceneCheck() - -''' - -new_text = bpy.data.texts.new('camobject_template.py') -new_text.write(script_data) -bpy.data.texts.active = new_text -Window.RedrawAll() diff --git a/release/scripts/scripttemplate_gamelogic.py b/release/scripts/scripttemplate_gamelogic.py deleted file mode 100644 index 577847c0dda..00000000000 --- a/release/scripts/scripttemplate_gamelogic.py +++ /dev/null @@ -1,97 +0,0 @@ -#!BPY -""" -Name: 'GameLogic Example' -Blender: 249 -Group: 'ScriptTemplate' -Tooltip: 'Script template with examples of how to use game logic' -""" - -from Blender import Window -import bpy - -script_data = \ -''' -# This script must be assigned to a python controller -# where it can access the object that owns it and the sensors/actuators that it connects to. - -# GameLogic has been added to the global namespace no need to import - -# for keyboard event comparison -# import GameKeys - -# support for Vector(), Matrix() types and advanced functions like AngleBetweenVecs(v1,v2) and RotationMatrix(...) -# import Mathutils - -# for functions like getWindowWidth(), getWindowHeight() -# import Rasterizer - -def main(): - cont = GameLogic.getCurrentController() - - # The KX_GameObject that owns this controller. - own = cont.owner - - # for scripts that deal with spacial logic - own_pos = own.worldPosition - - - # Some example functions, remove to write your own script. - # check for a positive sensor, will run on any object without errors. - print 'Logic info for KX_GameObject', own.name - input = False - - for sens in cont.sensors: - # The sensor can be on another object, we may want to use it - own_sens = sens.owner - print ' sensor:', sens.name, - if sens.positive: - print '(true)' - input = True - else: - print '(false)' - - for actu in cont.actuators: - # The actuator can be on another object, we may want to use it - own_actu = actu.owner - print ' actuator:', actu.name - - # This runs the actuator or turns it off - # note that actuators will continue to run unless explicitly turned off. - if input: - cont.activate(actu) - else: - cont.deactivate(actu) - - # Its also good practice to get sensors and actuators by name - # rather then index so any changes to their order wont break the script. - - # sens_key = cont.sensors['key_sensor'] - # actu_motion = cont.actuators['motion'] - - - # Loop through all other objects in the scene - sce = GameLogic.getCurrentScene() - print 'Scene Objects:', sce.name - for ob in sce.objects: - print ' ', ob.name, ob.worldPosition - - - # Example where collision objects are checked for their properties - # adding to our objects "life" property - """ - actu_collide = cont.sensors['collision_sens'] - for ob in actu_collide.objectHitList: - # Check to see the object has this property - if ob.has_key('life'): - own['life'] += ob['life'] - ob['life'] = 0 - print own['life'] - """ - -main() -''' - -new_text = bpy.data.texts.new('gamelogic_example.py') -new_text.write(script_data) -bpy.data.texts.active = new_text -Window.RedrawAll() diff --git a/release/scripts/scripttemplate_gamelogic_basic.py b/release/scripts/scripttemplate_gamelogic_basic.py deleted file mode 100644 index fd404d5c8a4..00000000000 --- a/release/scripts/scripttemplate_gamelogic_basic.py +++ /dev/null @@ -1,33 +0,0 @@ -#!BPY -""" -Name: 'GameLogic Template' -Blender: 249 -Group: 'ScriptTemplate' -Tooltip: 'Basic template for new game logic scripts' -""" - -from Blender import Window -import bpy - -script_data = \ -''' -def main(): - - cont = GameLogic.getCurrentController() - own = cont.owner - - sens = cont.sensors['mySensor'] - actu = cont.actuators['myActuator'] - - if sens.positive: - cont.activate(actu) - else: - cont.deactivate(actu) - -main() -''' - -new_text = bpy.data.texts.new('gamelogic_simple.py') -new_text.write(script_data) -bpy.data.texts.active = new_text -Window.RedrawAll() diff --git a/release/scripts/scripttemplate_gamelogic_module.py b/release/scripts/scripttemplate_gamelogic_module.py deleted file mode 100644 index 2ef4950917b..00000000000 --- a/release/scripts/scripttemplate_gamelogic_module.py +++ /dev/null @@ -1,45 +0,0 @@ -#!BPY -""" -Name: 'GameLogic Module' -Blender: 249 -Group: 'ScriptTemplate' -Tooltip: 'Basic template for new game logic modules' -""" - -from Blender import Window -import bpy - -script_data = \ -''' -# This module can be accessed by a python controller with -# its execution method set to 'Module' -# * Set the module string to "gamelogic_module.main" (without quotes) -# * When renaming the script it MUST have a .py extension -# * External text modules are supported as long as they are at -# the same location as the blendfile or one of its libraries. - -import GameLogic - -# variables defined here will only be set once when the -# module is first imported. Set object spesific vars -# inside the function if you intend to use the module -# with multiple objects. - -def main(cont): - own = cont.owner - - sens = cont.sensors['mySensor'] - actu = cont.actuators['myActuator'] - - if sens.positive: - cont.activate(actu) - else: - cont.deactivate(actu) - -# dont call main(GameLogic.getCurrentController()), the py controller will -''' - -new_text = bpy.data.texts.new('gamelogic_module.py') -new_text.write(script_data) -bpy.data.texts.active = new_text -Window.RedrawAll() diff --git a/release/scripts/scripttemplate_ipo_gen.py b/release/scripts/scripttemplate_ipo_gen.py deleted file mode 100644 index a333b4f20bf..00000000000 --- a/release/scripts/scripttemplate_ipo_gen.py +++ /dev/null @@ -1,92 +0,0 @@ -#!BPY -""" -Name: 'IPO Example' -Blender: 245 -Group: 'ScriptTemplate' -Tooltip: 'Script template for setting the IPO' -""" - -from Blender import Window -import bpy - -script_data = \ -'''#!BPY -""" -Name: 'My Ipo Script' -Blender: 245 -Group: 'Animation' -Tooltip: 'Put some useful info here' -""" - -# Add a licence here if you wish to re-distribute, we recommend the GPL - -from Blender import Ipo, Mathutils, Window -import bpy, BPyMessages - -def makeRandomIpo(object, firstFrame, numberOfFrames, frameStep): - # Create an new Ipo Curve of name myIpo and type Object - myIpo = bpy.data.ipos.new('myIpo', 'Object') - - # Create LocX, LocY, and LocZ Ipo curves in our new Curve Object - # and store them so we can access them later - myIpo_x = myIpo.addCurve('LocX') - myIpo_y = myIpo.addCurve('LocY') - myIpo_z = myIpo.addCurve('LocZ') - - # What value we want to scale our random value by - ipoScale = 4 - - # This Calculates the End Frame for use in an xrange() expression - endFrame = firstFrame + (numberOfFrames * frameStep) + frameStep - - for frame in xrange(firstFrame, endFrame, frameStep): - - # Use the Mathutils Rand() function to get random numbers - ipoValue_x = Mathutils.Rand(-1, 1) * ipoScale - ipoValue_y = Mathutils.Rand(-1, 1) * ipoScale - ipoValue_z = Mathutils.Rand(-1, 1) * ipoScale - - # Append to the Ipo curve at location frame, with the value ipoValue_x - # Note that we should pass the append function a tuple or a BezTriple - myIpo_x.append((frame, ipoValue_x)) - - # Similar to above - myIpo_y.append((frame, ipoValue_y)) - myIpo_z.append((frame, ipoValue_z)) - - # Link our new Ipo Curve to the passed object - object.setIpo(myIpo) - print object - - -def main(): - - # Get the active scene, since there can be multiple ones - sce = bpy.data.scenes.active - - # Get the active object - object = sce.objects.active - - # If there is no active object, pop up an error message - if not object: - BPyMessages.Error_NoActive() - - Window.WaitCursor(1) - - # Call our makeRandomIpo function - # Pass it our object, Tell it to keys from the start frame until the end frame, at a step of 10 frames - # between them - - makeRandomIpo(object, sce.render.sFrame, sce.render.eFrame, 10) - - Window.WaitCursor(0) - -if __name__ == '__main__': - main() - -''' - -new_text = bpy.data.texts.new('ipo_template.py') -new_text.write(script_data) -bpy.data.texts.active = new_text -Window.RedrawAll() diff --git a/release/scripts/scripttemplate_mesh_edit.py b/release/scripts/scripttemplate_mesh_edit.py deleted file mode 100644 index 159fb884925..00000000000 --- a/release/scripts/scripttemplate_mesh_edit.py +++ /dev/null @@ -1,98 +0,0 @@ -#!BPY -""" -Name: 'Mesh Editing' -Blender: 243 -Group: 'ScriptTemplate' -Tooltip: 'Add a new text for editing a mesh' -""" - -from Blender import Window -import bpy - -script_data = \ -'''#!BPY -""" -Name: 'My Mesh Script' -Blender: 243 -Group: 'Mesh' -Tooltip: 'Put some useful info here' -""" - -# Add a licence here if you wish to re-distribute, we recommend the GPL - -from Blender import Scene, Mesh, Window, sys -import BPyMessages -import bpy - -def my_mesh_util(me): - # This function runs out of editmode with a mesh - # error cases are alredy checked for - - # Remove these when writing your own tool - print me.name - print 'vert count', len(me.verts) - print 'edge count', len(me.edges) - print 'face count', len(me.faces) - - # Examples - - # Move selected verts on the x axis - """ - for v in me.verts: - if v.sel: - v.co.x += 1.0 - """ - - # Shrink selected faces - """ - for f in me.faces: - if f.sel: - c = f.cent - for v in f: - v.co = (c+v.co)/2 - """ - -def main(): - - # Gets the current scene, there can be many scenes in 1 blend file. - sce = bpy.data.scenes.active - - # Get the active object, there can only ever be 1 - # and the active object is always the editmode object. - ob_act = sce.objects.active - - if not ob_act or ob_act.type != 'Mesh': - BPyMessages.Error_NoMeshActive() - return - - - # Saves the editmode state and go's out of - # editmode if its enabled, we cant make - # changes to the mesh data while in editmode. - is_editmode = Window.EditMode() - if is_editmode: Window.EditMode(0) - - Window.WaitCursor(1) - me = ob_act.getData(mesh=1) # old NMesh api is default - t = sys.time() - - # Run the mesh editing function - my_mesh_util(me) - - # Restore editmode if it was enabled - if is_editmode: Window.EditMode(1) - - # Timing the script is a good way to be aware on any speed hits when scripting - print 'My Script finished in %.2f seconds' % (sys.time()-t) - Window.WaitCursor(0) - - -# This lets you can import the script without running it -if __name__ == '__main__': - main() -''' - -new_text = bpy.data.texts.new('mesh_template.py') -new_text.write(script_data) -bpy.data.texts.active = new_text -Window.RedrawAll()
\ No newline at end of file diff --git a/release/scripts/scripttemplate_metaball_create.py b/release/scripts/scripttemplate_metaball_create.py deleted file mode 100644 index 28db9de3af6..00000000000 --- a/release/scripts/scripttemplate_metaball_create.py +++ /dev/null @@ -1,76 +0,0 @@ -#!BPY -""" -Name: 'Metaball Generation' -Blender: 245 -Group: 'ScriptTemplate' -Tooltip: 'Script template to make metaballs from a mesh' -""" - -from Blender import Window -import bpy - -script_data = \ -'''#!BPY -""" -Name: 'My Metaball Script' -Blender: 245 -Group: 'Misc' -Tooltip: 'Put some useful info here' -""" - -# Add a license here if you wish to re-disribute, we recommend the GPL - -from Blender import Metaball, Mesh, Window -import bpy - -def makeMetaSculpture(sce): - #Create a base mesh for our sculpture to use - monkey = Mesh.Primitives.Monkey() - - #Create a new meta datablock to use and give it a name - metaObj = Metaball.New() - metaObj.name = "MetaSuzanne" - - #Increase the resolution so it looks better - metaObj.wiresize = 0.2 - metaObj.rendersize = 0.1 - - #The radius for our new meta objects to take - metaRadius = 2.0 - - for f in monkey.faces: - - #Create a new metaball as part of the Meta Object Data - newBall = metaObj.elements.add() - - #Make the new ball have the same coordinates as a vertex on our Mesh - newBall.co = f.cent - - #Assign the same radius to all balls - newBall.radius = f.area * metaRadius - - #Create the new object and put our meta data there - sce.objects.new(metaObj, "MetaSuzanne") - - -def main(): - scene = bpy.data.scenes.active #Get the active scene - - Window.WaitCursor(1) - - #Call the sculpture making function - makeMetaSculpture(scene) - - Window.WaitCursor(0) - - #Redraw the Screen When Finished - Window.RedrawAll(1) - -if __name__ == '__main__': - main() -''' - -new_text = bpy.data.texts.new('metaball_template.py') -new_text.write(script_data) -bpy.data.texts.active = new_text -Window.RedrawAll() diff --git a/release/scripts/scripttemplate_object_edit.py b/release/scripts/scripttemplate_object_edit.py deleted file mode 100644 index 3ba20f20dd1..00000000000 --- a/release/scripts/scripttemplate_object_edit.py +++ /dev/null @@ -1,81 +0,0 @@ -#!BPY -""" -Name: 'Object Editing' -Blender: 243 -Group: 'ScriptTemplate' -Tooltip: 'Add a new text for editing selected objects' -""" - -from Blender import Window -import bpy - -script_data = \ -'''#!BPY -""" -Name: 'My Object Script' -Blender: 245 -Group: 'Object' -Tooltip: 'Put some useful info here' -""" - -# Add a licence here if you wish to re-distribute, we recommend the GPL - -from Blender import Window, sys -import bpy - -def my_object_util(sce): - - # Remove these when writing your own tool - print 'Blend object count', len(bpy.data.objects) - print 'Scene object count', len(sce.objects) - - # context means its selected, in the view layer and not hidden. - print 'Scene context count', len(sce.objects.context) - - # Examples - - # Move context objects on the x axis - """ - for ob in sce.objects.context: - ob.LocX += 1 - """ - - # Copy Objects, does not copy object data - """ - # Store the current contetx - context = list(sce.objects.context) - # de-select all - sce.objects.selected = [] - - for ob in context: - ob_copy = ob.copy() - sce.objects.link(ob_copy) # the copy is not added to a scene - ob_copy.sel = True - """ - -def main(): - - # Gets the current scene, there can be many scenes in 1 blend file. - sce = bpy.data.scenes.active - - Window.WaitCursor(1) - t = sys.time() - - # Run the object editing function - my_object_util(sce) - - # Timing the script is a good way to be aware on any speed hits when scripting - print 'My Script finished in %.2f seconds' % (sys.time()-t) - Window.WaitCursor(0) - - -# This lets you can import the script without running it -if __name__ == '__main__': - main() - -''' - -new_text = bpy.data.texts.new('object_template.py') -new_text.write(script_data) -bpy.data.texts.active = new_text -Window.RedrawAll() diff --git a/release/scripts/scripttemplate_pyconstraint.py b/release/scripts/scripttemplate_pyconstraint.py deleted file mode 100644 index 0215e47a1bd..00000000000 --- a/release/scripts/scripttemplate_pyconstraint.py +++ /dev/null @@ -1,114 +0,0 @@ -#!BPY -""" -Name: 'Script Constraint' -Blender: 245 -Group: 'ScriptTemplate' -Tooltip: 'Add a new script for custom constraints' -""" - -from Blender import Window -import bpy - -script_data = \ -"""#BPYCONSTRAINT -''' - PyConstraint template, access this in the "add constraint" scripts submenu. - Add docstring here -''' - -import Blender -from Blender import Draw -from Blender import Mathutils -import math - -''' - This variable specifies the number of targets - that this constraint can use -''' -NUM_TARGETS = 1 - - -''' - This function is called to evaluate the constraint - obmatrix: (Matrix) copy of owner's 'ownerspace' matrix - targetmatrices: (List) list of copies of the 'targetspace' matrices of the targets (where applicable) - idprop: (IDProperties) wrapped data referring to this - constraint instance's idproperties -''' -def doConstraint(obmatrix, targetmatrices, idprop): - # Separate out the transformation components for easy access. - obloc = obmatrix.translationPart() # Translation - obrot = obmatrix.toEuler() # Rotation - obsca = obmatrix.scalePart() # Scale - - # Define user-settable parameters - # Must also be defined in getSettings(). - if not idprop.has_key('user_toggle'): idprop['user_toggle'] = 1 - if not idprop.has_key('user_slider'): idprop['user_slider'] = 1.0 - - - # Do stuff here, changing obloc, obrot, and obsca. - - - # Convert back into a matrix for loc, scale, rotation, - mtxloc = Mathutils.TranslationMatrix(obloc) - mtxrot = obrot.toMatrix().resize4x4() - mtxsca = Mathutils.Matrix([obsca[0],0,0,0], [0,obsca[1],0,0], [0,0,obsca[2],0], [0,0,0,1]) - - # Recombine the separate elements into a transform matrix. - outputmatrix = mtxsca * mtxrot * mtxloc - - # Return the new matrix. - return outputmatrix - - - -''' - This function manipulates the matrix of a target prior to sending it to doConstraint() - target_object: wrapped data, representing the target object - subtarget_bone: wrapped data, representing the subtarget pose-bone/vertex-group (where applicable) - target_matrix: (Matrix) the transformation matrix of the target - id_properties_of_constraint: (IDProperties) wrapped idproperties -''' -def doTarget(target_object, subtarget_bone, target_matrix, id_properties_of_constraint): - return target_matrix - - -''' - This function draws a pupblock that lets the user set - the values of custom settings the constraint defines. - This function is called when the user presses the settings button. - idprop: (IDProperties) wrapped data referring to this - constraint instance's idproperties -''' -def getSettings(idprop): - # Define user-settable parameters. - # Must also be defined in getSettings(). - if not idprop.has_key('user_toggle'): idprop['user_toggle'] = 1 - if not idprop.has_key('user_slider'): idprop['user_slider'] = 1.0 - - # create temporary vars for interface - utoggle = Draw.Create(idprop['user_toggle']) - uslider = Draw.Create(idprop['user_slider']) - - - # define and draw pupblock - block = [] - block.append("Buttons: ") - block.append(("Toggle", utoggle, "This is a toggle button.")) - block.append("More buttons: ") - block.append(("Slider", uslider, 0.0000001, 1000.0, "This is a number field.")) - - retval = Draw.PupBlock("Constraint Template", block) - - # update id-property values after user changes settings - if (retval): - idprop['user_toggle']= utoggle.val - idprop['user_slider']= uslider.val - -""" - -new_text = bpy.data.texts.new('pyconstraint_template.py') -new_text.write(script_data) -bpy.data.texts.active = new_text -Window.RedrawAll() diff --git a/release/scripts/scripttemplate_text_plugin.py b/release/scripts/scripttemplate_text_plugin.py deleted file mode 100644 index 4ae562736d3..00000000000 --- a/release/scripts/scripttemplate_text_plugin.py +++ /dev/null @@ -1,69 +0,0 @@ -#!BPY -""" -Name: 'Text Plugin' -Blender: 246 -Group: 'ScriptTemplate' -Tooltip: 'Add a new text for writing a text plugin' -""" - -from Blender import Window -import bpy - -script_data = \ -'''#!BPY -""" -Name: 'My Plugin Script' -Blender: 246 -Group: 'TextPlugin' -Shortcut: 'Ctrl+Alt+U' -Tooltip: 'Put some useful info here' -""" - -# Add a licence here if you wish to re-distribute, we recommend the GPL - -from Blender import Window, sys -import BPyTextPlugin, bpy - -def my_script_util(txt): - # This function prints out statistical information about a script - - desc = BPyTextPlugin.get_cached_descriptor(txt) - print '---------------------------------------' - print 'Script Name:', desc.name - print 'Classes:', len(desc.classes) - print ' ', desc.classes.keys() - print 'Functions:', len(desc.defs) - print ' ', desc.defs.keys() - print 'Variables:', len(desc.vars) - print ' ', desc.vars.keys() - -def main(): - - # Gets the active text object, there can be many in one blend file. - txt = bpy.data.texts.active - - # Silently return if the script has been run with no active text - if not txt: - return - - # Text plug-ins should run quickly so we time it here - Window.WaitCursor(1) - t = sys.time() - - # Run our utility function - my_script_util(txt) - - # Timing the script is a good way to be aware on any speed hits when scripting - print 'Plugin script finished in %.2f seconds' % (sys.time()-t) - Window.WaitCursor(0) - - -# This lets you import the script without running it -if __name__ == '__main__': - main() -''' - -new_text = bpy.data.texts.new('textplugin_template.py') -new_text.write(script_data) -bpy.data.texts.active = new_text -Window.RedrawAll() diff --git a/release/scripts/slp_import.py b/release/scripts/slp_import.py deleted file mode 100644 index 30387ad7440..00000000000 --- a/release/scripts/slp_import.py +++ /dev/null @@ -1,116 +0,0 @@ -#!BPY - -""" -Name: 'Pro Engineer (.slp)...' -Blender: 232 -Group: 'Import' -Tooltip: 'Import Pro Engineer (.slp) File Format' -""" - -__author__ = "Anthony D'Agostino (Scorpius)" -__url__ = ("blender", "blenderartists.org", -"Author's homepage, http://www.redrival.com/scorpius") -__version__ = "Part of IOSuite 0.5" - -__bpydoc__ = """\ -This script imports Pro Engineer files to Blender. - -This format can be exported from Pro/Engineer and most other CAD -applications. Written at the request of a Blender user. It is almost -identical to RAW format. - -Usage:<br> - Execute this script from the "File->Import" menu and choose an SLP file to -open. - -Notes:<br> - Generates the standard verts and faces lists, but without duplicate -verts. Only *exact* duplicates are removed, there is no way to specify a -tolerance. -""" - -# $Id$ -# -# +---------------------------------------------------------+ -# | Copyright (c) 2004 Anthony D'Agostino | -# | http://www.redrival.com/scorpius | -# | scorpius@netzero.com | -# | May 3, 2004 | -# | Read and write SLP Triangle File Format (*.slp) | -# +---------------------------------------------------------+ - -# ***** 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 ***** - -import Blender, meshtools -#import time - -# ================================ -# === Read SLP Triangle Format === -# ================================ -def read(filename): - #start = time.clock() - file = open(filename, "rb") - - raw = [] - for line in file: #.xreadlines(): - data = line.split() - if data[0] == "vertex": - vert = map(float, data[1:]) - raw.append(vert) - - tri = [] - for i in xrange(0, len(raw), 3): - tri.append(raw[i] + raw[i+1] + raw[i+2]) - - #$import pprint; pprint.pprint(tri) - - # Collect data from RAW format - faces = [] - for line in tri: - f1, f2, f3, f4, f5, f6, f7, f8, f9 = line - faces.append([(f1, f2, f3), (f4, f5, f6), (f7, f8, f9)]) - - # Generate verts and faces lists, without duplicates - verts = [] - coords = {} - index = 0 - for i in xrange(len(faces)): - for j in xrange(len(faces[i])): - vertex = faces[i][j] - if not coords.has_key(vertex): - coords[vertex] = index - index += 1 - verts.append(vertex) - faces[i][j] = coords[vertex] - - objname = Blender.sys.splitext(Blender.sys.basename(filename))[0] - - meshtools.create_mesh(verts, faces, objname) - Blender.Window.DrawProgressBar(1.0, '') # clear progressbar - file.close() - #end = time.clock() - #seconds = " in %.2f %s" % (end-start, "seconds") - message = "Successfully imported " + Blender.sys.basename(filename)# + seconds - meshtools.print_boxed(message) - -def fs_callback(filename): - read(filename) - -if __name__ == '__main__': - Blender.Window.FileSelector(fs_callback, "Import SLP", "*.slp") diff --git a/release/scripts/sysinfo.py b/release/scripts/sysinfo.py deleted file mode 100644 index 3a671e7221e..00000000000 --- a/release/scripts/sysinfo.py +++ /dev/null @@ -1,287 +0,0 @@ -#!BPY - -""" -Name: 'System Information...' -Blender: 236 -Group: 'HelpSystem' -Tooltip: 'Information about your Blender environment, useful to diagnose problems.' -""" - -__author__ = "Willian P. Germano" -__url__ = ("blenderartists.org", "blenderartists.org") -__version__ = "1.1" -__bpydoc__ = """\ -This script creates a text in Blender's Text Editor with information -about your OS, video card, OpenGL driver, Blender and Python versions, -script related paths and more. - -If you are experiencing trouble running Blender itself or any Blender Python -script, this information can be useful to fix any problems or at least for -online searches (like checking if there are known issues related to your -video card) or to get help from other users or the program's developers. -""" - -# $Id$ -# -# -------------------------------------------------------------------------- -# sysinfo.py version 1.1 Mar 20, 2005 -# -------------------------------------------------------------------------- -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Copyright (C) 2004: Willian P. Germano, wgermano _at_ ig.com.br -# -# 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 ***** -# -------------------------------------------------------------------------- - -import Blender -import Blender.sys as bsys -from Blender.BGL import * -import sys - -Blender.Window.WaitCursor(1) -# has_textwrap = 1 # see commented code below -output_filename = "system-info.txt" -warnings = 0 -notices = 0 # non critical warnings - -def cutPoint(text, length): - "Returns position of the last space found before 'length' chars" - l = length - c = text[l] - while c != ' ': - l -= 1 - if l == 0: return length # no space found - c = text[l] - return l - -def textWrap(text, length = 70): - lines = [] - while len(text) > 70: - cpt = cutPoint(text, length) - line, text = text[:cpt], text[cpt + 1:] - lines.append(line) - lines.append(text) - return lines - -## Better use our own text wrap functions here -#try: -# import textwrap -#except: -# has_textwrap = 0 -# msg = sys.exc_info()[1].__str__().split()[3] -# Blender.Draw.PupMenu("Python error:|This script requires the %s module" %msg) - -version = Blender.Get('version') / 100.0 -header = "= Blender %s System Information =" % version -lilies = len(header)*"="+"\n" -header = lilies + header + "\n" + lilies - -output = Blender.Text.New(output_filename) - -output.write(header + "\n\n") - -output.write("%s\n\n" % Blender.Get('buildinfo')) - -output.write("Platform: %s\n========\n\n" % sys.platform) - -output.write("Python:\n======\n\n") -output.write("- Version: %s\n\n" % sys.version) -output.write("- Paths:\n\n") -for p in sys.path: - output.write(p + '\n') - -output.write("\n- Directories:") - -dirlist = [ - ['homedir', 'Blender home dir', 1], - ['scriptsdir', 'Default dir for scripts', 1], - ['datadir', 'Default "bpydata/" data dir for scripts', 1], - ['uscriptsdir', 'User defined dir for scripts', 0], - ['udatadir', 'Data dir "bpydata/" inside user defined dir', 0] -] - -has_dir = {} - -for dir in dirlist: - dirname, dirstr, is_critical = dir - dirpath = Blender.Get(dirname) - output.write("\n\n %s:\n" % dirstr) - if not dirpath: - has_dir[dirname] = False - if is_critical: - warnings += 1 - output.write(" <WARNING> -- not found") - else: - notices += 1 - output.write(" <NOTICE> -- not found") - else: - output.write(" %s" % dirpath) - has_dir[dirname] = True - -if not has_dir['homedir']: - outmsg = """ - -<WARNING> - Blender home dir not found! - This should probably be "<path>/.blender/" - where <path> is usually the user's home dir. - - Blender's home dir is where entries like: - folders scripts/, plugins/ and locale/ and - files .Blanguages and .bfont.ttf - are located. - - It's also where Blender stores the Bpymenus file - with information about registered scripts, so it - only needs to scan scripts dir(s) when they are - modified. -""" - output.write(outmsg) - -has_uconfdir = False -if has_dir['udatadir']: - uconfigdir = bsys.join(Blender.Get('udatadir'), 'config') - output.write("\n\n User defined config data dir:") - if bsys.exists(uconfigdir): - has_uconfdir = True - output.write(" %s" % uconfigdir) - else: - notices += 1 - output.write(""" - <NOTICE> -- not found. - bpydata/config/ should be inside the user defined scripts dir. - It's used by Blender to store scripts configuration data. - (Since it is on the user defined dir, a new Blender installation - won't overwrite the data.) -""") - -configdir = bsys.join(Blender.Get('datadir'), 'config') -output.write('\n\n Default config data "bpydata/config/" dir:\n') -if bsys.exists(configdir): - output.write(" %s" % configdir) -else: - warnings += 1 - output.write("""<WARNING> -- not found. - config/ should be inside the default scripts *data dir*. - It's used by Blender to store scripts configuration data - when <user defined scripts dir>/bpydata/config/ dir is - not available. -""") - -if has_uconfdir: - output.write(""" - -The user defined config dir will be used. -""") - -cvsdir = 'release/scripts' -if bsys.dirsep == '\\': cvsdir = cvsdir.replace('/','\\') -sdir = Blender.Get('scriptsdir') -if sdir and sdir.find(cvsdir) >= 0: - if has_uconfdir: - notices += 1 - output.write("\n\n<NOTICE>:\n") - else: - warnings += 1 - output.write("\n\n<WARNING>:\n") - output.write(""" -It seems this Blender binary is located in its cvs source tree. - -It's recommended that the release/scripts/ dir tree is copied -to your blender home dir. -""") - if not has_uconfdir: - output.write(""" -Since you also don't have a user defined scripts dir with the -bpydata/config dir inside it, it will not be possible to save -and restore scripts configuration data files, since writing -to a dir inside a cvs tree is not a good idea and is avoided. -""") - -missing_mods = [] # missing basic modules - -try: - from BPyBlender import basic_modules - for m in basic_modules: - try: exec ("import %s" % m) - except: missing_mods.append(m) - - if missing_mods: - outmsg = """ - -<WARNING>: - -Some expected modules were not found. -Because of that some scripts bundled with Blender may not work. -Please read the FAQ in the Readme.html file shipped with Blender -for information about how to fix the problem. -Missing modules: -""" - output.write(outmsg) - warnings += 1 - for m in missing_mods: - output.write('-> ' + m + '\n') - if 'BPyRegistry' in missing_mods: - output.write(""" -Module BPyRegistry.py is missing! -Without this module it's not possible to save and restore -scripts configuration data files. -""") - - else: - output.write("\n\n- Modules: all basic ones were found.\n") - -except ImportError: - output.write("\n\n<WARNING>:\n Couldn't find BPyBlender.py in scripts/bpymodules/ dir.") - output.write("\n Basic modules availability won't be tested.\n") - warnings += 1 - -output.write("\nOpenGL:\n======\n\n") -output.write("- Renderer: %s\n" % glGetString(GL_RENDERER)) -output.write("- Vendor: %s\n" % glGetString(GL_VENDOR)) -output.write("- Version: %s\n\n" % glGetString(GL_VERSION)) -output.write("- Extensions:\n\n") - -glext = glGetString(GL_EXTENSIONS) -glext = textWrap(glext, 70) - -for l in glext: - output.write(l + "\n") - -output.write("\n\n- Simplistic almost useless benchmark:\n\n") -t = Blender.sys.time() -nredraws = 10 -for i in range(nredraws): - Blender.Redraw(-1) # redraw all windows -result = Blender.sys.time() - t -output.write("Redrawing all areas %s times took %.4f seconds.\n" % (nredraws, result)) - -if warnings or notices: - output.write("\n%s%s\n" % (warnings*"#", notices*".")) - if warnings: - output.write("\n(*) Found %d warning" % warnings) - if (warnings > 1): output.write("s") # (blush) - output.write(", documented in the text above.\n") - if notices: - output.write("\n(*) Found %d notice" % notices) - if (notices > 1): output.write("s") # (blush) - output.write(", documented in the text above.\n") - -else: output.write("\n==\nNo problems were found (scroll up for details).") - -Blender.Window.WaitCursor(0) -exitmsg = "Done!|Please check the text %s in the Text Editor window" % output.name -Blender.Draw.PupMenu(exitmsg) diff --git a/release/scripts/textplugin_convert_ge.py b/release/scripts/textplugin_convert_ge.py deleted file mode 100644 index fb17367d622..00000000000 --- a/release/scripts/textplugin_convert_ge.py +++ /dev/null @@ -1,863 +0,0 @@ -#!BPY -""" -Name: 'Convert BGE 2.49' -Blender: 246 -Group: 'TextPlugin' -Shortcut: '' -Tooltip: 'Attemps to update deprecated usage of game engine API.' -""" - -# -# Copyright 2009 Alex Fraser <alex@phatcore.com> -# -# 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 3 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, see <http://www.gnu.org/licenses/>. -# - -# -# This script updates game engine scripts that were designed for pre-2.49 -# versions of Blender to run with the new API. Deprecated function calls are -# listed in attributeRenameDict. This script searches for instances of the keys -# in a target script and re-writes them. -# -# Some deprecated functions are complicated to re-write. The most common -# conversions have been implemented, but some have not. Running this will reduce -# the number of deprecation warnings in your scripts, but may not eliminate them -# entirely. -# -# NOTE: The conversion is not guaranteed to be perfect. It is strongly -# recommended that you review all changes after running this script. -# -# TODO: The following attributes are either ambiguous or need special processing -# to handle parameters. Deprecated attributes that map to multiple target -# attributes will require a refactor of the main conversion loop in the -# convert248to249 function: currently, it doesn't allow any conversion to -# advance the row index by more than one. -# -# getLinearVelocity (KX_SCA_AddObjectActuator, KX_ObjectActuator) -# Conflicts with KX_GameObject. -# Maps to multiple attributes. -# setLinearVelocity (KX_SCA_AddObjectActuator, KX_ObjectActuator) -# Conflicts with KX_GameObject. -# Maps to multiple attributes. -# getAngularVelocity (KX_SCA_AddObjectActuator, KX_ObjectActuator) -# Conflicts with KX_GameObject. -# Maps to multiple attributes. -# setAngularVelocity (KX_SCA_AddObjectActuator, KX_ObjectActuator) -# Conflicts with KX_GameObject. -# Maps to multiple attributes. -# setAction (BL_ShapeActionActuator, BL_ActionActuator) -# `reset' argument has no conversion target. -# set (KX_VisibilityActuator, KX_IpoActuator) -# Different numbers of arguments. -# Arguments map to multiple attributes. -# getIndex (SCA_JoystickSensor) -# Incompatible values: Old = 1-based index; new = 0-based. -# getMesh (KX_SCA_ReplaceMeshActuator) -# Return types differ. Need to call object.name. -# getObject (KX_SCA_AddObjectActuator, KX_CameraActuator, -# KX_TrackToActuator, KX_ParentActuator) -# Default return type differs between classes. -# setIndex (SCA_JoystickSensor) -# Incompatible values: Old = 1-based index; new = 0-based. -# setObject (KX_SCA_AddObjectActuator, KX_CameraActuator, -# KX_TrackToActuator, KX_ParentActuator) -# Incompatible types: Old = KX_GameObject or String; new = -# KX_GameObject. -# setOperation (KX_SCA_DynamicActuator, KX_StateActuator) -# Ambiguous: different target names. -# getDRot (KX_ObjectActuator) -# Maps to multiple attributes. -# setDRot (KX_ObjectActuator) -# Arguments map to multiple attributes. -# getDLoc (KX_ObjectActuator) -# Maps to multiple attributes. -# setDLoc (KX_ObjectActuator) -# Arguments map to multiple attributes. -# getTorque (KX_ObjectActuator) -# Maps to multiple attributes. -# setTorque (KX_ObjectActuator) -# Arguments map to multiple attributes. -# getForce (KX_ObjectActuator) -# Maps to multiple attributes. -# setForce (KX_ObjectActuator) -# Arguments map to multiple attributes. -# position (KX_GameObject) -# Conflicts with KX_SoundActuator. -# orientation (KX_GameObject) -# Conflicts with KX_SoundActuator. -# - -import string -import re - -COMMENTCHAR = '#' - -class ParseError(Exception): pass -class ConversionError(Exception): pass - -def findBalancedParens(lines, row, col, openChar = '(', closeChar = ')'): - """Finds a balanced pair of parentheses, searching from lines[row][col]. - The opening parenthesis must be on the starting line. - - Returns two tuples containing the row and column of the opening paren, and - the row and column of the matching paren. - - Throws a ParseError if the first character is not openChar, or if a matching - paren cannot be found.""" - - # - # Find the opening coordinates. - # - oRow = row - oCol = col - line = lines[oRow] - while oCol < len(line): - if line[oCol] == openChar: - break - elif line[oCol] == COMMENTCHAR: - break - oCol = oCol + 1 - - if oCol >= len(line) or line[oCol] != openChar or not re.match(r'^\s*$', line[col:oCol]): - raise ParseError, "Can't find opening parenthesis. '%s'" % openChar - - # - # Find the closing coordinates. - # - eRow = oRow - eCol = oCol + 1 - level = 1 - while eRow < len(lines) and level > 0: - line = lines[eRow] - while eCol < len(line) and level > 0: - c = line[eCol] - if c == openChar: - # Found a nested paren. - level = level + 1 - elif c == closeChar: - # Exiting one level of nesting. - level = level - 1 - if level == 0: - # Back to top level! - return (oRow, oCol), (eRow, eCol) - elif c == COMMENTCHAR: - # Comment. Skip the rest of the line. - break - eCol = eCol + 1 - eRow = eRow + 1 - eCol = 0 - raise ParseError, "Couldn't find closing parenthesis." - -def findLastAssignment(lines, row, attrName): - """Finds the most recent assignment of `attrName' before `row'. Returns - everything after the '=' sign or None, if there was no match.""" - contRegex = re.compile(r'[^#]*?' + # Don't search in comments. - attrName + - r'\s*=\s*(.*)') # Assignment - - cRow = row - 1 - while cRow >= 0: - match = contRegex.search(lines[cRow]) - if match: - return match.group(1) - cRow = cRow - 1 - return None - -def replaceSubstr(s, start, end, newSubStr): - """Replace the contents of `s' between `start' and `end' with - `newSubStr'.""" - return s[:start] + newSubStr + s[end:] - -def replaceNextParens(lines, row, colStart, newOpenChar, newCloseChar, - oldOpenChar = '(', oldCloseChar = ')'): - """Replace the next set of parentheses with different characters. The - opening parenthesis must be located on line `row', and on or after - `colStart'. The closing parenthesis may be on the same line or any following - line. The strings are edited in-place. - - Throws a ParseError if the set of parentheses can't be found. In this case, - the strings in `lines' will be untouched.""" - try: - pOpen, pClose = findBalancedParens(lines, row, colStart, oldOpenChar, - oldCloseChar) - except ParseError: - raise - - # Replacement may change string length. Replace closing paren first. - r, c = pClose - lines[r] = replaceSubstr(lines[r], c, c + 1, newCloseChar) - # Replace opening paren. - r, c = pOpen - lines[r] = replaceSubstr(lines[r], c, c + 1, newOpenChar) - -def replaceSimpleGetter(lines, row, colStart, colEnd, newName): - """Replace a call to a simple getter function with a reference to a - property, e.g. foo.getBar() -> foo.bar - - The function identifier being replaced must be on line `row' and - between `colStart' and `colEnd'. The opening parenthesis must follow - immediately (whitespace is allowed). The closing parenthesis may be on the - same or following lines. - - Throws a ConversionError if the parentheses can't be found. In this case - the content of `lines' will be untouched.""" - try: - replaceNextParens(lines, row, colEnd, newOpenChar = '', newCloseChar = '') - except ParseError: - raise ConversionError, ("Deprecated function reference.") - - lines[row] = replaceSubstr(lines[row], colStart, colEnd, newName) - -def replaceSimpleSetter(lines, row, colStart, colEnd, newName): - """Replace a call to a simple setter function with a reference to a - property, e.g. foo.setBar(baz) -> foo.bar = baz - - The function identifier being replaced must be on line `row' and - between `colStart' and `colEnd'. The opening parenthesis must follow - immediately (whitespace is allowed). The closing parenthesis may be on the - same or following lines. - - Throws a ConversionError if the parentheses can't be found. In this case - the content of `lines' will be untouched.""" - try: - replaceNextParens(lines, row, colEnd, newOpenChar = '', newCloseChar = '') - except ParseError: - raise ConversionError, ("Deprecated function reference.") - - lines[row] = replaceSubstr(lines[row], colStart, colEnd, newName + ' = ') - -def replaceArgsWithListSetter(lines, row, colStart, colEnd, newName): - """Replace a call to a multi-agument setter function with a reference to a - list property, e.g. foo.setBar(baz, bazZ) -> foo.bar = [baz, bazZ] - - The function identifier being replaced must be on line `row' and - between `colStart' and `colEnd'. The opening parenthesis must follow - immediately (whitespace is allowed). The closing parenthesis may be on the - same or following lines. - - Throws a ConversionError if the parentheses can't be found. In this case - the content of `lines' will be untouched.""" - try: - replaceNextParens(lines, row, colEnd, newOpenChar = '[', newCloseChar = ']') - except ParseError: - raise ConversionError, ("Deprecated function reference.") - - lines[row] = replaceSubstr(lines[row], colStart, colEnd, newName + ' = ') - - -def replaceKeyedGetter(lines, row, colStart, colEnd, newName): - """Replace a call to a keyed getter function with a reference to a - property, e.g. foo.getBar(baz) -> foo.bar[baz] - - The function identifier being replaced must be on line `row' and - between `colStart' and `colEnd'. The opening parenthesis must follow - immediately (whitespace is allowed). The closing parenthesis may be on the - same or following lines. - - Throws a ConversionError if the parentheses can't be found. In this case - the content of `lines' will be untouched.""" - try: - replaceNextParens(lines, row, colEnd, newOpenChar = '[', newCloseChar = ']') - except ParseError: - raise ConversionError, ("Deprecated function reference.") - - lines[row] = replaceSubstr(lines[row], colStart, colEnd, newName) - -def replaceGetXYPosition(lines, row, colStart, colEnd, axis): - '''SCA_MouseSensor.getXPosition; SCA_MouseSensor.getYPosition. - This is like a keyed getter, but the key is embedded in the attribute - name. - - Throws a ConversionError if the parentheses can't be found. In this case - the content of `lines' will be untouched.''' - try: - (openRow, openCol), (closeRow, closeCol) = findBalancedParens(lines, - row, colEnd) - except ParseError: - raise ConversionError, "Deprecated function reference." - if closeRow != row: - raise ConversionError, "Can't modify multiple lines." - - lines[row] = replaceSubstr(lines[row], openCol, closeCol + 1, - "[%s]" % axis) - - lines[row] = replaceSubstr(lines[row], colStart, colEnd, 'position') - -def replaceRename(lines, row, colStart, colEnd, newName): - """Replace an identifier with another, e.g. - foo.getBar() -> foo.getBaz() - foo.bar -> foo.baz - - The identifier being replaced must be on line `row' and between `colStart' - and `colEnd'.""" - lines[row] = replaceSubstr(lines[row], colStart, colEnd, newName) - -def replaceAddActiveActuator(lines, row, colStart, colEnd, closure): - '''Extra work needs to be done here to find out the name of the controller, - and whether the actuator should be activated or deactivated. - - Throws a ConversionError if the actuator, controller or condition can't be - found. In this case the content of `lines' will be untouched.''' - try: - (openRow, openCol), (closeRow, closeCol) = findBalancedParens(lines, row, colEnd) - except ParseError: - ConversionError, "Can't find arguments." - - if closeRow != openRow: - raise ConversionError, ("Can't perform conversion: arguments span multiple lines.") - - args = lines[row][openCol + 1:closeCol] - match = re.search(r'([a-zA-Z_]\w*)' # Actuator identifier - r',\s*' - r'([0-9a-zA-Z_]\w*)', # Condition (boolean) - args) - if not match: - raise ConversionError, "Can't find arguments." - - actuator = match.group(1) - condition = match.group(2) - controller = None - - assn = findLastAssignment(lines, row, actuator) - if assn: - match = re.search(r'([a-zA-Z_]\w*)' # Controller identifier - r'\s*\.\s*' # Dot - r'(actuators\s*\[|getActuator\s*\()', # Dictionary/getter identifier - assn) - if match: - controller = match.group(1) - - if not controller: - raise ConversionError, "Can't find actuator's controller." - - gameLogicStart = lines[row].rfind("GameLogic", 0, colStart) - if gameLogicStart < 0: - raise ConversionError, "Can't find GameLogic identifier." - - newExpr = None - if condition in ['1', 'True']: - newExpr = "%s.activate(%s)" % (controller, actuator) - elif condition in ['0', 'False']: - newExpr = "%s.deactivate(%s)" % (controller, actuator) - else: - newExpr = "(lambda: %s and (%s.activate(%s) or True) or %s.deactivate(%s))()" % ( - condition, controller, actuator, controller, actuator) - lines[row] = replaceSubstr(lines[row], gameLogicStart, closeCol + 1, newExpr) - -def getObject(line, attributeStart): - '''Get the object that an attribute belongs to. `attributeStart' is the - index of the first character of the attribute name in the string `line'. - Returns: the identifier preceding `attributeStart', or None if one can't be - found.''' - match = re.search(r'([a-zA-Z_]\w*)\s*\.\s*$', line[0:attributeStart]) - if not match: - return None - return match.group(1) - -def replaceGetActuator(lines, row, colStart, colEnd, closure): - '''getActuator is ambiguous: it could belong to SCA_IController or - SCA_ActuatorSensor. Try to resolve and then convert. - - Raises a ConversionError if the parentheses can't be found, or if the - ambiguity can't be resolved.''' - # Get the name of the object this attribute is attached to. - obName = getObject(lines[row], colStart) - if obName: - # Try to find out whether the object is a controller. - assn = findLastAssignment(lines, row, obName) - if assn and re.search(r'GameLogic\s*\.\s*getCurrentController', assn): - # It is (probably) a controller! - replaceKeyedGetter(lines, row, colStart, colEnd, 'actuators') - return - - raise ConversionError, "Ambiguous: addActiveActuator -> actuators[key] (SCA_IController) or actuator (SCA_ActuatorSensor)." - -def replaceSetOrientation(lines, row, colStart, colEnd, closure): - '''setOrientation is ambiguous: it could belong to KX_SoundActuator or - KX_GameObject. Try to resolve and then convert. If the type can't be - determined, it is assumed to be a KX_GameObject. Currently, only the - conversion for KX_GameObject is implemented. - - Raises a ConversionError if the parentheses can't be found, or if the - object is found to be a KX_SoundActuator.''' - # Get the name of the object this attribute is attached to. - obName = getObject(lines[row], colStart) - if obName: - # Try to find out whether the object is an actuator. - assn = findLastAssignment(lines, row, obName) - if assn: - match = re.search(r'([a-zA-Z_]\w*)' # Controller identifier - r'\s*\.\s*' # Dot - r'(actuators\s*\[|getActuator\s*\()', # Dictionary/getter identifier - assn) - if match: - # It's probably a KX_SoundActuator. - raise ConversionError, "Not implemented: Can't convert arguments to matrix." - - # It's probably a KX_GameObject. - replaceSimpleSetter(lines, row, colStart, colEnd, 'localOrientation') - -def replaceSetPosition(lines, row, colStart, colEnd, closure): - '''setPosition is ambiguous: it could belong to KX_SoundActuator or - KX_GameObject. Try to resolve and then convert. If the type can't be - determined, it is assumed to be a KX_GameObject. - - Raises a ConversionError if the parentheses can't be found.''' - # Get the name of the object this attribute is attached to. - obName = getObject(lines[row], colStart) - if obName: - # Try to find out whether the object is an actuator. - assn = findLastAssignment(lines, row, obName) - if assn: - match = re.search(r'([a-zA-Z_]\w*)' # Controller identifier - r'\s*\.\s*' # Dot - r'(actuators\s*\[|getActuator\s*\()', # Dictionary/getter identifier - assn) - if match: - # It's probably a KX_SoundActuator. - replaceSimpleSetter(lines, row, colStart, colEnd, 'position') - - # It's probably a KX_GameObject. - replaceSimpleSetter(lines, row, colStart, colEnd, 'localPosition') - -def replaceSplitProperty(lines, row, colStart, colEnd, (newGetter, newSetter)): - '''Some property attributes behave differently when being written to or read - from. Try to determine the operation, and replace accordingly. E.G. - o.position = foo -> o.localPosition = foo # set - foo = o.position -> foo = o.worldPosition # get - - This implementation can not handle cases where the object is returned from - a function, e.g. - foo = bar.getObject().position # Error! - - Raises a ConversionError if the operation can't be determined, or if the - object is returned from a function.''' - assnRegex = re.compile(r'(=\s*)?' # Getter - r'[a-zA-Z_]\w*' # Object identifier - r'\.([a-zA-Z_][a-zA-Z0-9_.]*)+' # Trailing attributes - r'(\s*=)?') # Setter - match = assnRegex.search(lines[row]) - - if not match: - raise ConversionError, "Can't determine operation (getting or setting)." - - setting = False - getting = False - if match.group(1): - getting = True - if match.group(3): - setting = True - if (getting and setting) or ((not getting) and (not setting)): - raise ConversionError, "Can't determine operation (getting or setting)." - - if getting: - replaceRename(lines, row, colStart, colEnd, newGetter) - else: - replaceRename(lines, row, colStart, colEnd, newSetter) - -def notImplemented(lines, row, colStart, colEnd, classNames): - message = "Conversion not implemented. See documentation for " +\ - string.join(classNames, ', ') - raise ConversionError, message - -# -# Deprecated attribute information. The format is: -# deprecatedAttributeName: (conversionFunction, closure) -# Usually the closure will be the name of the superceding attribute. -# -# Since each deprecated attribute can appear in this dictionary only once, it is -# the conversion function's responsibility to resolve ambiguity. -# -attributeRenameDict = { - # Special cases - 'addActiveActuator': (replaceAddActiveActuator, None), # - 'getActuator': (replaceGetActuator, None), # SCA_IController, SCA_ActuatorSensor - 'getXPosition': (replaceGetXYPosition, '0'), # SCA_MouseSensor - 'getYPosition': (replaceGetXYPosition, '1'), # SCA_MouseSensor - 'setOrientation': (replaceSetOrientation, None), # KX_GameObject, KX_SoundActuator - 'setPosition': (replaceSetPosition, None), # KX_GameObject, KX_SoundActuator - - # Keyed getters/setters - 'getSensor': (replaceKeyedGetter, 'sensors'), # SCA_IController - - # Multi-arg -> List setter - 'setAxis': (replaceArgsWithListSetter, 'axis'), # SCA_JoystickSensor - 'setForceLimitX': (replaceArgsWithListSetter, 'forceLimitX'), # KX_ObjectActuator - 'setForceLimitY': (replaceArgsWithListSetter, 'forceLimitY'), # KX_ObjectActuator - 'setForceLimitZ': (replaceArgsWithListSetter, 'forceLimitZ'), # KX_ObjectActuator - 'setHat': (replaceArgsWithListSetter, 'hat'), # SCA_JoystickSensor - 'setPID': (replaceArgsWithListSetter, 'pid'), # KX_ObjectActuator - 'setVelocity': (replaceArgsWithListSetter, 'velocity'), # KX_SoundActuator - - # Straight rename - 'getButtonValue': (replaceRename, 'getButtonActiveList'), # SCA_JoystickSensor - - # Split properties - 'scaling': (replaceSplitProperty, ('worldScaling', 'localScaling')), # KX_GameObject - - # Simple getters/setters - 'getSensors': (replaceSimpleGetter, 'sensors'), # SCA_IController - 'getActuators': (replaceSimpleGetter, 'actuators'), # SCA_IController - 'enableViewport': (replaceSimpleSetter, 'useViewport'), # KX_Camera - 'getAction': (replaceSimpleGetter, 'action'), # BL_ShapeActionActuator, BL_ActionActuator - 'getAxis': (replaceSimpleGetter, 'axis'), # SCA_JoystickSensor - 'getAxisValue': (replaceSimpleGetter, 'axisValues'), # SCA_JoystickSensor - 'getBlendin': (replaceSimpleGetter, 'blendIn'), # BL_ShapeActionActuator, BL_ActionActuator - 'getBodies': (replaceSimpleGetter, 'bodies'), # KX_NetworkMessageSensor - 'getButton': (replaceSimpleGetter, 'button'), # SCA_JoystickSensor - 'getCamera': (replaceSimpleGetter, 'camera'), # KX_SceneActuator - 'getConeOrigin': (replaceSimpleGetter, 'coneOrigin'), # KX_RadarSensor - 'getConeTarget': (replaceSimpleGetter, 'coneTarget'), # KX_RadarSensor - 'getContinue': (replaceSimpleGetter, 'useContinue'), # BL_ActionActuator - 'getCurrentlyPressedKeys': (replaceSimpleGetter, 'events'), # SCA_KeyboardSensor - 'getDamping': (replaceSimpleGetter, 'damping'), # KX_ObjectActuator - 'getDelay': (replaceSimpleGetter, 'delay'), # SCA_DelaySensor - 'getDistribution': (replaceSimpleGetter, 'distribution'), # SCA_RandomActuator - 'getDuration': (replaceSimpleGetter, 'duration'), # SCA_DelaySensor - 'getEnd': (replaceSimpleGetter, 'frameEnd'), # BL_ShapeActionActuator, KX_IpoActuator, BL_ActionActuator - 'getExecutePriority': (replaceSimpleGetter, 'executePriority'), # SCA_ILogicBrick - 'getFile': (replaceSimpleGetter, 'fileName'), # KX_GameActuator - 'getFilename': (replaceSimpleGetter, 'fileName'), # KX_SoundActuator - 'getForceIpoActsLocal': (replaceSimpleGetter, 'useIpoLocal'), # KX_IpoActuator - 'getForceLimitX': (replaceSimpleGetter, 'forceLimitX'), # KX_ObjectActuator - 'getForceLimitY': (replaceSimpleGetter, 'forceLimitY'), # KX_ObjectActuator - 'getForceLimitZ': (replaceSimpleGetter, 'forceLimitZ'), # KX_ObjectActuator - 'getFrame': (replaceSimpleGetter, 'frame'), # BL_ShapeActionActuator, BL_ActionActuator - 'getFrameMessageCount': (replaceSimpleGetter, 'frameMessageCount'), # KX_NetworkMessageSensor - 'getFrameProperty': (replaceSimpleGetter, 'framePropName'), # BL_ShapeActionActuator, BL_ActionActuator - 'getFrequency': (replaceSimpleGetter, 'frequency'), # SCA_ISensor - 'getGain': (replaceSimpleGetter, 'volume'), # KX_SoundActuator - 'getHat': (replaceSimpleGetter, 'hat'), # SCA_JoystickSensor - 'getHeight': (replaceSimpleGetter, 'height'), # KX_CameraActuator - 'getHitNormal': (replaceSimpleGetter, 'hitNormal'), # KX_MouseFocusSensor, KX_RaySensor - 'getHitObject': (replaceSimpleGetter, 'hitObject'), # KX_MouseFocusSensor, KX_RaySensor, KX_TouchSensor - 'getHitObjectList': (replaceSimpleGetter, 'hitObjectList'), # KX_TouchSensor - 'getHitPosition': (replaceSimpleGetter, 'hitPosition'), # KX_MouseFocusSensor, KX_RaySensor - 'getHold1': (replaceSimpleGetter, 'hold1'), # SCA_KeyboardSensor - 'getHold2': (replaceSimpleGetter, 'hold2'), # SCA_KeyboardSensor - 'getInvert': (replaceSimpleGetter, 'invert'), # SCA_ISensor - 'getIpoAdd': (replaceSimpleGetter, 'useIpoAdd'), # KX_IpoActuator - 'getIpoAsForce': (replaceSimpleGetter, 'useIpoAsForce'), # KX_IpoActuator - 'getKey': (replaceSimpleGetter, 'key'), # SCA_KeyboardSensor - 'getLastCreatedObject': (replaceSimpleGetter, 'objectLastCreated'), # KX_SCA_AddObjectActuator - 'getLevel': (replaceSimpleGetter, 'level'), # SCA_ISensor - 'getLightList': (replaceSimpleGetter, 'lights'), # KX_Scene - 'getLooping': (replaceSimpleGetter, 'looping'), # KX_SoundActuator - 'getMass': (replaceSimpleGetter, 'mass'), # KX_GameObject - 'getMax': (replaceSimpleGetter, 'max'), # KX_CameraActuator - 'getMin': (replaceSimpleGetter, 'min'), # KX_CameraActuator - 'getName': (replaceSimpleGetter, 'name'), # KX_Scene - 'getNumAxes': (replaceSimpleGetter, 'numAxis'), # SCA_JoystickSensor - 'getNumButtons': (replaceSimpleGetter, 'numButtons'), # SCA_JoystickSensor - 'getNumHats': (replaceSimpleGetter, 'numHats'), # SCA_JoystickSensor - 'getObjectList': (replaceSimpleGetter, 'objects'), # KX_Scene - 'getOperation': (replaceSimpleGetter, 'mode'), # KX_SCA_DynamicActuator - 'getOrientation': (replaceSimpleGetter, 'worldOrientation'), # KX_GameObject - 'getOwner': (replaceSimpleGetter, 'owner'), # SCA_ILogicBrick - 'getPara1': (replaceSimpleGetter, 'para1'), # SCA_RandomActuator - 'getPara2': (replaceSimpleGetter, 'para2'), # SCA_RandomActuator - 'getParent': (replaceSimpleGetter, 'parent'), # KX_GameObject - 'getPID': (replaceSimpleGetter, 'pid'), # KX_ObjectActuator - 'getPitch': (replaceSimpleGetter, 'pitch'), # KX_SoundActuator - 'getPosition': (replaceSimpleGetter, 'worldPosition'), # KX_GameObject - 'getPressedKeys': (replaceSimpleGetter, 'events'), # SCA_KeyboardSensor - 'getPriority': (replaceSimpleGetter, 'priority'), # BL_ShapeActionActuator, BL_ActionActuator - 'getProjectionMatrix': (replaceSimpleGetter, 'projection_matrix'), # KX_Camera - 'getProperty': (replaceSimpleGetter, 'propName'), # SCA_PropertySensor, SCA_RandomActuator, SCA_PropertyActuator - 'getRayDirection': (replaceSimpleGetter, 'rayDirection'), # KX_MouseFocusSensor, KX_RaySensor - 'getRaySource': (replaceSimpleGetter, 'raySource'), # KX_MouseFocusSensor - 'getRayTarget': (replaceSimpleGetter, 'rayTarget'), # KX_MouseFocusSensor - 'getRepeat': (replaceSimpleGetter, 'repeat'), # SCA_DelaySensor - 'getRollOffFactor': (replaceSimpleGetter, 'rollOffFactor'), # KX_SoundActuator - 'getScene': (replaceSimpleGetter, 'scene'), # KX_SceneActuator - 'getScript': (replaceSimpleGetter, 'script'), # SCA_PythonController - 'getSeed': (replaceSimpleGetter, 'seed'), # SCA_RandomActuator - 'getStart': (replaceSimpleGetter, 'frameStart'), # BL_ShapeActionActuator, KX_IpoActuator, BL_ActionActuator - 'getState': (replaceSimpleGetter, 'state'), # SCA_IController, KX_GameObject - 'getSubject': (replaceSimpleGetter, 'subject'), # KX_NetworkMessageSensor - 'getSubjects': (replaceSimpleGetter, 'subjects'), # KX_NetworkMessageSensor - 'getThreshold': (replaceSimpleGetter, 'threshold'), # SCA_JoystickSensor - 'getTime': (replaceSimpleGetter, 'time'), # KX_SCA_AddObjectActuator, KX_TrackToActuator - 'getTouchMaterial': (replaceSimpleGetter, 'useMaterial'), # KX_TouchSensor - 'getType': (replaceSimpleGetter, 'mode'), # SCA_PropertySensor - 'getUse3D': (replaceSimpleGetter, 'use3D'), # KX_TrackToActuator - 'getUseNegPulseMode': (replaceSimpleGetter, 'useNegPulseMode'), # SCA_ISensor - 'getUsePosPulseMode': (replaceSimpleGetter, 'usePosPulseMode'), # SCA_ISensor - 'getUseRestart': (replaceSimpleGetter, 'useRestart'), # KX_SceneActuator - 'getValue': (replaceSimpleGetter, 'value'), # SCA_PropertySensor, SCA_PropertyActuator - 'getVisible': (replaceSimpleGetter, 'visible'), # KX_GameObject - 'getXY': (replaceSimpleGetter, 'useXY'), # KX_CameraActuator - 'isConnected': (replaceSimpleGetter, 'connected'), # SCA_JoystickSensor - 'isPositive': (replaceSimpleGetter, 'positive'), # SCA_ISensor - 'isTriggered': (replaceSimpleGetter, 'triggered'), # SCA_ISensor - 'setActuator': (replaceSimpleSetter, 'actuator'), # SCA_ActuatorSensor - 'setBlendin': (replaceSimpleSetter, 'blendIn'), # BL_ShapeActionActuator, BL_ActionActuator - 'setBlendtime': (replaceSimpleSetter, 'blendTime'), # BL_ShapeActionActuator, BL_ActionActuator - 'setBodyType': (replaceSimpleSetter, 'usePropBody'), # KX_NetworkMessageActuator - 'setBody': (replaceSimpleSetter, 'body'), # KX_NetworkMessageActuator - 'setButton': (replaceSimpleSetter, 'button'), # SCA_JoystickSensor - 'setCamera': (replaceSimpleSetter, 'camera'), # KX_SceneActuator - 'setContinue': (replaceSimpleSetter, 'useContinue'), # BL_ActionActuator - 'setDamping': (replaceSimpleSetter, 'damping'), # KX_ObjectActuator - 'setDelay': (replaceSimpleSetter, 'delay'), # SCA_DelaySensor - 'setDuration': (replaceSimpleSetter, 'duration'), # SCA_DelaySensor - 'setEnd': (replaceSimpleSetter, 'frameEnd'), # BL_ShapeActionActuator, KX_IpoActuator, BL_ActionActuator - 'setExecutePriority': (replaceSimpleSetter, 'executePriority'), # SCA_ILogicBrick - 'setFile': (replaceSimpleSetter, 'fileName'), # KX_GameActuator - 'setFilename': (replaceSimpleSetter, 'fileName'), # KX_SoundActuator - 'setForceIpoActsLocal': (replaceSimpleSetter, 'useIpoLocal'), # KX_IpoActuator - 'setFrame': (replaceSimpleSetter, 'frame'), # BL_ShapeActionActuator, BL_ActionActuator - 'setFrameProperty': (replaceSimpleSetter, 'framePropName'), # BL_ShapeActionActuator, BL_ActionActuator - 'setFrequency': (replaceSimpleSetter, 'frequency'), # SCA_ISensor - 'setGain': (replaceSimpleSetter, 'volume'), # KX_SoundActuator - 'setHeight': (replaceSimpleSetter, 'height'), # KX_CameraActuator - 'setHold1': (replaceSimpleSetter, 'hold1'), # SCA_KeyboardSensor - 'setHold2': (replaceSimpleSetter, 'hold2'), # SCA_KeyboardSensor - 'setInvert': (replaceSimpleSetter, 'invert'), # SCA_ISensor - 'setIpoAdd': (replaceSimpleSetter, 'useIpoAdd'), # KX_IpoActuator - 'setIpoAsForce': (replaceSimpleSetter, 'useIpoAsForce'), # KX_IpoActuator - 'setKey': (replaceSimpleSetter, 'key'), # SCA_KeyboardSensor - 'setLevel': (replaceSimpleSetter, 'level'), # SCA_ISensor - 'setLooping': (replaceSimpleSetter, 'looping'), # KX_SoundActuator - 'setMask': (replaceSimpleSetter, 'mask'), # KX_StateActuator - 'setMax': (replaceSimpleSetter, 'max'), # KX_CameraActuator - 'setMesh': (replaceSimpleSetter, 'mesh'), # KX_SCA_ReplaceMeshActuator - 'setMin': (replaceSimpleSetter, 'min'), # KX_CameraActuator - 'setPitch': (replaceSimpleSetter, 'pitch'), # KX_SoundActuator - 'setPriority': (replaceSimpleSetter, 'priority'), # BL_ShapeActionActuator, BL_ActionActuator - 'setProjectionMatrix': (replaceSimpleSetter, 'projection_matrix'), # KX_Camera - 'setProperty': (replaceSimpleSetter, 'propName'), # KX_IpoActuator, SCA_PropertySensor, SCA_RandomActuator, SCA_PropertyActuator - 'setRepeat': (replaceSimpleSetter, 'repeat'), # SCA_DelaySensor - 'setRollOffFactor': (replaceSimpleSetter, 'rollOffFactor'), # KX_SoundActuator - 'setScene': (replaceSimpleSetter, 'scene'), # KX_SceneActuator - 'setScript': (replaceSimpleSetter, 'script'), # SCA_PythonController - 'setSeed': (replaceSimpleSetter, 'seed'), # SCA_RandomActuator - 'setStart': (replaceSimpleSetter, 'frameStart'), # BL_ShapeActionActuator, KX_IpoActuator, BL_ActionActuator - 'setState': (replaceSimpleSetter, 'state'), # KX_GameObject - 'setSubject': (replaceSimpleSetter, 'subject'), # KX_NetworkMessageActuator - 'setSubjectFilterText': (replaceSimpleSetter, 'subject'), # KX_NetworkMessageSensor - 'setThreshold': (replaceSimpleSetter, 'threshold'), # SCA_JoystickSensor - 'setTime': (replaceSimpleSetter, 'time'), # KX_SCA_AddObjectActuator, KX_TrackToActuator - 'setToPropName': (replaceSimpleSetter, 'propName'), # KX_NetworkMessageActuator - 'setType': (replaceSimpleSetter, 'mode'), # SCA_PropertySensor - 'setUse3D': (replaceSimpleSetter, 'use3D'), # KX_TrackToActuator - 'setUseNegPulseMode': (replaceSimpleSetter, 'useNegPulseMode'), # SCA_ISensor - 'setUsePosPulseMode': (replaceSimpleSetter, 'usePosPulseMode'), # SCA_ISensor - 'setUseRestart': (replaceSimpleSetter, 'useRestart'), # KX_SceneActuator - 'setValue': (replaceSimpleSetter, 'value'), # SCA_PropertySensor, SCA_PropertyActuator - 'setXY': (replaceSimpleSetter, 'useXY'), # KX_CameraActuator - - # Unimplemented! - 'getLinearVelocity': (notImplemented, ['KX_SCA_AddObjectActuator', 'KX_GameObject']), - 'setLinearVelocity': (notImplemented, ['KX_SCA_AddObjectActuator', 'KX_GameObject']), - 'getAngularVelocity': (notImplemented, ['KX_SCA_AddObjectActuator', 'KX_GameObject']), - 'setAngularVelocity': (notImplemented, ['KX_SCA_AddObjectActuator', 'KX_GameObject']), - 'setAction': (notImplemented, ['BL_ShapeActionActuator', 'BL_ActionActuator']), - 'set': (notImplemented, ['KX_VisibilityActuator', 'KX_IpoActuator']), - 'getIndex': (notImplemented, ['SCA_JoystickSensor']), - 'getMesh': (notImplemented, ['KX_SCA_ReplaceMeshActuator']), - 'getObject': (notImplemented, ['KX_SCA_AddObjectActuator', 'KX_CameraActuator', 'KX_TrackToActuator', 'KX_ParentActuator']), - 'setIndex': (notImplemented, ['SCA_JoystickSensor']), - 'setObject': (notImplemented, ['KX_SCA_AddObjectActuator', 'KX_CameraActuator', 'KX_TrackToActuator', 'KX_ParentActuator']), - 'setOperation': (notImplemented, ['KX_SCA_DynamicActuator', 'KX_StateActuator']), - 'position': (notImplemented, ['KX_GameObject', 'KX_SoundActuator']), - 'orientation': (notImplemented, ['KX_GameObject', 'KX_SoundActuator']), - 'getDRot': (notImplemented, ['KX_ObjectActuator']), - 'setDRot': (notImplemented, ['KX_ObjectActuator']), - 'getDLoc': (notImplemented, ['KX_ObjectActuator']), - 'setDLoc': (notImplemented, ['KX_ObjectActuator']), - 'getTorque': (notImplemented, ['KX_ObjectActuator']), - 'getTorque': (notImplemented, ['KX_ObjectActuator']), - 'getForce': (notImplemented, ['KX_ObjectActuator']), - 'setForce': (notImplemented, ['KX_ObjectActuator']), -} - -def convert248to249(lines, log = True, logErrors = True, fileName = None): - # Regular expression for finding attributes. For the string 'a.b', this - # returns three groups: ['a.b', 'a.', 'b']. The last is the attribute name. - attrRegex = re.compile(r'\.\s*' # Dot - r'([a-zA-Z_]\w*)') # Identifier - - fileIdStr = "" - if fileName: - fileIdStr = fileName + ": " - row = 0 - col = 0 - nconverted = 0 - nerrors = 0 - while row < len(lines): - originalLine = lines[row] - changed = False - while col < len(lines[row]): - # Don't search past comment. We have to check each iteration - # because the line contents may have changed. - commentStart = lines[row].find('#', col) - if commentStart < 0: - commentStart = len(lines[row]) - - # Search for an attribute identifier. - match = attrRegex.search(lines[row], col, commentStart) - if not match: - break - - attrName = match.group(1) - if attributeRenameDict.has_key(attrName): - # name is deprecated. - func, closure = attributeRenameDict[attrName] - try: - # Convert! - func(lines, row, match.start(1), match.end(1), closure) - except ConversionError, e: - # Insert a comment saying the conversion failed. - print "ERROR: %sline %d, %s: %s\n" % ( - fileIdStr, row + 1, attrName, e) - if logErrors: - lines.insert(row, - "##248## ERROR: %s: %s\n" % - (attrName, e)) - row = row + 1 - nerrors = nerrors + 1 - else: - changed = True - nconverted = nconverted + 1 - # Search the rest of this line. - col = match.start(1) - - if changed and log: - # Insert a comment to showing difference in lines. - if originalLine[-1] != '\n': - originalLine = originalLine + '\n' - lines.insert(row, "##248##%s" % originalLine) - row = row + 1 - - row = row + 1 - col = 0 - return nconverted, nerrors - -def usage(): - print "Usage: blender248to249.py [options] <infile> [outfile]" - print "Options:" - print "\t--nolog Don't include old lines as comments." - print "\t--quieterrors Don't insert errors as comments." - -def runAsConsoleScript(): - '''Called when being run as a console script.''' - try: - opts, args = getopt.getopt(sys.argv[1:], "", ["nolog", "quieterrors"]) - except getopt.GetoptError, err: - # print help information and exit: - print str(err) - usage() - sys.exit(2) - - log = True - logErrors = True - for o, a in opts: - if o == "--nolog": - log = False - elif o == "--quieterrors": - logErrors = False - - try: - inpath = args.pop(0) - except IndexError: - usage() - sys.exit(2) - try: - outpath = args.pop(0) - except IndexError: - outpath = inpath - - infile = io.FileIO(inpath, 'r') - # arbitrary file size of around 100kB - lines = infile.readlines(100000) - infile.close() - - nconverted, nerrors = convert248to249(lines, log, logErrors) - - outfile = io.FileIO(outpath, 'w') - outfile.writelines(lines) - outfile.close() - print "Conversion finished. Modified %d attributes." % nconverted - print "There were %d errors." % nerrors - print "Please review all the changes." - -def runAsTextPlugin(): - '''Called when run as a text plugin.''' - - import Blender - from Blender import Window, sys, Draw - import BPyTextPlugin, bpy - - message = ("Convert Game Engine script from 4.48 API to 2.49 API%t|" - "Run on active script only%x1|" - "Run on ALL text buffers%x2") - convertAllBuffers = Draw.PupMenu(message) == 2 - - Window.WaitCursor(1) - try: - nconverted = 0 - nerrors = 0 - - if convertAllBuffers: - texts = bpy.data.texts - else: - if not bpy.data.texts.active: - Draw.PupMenu("No active buffer.") - return - texts = [bpy.data.texts.active] - - Blender.SaveUndoState('Convert BGE 2.49') - - for txt in texts: - bufName = txt.name - if txt.lib: - bufName = txt.lib + '/' + bufName - lines = txt.asLines() - for i in range(0, len(lines)): - if not lines[i].endswith('\n'): - lines[i] = lines[i] + '\n' - - nc, ne = convert248to249(lines, fileName = bufName) - nconverted = nconverted + nc - nerrors = nerrors + ne - txt.clear() - for line in lines: - txt.write(line) - - finally: - Window.WaitCursor(0) - - message = "Converted %d attributes." % nconverted - if nerrors == 1: - message = message + " There was 1 error (see console)." - if nerrors > 1: - message = message + " There were %d errors (see console)." % nerrors - message = message + "|Please review all the changes." - Draw.PupMenu(message) - -def main(): - try: - import Blender - except ImportError: - runAsConsoleScript() - else: - runAsTextPlugin() - -# This lets you import the script without running it -if __name__ == "__main__": - import sys - import getopt - import io - main() diff --git a/release/scripts/textplugin_functiondocs.py b/release/scripts/textplugin_functiondocs.py deleted file mode 100644 index 41c8d4842a0..00000000000 --- a/release/scripts/textplugin_functiondocs.py +++ /dev/null @@ -1,64 +0,0 @@ -#!BPY -""" -Name: 'Function Documentation | Ctrl I' -Blender: 246 -Group: 'TextPlugin' -Shortcut: 'Ctrl+I' -Tooltip: 'Attempts to display documentation about the function preceding the cursor.' -""" - -# Only run if we have the required modules -try: - import bpy - from BPyTextPlugin import * -except ImportError: - OK = False -else: - OK = True - -def main(): - txt = bpy.data.texts.active - if not txt: - return - - (line, c) = current_line(txt) - - # Check we are in a normal context - if get_context(txt) != CTX_NORMAL: - return - - # Identify the name under the cursor - llen = len(line) - while c<llen and (line[c].isalnum() or line[c]=='_'): - c += 1 - - targets = get_targets(line, c) - - # If no name under cursor, look backward to see if we're in function parens - if len(targets) == 0 or targets[0] == '': - # Look backwards for first '(' without ')' - b = 0 - found = False - for i in range(c-1, -1, -1): - if line[i] == ')': b += 1 - elif line[i] == '(': - b -= 1 - if b < 0: - found = True - c = i - break - if found: targets = get_targets(line, c) - if len(targets) == 0 or targets[0] == '': - return - - obj = resolve_targets(txt, targets) - if not obj: return - - if isinstance(obj, Definition): # Local definition - txt.showDocs(obj.doc) - elif hasattr(obj, '__doc__') and obj.__doc__: - txt.showDocs(obj.__doc__) - -# Check we are running as a script and not imported as a module -if __name__ == "__main__" and OK: - main() diff --git a/release/scripts/textplugin_imports.py b/release/scripts/textplugin_imports.py deleted file mode 100644 index ec608243c2b..00000000000 --- a/release/scripts/textplugin_imports.py +++ /dev/null @@ -1,91 +0,0 @@ -#!BPY -""" -Name: 'Import Complete|Space' -Blender: 246 -Group: 'TextPlugin' -Shortcut: 'Space' -Tooltip: 'Lists modules when import or from is typed' -""" - -# Only run if we have the required modules -try: - import bpy, sys - from BPyTextPlugin import * -except ImportError: - OK = False -else: - OK = True - -def main(): - txt = bpy.data.texts.active - if not txt: - return - - line, c = current_line(txt) - - # Check we are in a normal context - if get_context(txt) != CTX_NORMAL: - return - - pos = line.rfind('from ', 0, c) - - # No 'from' found - if pos == -1: - # Check instead for straight 'import xxxx' - pos2 = line.rfind('import ', 0, c) - if pos2 != -1: - pos2 += 7 - for i in range(pos2, c): - if line[i]==',' or (line[i]==' ' and line[i-1]==','): - pos2 = i+1 - elif not line[i].isalnum() and line[i] != '_': - return - items = [(m, 'm') for m in get_modules()] - items.sort(cmp = suggest_cmp) - txt.suggest(items, line[pos2:c].strip()) - return - - # Found 'from xxxxx' before cursor - immediate = True - pos += 5 - for i in range(pos, c): - if not line[i].isalnum() and line[i] != '_' and line[i] != '.': - immediate = False - break - - # Immediate 'from' followed by at most a module name - if immediate: - items = [(m, 'm') for m in get_modules()] - items.sort(cmp = suggest_cmp) - txt.suggest(items, line[pos:c]) - return - - # Found 'from' earlier, suggest import if not already there - pos2 = line.rfind('import ', pos, c) - - # No 'import' found after 'from' so suggest it - if pos2 == -1: - txt.suggest([('import', 'k')], '') - return - - # Immediate 'import' before cursor and after 'from...' - for i in range(pos2+7, c): - if line[i]==',' or (line[i]==' ' and line[i-1]==','): - pass - elif not line[i].isalnum() and line[i] != '_': - return - between = line[pos:pos2-1].strip() - try: - mod = get_module(between) - except ImportError: - return - - items = [('*', 'k')] - for (k,v) in mod.__dict__.items(): - items.append((k, type_char(v))) - items.sort(cmp = suggest_cmp) - txt.suggest(items, '') - -# Check we are running as a script and not imported as a module -if __name__ == "__main__" and OK: - main() diff --git a/release/scripts/textplugin_membersuggest.py b/release/scripts/textplugin_membersuggest.py deleted file mode 100644 index 7c0de78b704..00000000000 --- a/release/scripts/textplugin_membersuggest.py +++ /dev/null @@ -1,90 +0,0 @@ -#!BPY -""" -Name: 'Member Suggest | .' -Blender: 246 -Group: 'TextPlugin' -Shortcut: 'Period' -Tooltip: 'Lists members of the object preceding the cursor in the current text space' -""" - -# Only run if we have the required modules -try: - import bpy - from BPyTextPlugin import * -except ImportError: - OK = False -else: - OK = True - -def main(): - txt = bpy.data.texts.active - if not txt: - return - - (line, c) = current_line(txt) - - # Check we are in a normal context - if get_context(txt) != CTX_NORMAL: - return - - targets = get_targets(line, c) - - if targets[0] == '': # Check if we are looking at a constant [] {} '' etc. - i = c - len('.'.join(targets)) - 1 - if i >= 0: - if line[i] == '"' or line[i] == "'": - targets[0] = 'str' - elif line[i] == '}': - targets[0] = 'dict' - elif line[i] == ']': # Could be array elem x[y] or list [y] - i = line.rfind('[', 0, i) - 1 - while i >= 0: - if line[i].isalnum() or line[i] == '_': - break - elif line[i] != ' ' and line[i] != '\t': - i = -1 - break - i -= 1 - if i < 0: - targets[0] = 'list' - - obj = resolve_targets(txt, targets[:-1]) - if not obj: - return - - items = [] - - if isinstance(obj, VarDesc): - obj = obj.type - - if isinstance(obj, Definition): # Locally defined - if hasattr(obj, 'classes'): - items.extend([(s, 'f') for s in obj.classes.keys()]) - if hasattr(obj, 'defs'): - items.extend([(s, 'f') for s in obj.defs.keys()]) - if hasattr(obj, 'vars'): - items.extend([(s, 'v') for s in obj.vars.keys()]) - - else: # Otherwise we have an imported or builtin object - try: - attr = obj.__dict__.keys() - except AttributeError: - attr = dir(obj) - else: - if not attr: attr = dir(obj) - - for k in attr: - try: - v = getattr(obj, k) - except (AttributeError, TypeError): # Some attributes are not readable - pass - else: - items.append((k, type_char(v))) - - if items != []: - items.sort(cmp = suggest_cmp) - txt.suggest(items, targets[-1]) - -# Check we are running as a script and not imported as a module -if __name__ == "__main__" and OK: - main() diff --git a/release/scripts/textplugin_outliner.py b/release/scripts/textplugin_outliner.py deleted file mode 100644 index 3879a2819a5..00000000000 --- a/release/scripts/textplugin_outliner.py +++ /dev/null @@ -1,142 +0,0 @@ -#!BPY -""" -Name: 'Code Outline | Ctrl T' -Blender: 246 -Group: 'TextPlugin' -Shortcut: 'Ctrl+T' -Tooltip: 'Provides a menu for jumping to class and functions definitions.' -""" - -# Only run if we have the required modules -try: - import bpy - from BPyTextPlugin import * - from Blender import Draw -except ImportError: - OK = False -else: - OK = True - -def make_menu(items, eventoffs): - n = len(items) - if n < 20: - return [(items[i], i+1+eventoffs) for i in range(len(items))] - - letters = [] - check = 'abcdefghijklmnopqrstuvwxyz_' # Names cannot start 0-9 - for c in check: - for item in items: - if item[0].lower() == c: - letters.append(c) - break - - entries = {} - i = 0 - for item in items: - i += 1 - c = item[0].lower() - entries.setdefault(c, []).append((item, i+eventoffs)) - - subs = [] - for c in letters: - subs.append((c, entries[c])) - - return subs - -def find_word(txt, word): - i = 0 - txt.reset() - while True: - try: - line = txt.readline() - except StopIteration: - break - c = line.find(word) - if c != -1: - txt.setCursorPos(i, c) - break - i += 1 - -def main(): - txt = bpy.data.texts.active - if not txt: - return - - # Identify word under cursor - if get_context(txt) == CTX_NORMAL: - line, c = current_line(txt) - start = c-1 - end = c - while start >= 0: - if not line[start].lower() in 'abcdefghijklmnopqrstuvwxyz0123456789_': - break - start -= 1 - while end < len(line): - if not line[end].lower() in 'abcdefghijklmnopqrstuvwxyz0123456789_': - break - end += 1 - word = line[start+1:end] - if word in KEYWORDS: - word = None - else: - word = None - - script = get_cached_descriptor(txt) - items = [] - desc = None - - tmp = script.classes.keys() - tmp.sort(cmp = suggest_cmp) - class_menu = make_menu(tmp, len(items)) - class_menu_length = len(tmp) - items.extend(tmp) - - tmp = script.defs.keys() - tmp.sort(cmp = suggest_cmp) - defs_menu = make_menu(tmp, len(items)) - defs_menu_length = len(tmp) - items.extend(tmp) - - tmp = script.vars.keys() - tmp.sort(cmp = suggest_cmp) - vars_menu = make_menu(tmp, len(items)) - vars_menu_length = len(tmp) - items.extend(tmp) - - menu = [('Script %t', 0), - ('Classes', class_menu), - ('Functions', defs_menu), - ('Variables', vars_menu)] - if word: - menu.extend([None, ('Locate', [(word, -10)])]) - - i = Draw.PupTreeMenu(menu) - if i == -1: - return - - # Chosen to search for word under cursor - if i == -10: - if script.classes.has_key(word): - desc = script.classes[word] - elif script.defs.has_key(word): - desc = script.defs[word] - elif script.vars.has_key(word): - desc = script.vars[word] - else: - find_word(txt, word) - return - else: - i -= 1 - if i < class_menu_length: - desc = script.classes[items[i]] - elif i < class_menu_length + defs_menu_length: - desc = script.defs[items[i]] - elif i < class_menu_length + defs_menu_length + vars_menu_length: - desc = script.vars[items[i]] - - if desc: - txt.setCursorPos(desc.lineno-1, 0) - -# Check we are running as a script and not imported as a module -if __name__ == "__main__" and OK: - main() diff --git a/release/scripts/textplugin_suggest.py b/release/scripts/textplugin_suggest.py deleted file mode 100644 index d8122212d3b..00000000000 --- a/release/scripts/textplugin_suggest.py +++ /dev/null @@ -1,94 +0,0 @@ -#!BPY -""" -Name: 'Suggest All | Ctrl Space' -Blender: 246 -Group: 'TextPlugin' -Shortcut: 'Ctrl+Space' -Tooltip: 'Performs suggestions based on the context of the cursor' -""" - -# Only run if we have the required modules -try: - import bpy - from BPyTextPlugin import * -except ImportError: - OK = False -else: - OK = True - -def check_membersuggest(line, c): - pos = line.rfind('.', 0, c) - if pos == -1: - return False - for s in line[pos+1:c]: - if not s.isalnum() and s != '_': - return False - return True - -def check_imports(line, c): - pos = line.rfind('import ', 0, c) - if pos > -1: - for s in line[pos+7:c]: - if not s.isalnum() and s != '_': - return False - return True - pos = line.rfind('from ', 0, c) - if pos > -1: - for s in line[pos+5:c]: - if not s.isalnum() and s != '_': - return False - return True - return False - -def main(): - txt = bpy.data.texts.active - if not txt: - return - - line, c = current_line(txt) - - # Check we are in a normal context - if get_context(txt) != CTX_NORMAL: - return - - # Check the character preceding the cursor and execute the corresponding script - - if check_membersuggest(line, c): - import textplugin_membersuggest - textplugin_membersuggest.main() - return - - elif check_imports(line, c): - import textplugin_imports - textplugin_imports.main() - return - - # Otherwise we suggest globals, keywords, etc. - list = [] - targets = get_targets(line, c) - desc = get_cached_descriptor(txt) - - for k in KEYWORDS: - list.append((k, 'k')) - - for k, v in get_builtins().items(): - list.append((k, type_char(v))) - - for k, v in desc.imports.items(): - list.append((k, type_char(v))) - - for k, v in desc.classes.items(): - list.append((k, 'f')) - - for k, v in desc.defs.items(): - list.append((k, 'f')) - - for k, v in desc.vars.items(): - list.append((k, 'v')) - - list.sort(cmp = suggest_cmp) - txt.suggest(list, targets[-1]) - -# Check we are running as a script and not imported as a module -if __name__ == "__main__" and OK: - main() diff --git a/release/scripts/textplugin_templates.py b/release/scripts/textplugin_templates.py deleted file mode 100644 index 8f949563ac0..00000000000 --- a/release/scripts/textplugin_templates.py +++ /dev/null @@ -1,123 +0,0 @@ -#!BPY -""" -Name: 'Template Completion | Tab' -Blender: 246 -Group: 'TextPlugin' -Shortcut: 'Tab' -Tooltip: 'Completes templates based on the text preceding the cursor' -""" - -# Only run if we have the required modules -try: - import bpy - from BPyTextPlugin import * - from Blender import Text -except ImportError: - OK = False -else: - OK = True - -templates = { - 'ie': - 'if ${1:cond}:\n' - '\t${2}\n' - 'else:\n' - '\t${3}\n', - 'iei': - 'if ${1:cond}:\n' - '\t${2}\n' - 'elif:\n' - '\t${3}\n' - 'else:\n' - '\t${4}\n', - 'def': - 'def ${1:name}(${2:params}):\n' - '\t"""(${2}) - ${3:comment}"""\n' - '\t${4}', - 'cls': - 'class ${1:name}(${2:parent}):\n' - '\t"""${3:docs}"""\n' - '\t\n' - '\tdef __init__(self, ${4:params}):\n' - '\t\t"""Creates a new ${1}"""\n' - '\t\t${5}', - 'class': - 'class ${1:name}(${2:parent}):\n' - '\t"""${3:docs}"""\n' - '\t\n' - '\tdef __init__(self, ${4:params}):\n' - '\t\t"""Creates a new ${1}"""\n' - '\t\t${5}' -} - -def main(): - txt = bpy.data.texts.active - if not txt: - return - - row, c = txt.getCursorPos() - line = txt.asLines(row, row+1)[0] - indent=0 - while indent<c and (line[indent]==' ' or line[indent]=='\t'): - indent += 1 - - # Check we are in a normal context - if get_context(txt) != CTX_NORMAL: - return - - targets = get_targets(line, c-1); - if len(targets) != 1: return - - color = (0, 192, 32) - - for trigger, template in templates.items(): - if trigger != targets[0]: continue - inserts = {} - txt.delete(-len(trigger)-1) - y, x = txt.getCursorPos() - first = None - - # Insert template text and parse for insertion points - count = len(template); i = 0 - while i < count: - if i<count-1 and template[i]=='$' and template[i+1]=='{': - i += 2 - e = template.find('}', i) - item = template[i:e].split(':') - if len(item)<2: item.append('') - if not inserts.has_key(item[0]): - inserts[item[0]] = (item[1], [(x, y)]) - else: - inserts[item[0]][1].append((x, y)) - item[1] = inserts[item[0]][0] - if not first: first = (item[1], x, y) - txt.insert(item[1]) - x += len(item[1]) - i = e - else: - txt.insert(template[i]) - if template[i] == '\n': - txt.insert(line[:indent]) - y += 1 - x = indent - else: - x += 1 - i += 1 - - # Insert markers at insertion points - for id, (text, points) in inserts.items(): - for x, y in points: - txt.setCursorPos(y, x) - txt.setSelectPos(y, x+len(text)) - txt.markSelection((hash(text)+int(id)) & 0xFFFF, color, - Text.TMARK_TEMP | Text.TMARK_EDITALL) - if first: - text, x, y = first - txt.setCursorPos(y, x) - txt.setSelectPos(y, x+len(text)) - break - - -# Check we are running as a script and not imported as a module -if __name__ == "__main__" and OK: - main() diff --git a/release/ui/bpy_ops.py b/release/scripts/ui/bpy_ops.py index 83c2e82bf6c..83c2e82bf6c 100644 --- a/release/ui/bpy_ops.py +++ b/release/scripts/ui/bpy_ops.py diff --git a/release/ui/buttons_data_armature.py b/release/scripts/ui/buttons_data_armature.py index 9344294ff9e..9344294ff9e 100644 --- a/release/ui/buttons_data_armature.py +++ b/release/scripts/ui/buttons_data_armature.py diff --git a/release/ui/buttons_data_bone.py b/release/scripts/ui/buttons_data_bone.py index 50ece679e27..50ece679e27 100644 --- a/release/ui/buttons_data_bone.py +++ b/release/scripts/ui/buttons_data_bone.py diff --git a/release/ui/buttons_data_camera.py b/release/scripts/ui/buttons_data_camera.py index 19d7dfef852..19d7dfef852 100644 --- a/release/ui/buttons_data_camera.py +++ b/release/scripts/ui/buttons_data_camera.py diff --git a/release/ui/buttons_data_curve.py b/release/scripts/ui/buttons_data_curve.py index c715cfb5d93..c715cfb5d93 100644 --- a/release/ui/buttons_data_curve.py +++ b/release/scripts/ui/buttons_data_curve.py diff --git a/release/ui/buttons_data_empty.py b/release/scripts/ui/buttons_data_empty.py index c07f3136fae..c07f3136fae 100644 --- a/release/ui/buttons_data_empty.py +++ b/release/scripts/ui/buttons_data_empty.py diff --git a/release/ui/buttons_data_lamp.py b/release/scripts/ui/buttons_data_lamp.py index 86ca5beb9b5..86ca5beb9b5 100644 --- a/release/ui/buttons_data_lamp.py +++ b/release/scripts/ui/buttons_data_lamp.py diff --git a/release/ui/buttons_data_lattice.py b/release/scripts/ui/buttons_data_lattice.py index bc977860330..bc977860330 100644 --- a/release/ui/buttons_data_lattice.py +++ b/release/scripts/ui/buttons_data_lattice.py diff --git a/release/ui/buttons_data_mesh.py b/release/scripts/ui/buttons_data_mesh.py index 780ae3ac8f9..780ae3ac8f9 100644 --- a/release/ui/buttons_data_mesh.py +++ b/release/scripts/ui/buttons_data_mesh.py diff --git a/release/ui/buttons_data_metaball.py b/release/scripts/ui/buttons_data_metaball.py index 757546fdf8a..757546fdf8a 100644 --- a/release/ui/buttons_data_metaball.py +++ b/release/scripts/ui/buttons_data_metaball.py diff --git a/release/ui/buttons_data_modifier.py b/release/scripts/ui/buttons_data_modifier.py index 754e8ce106e..754e8ce106e 100644 --- a/release/ui/buttons_data_modifier.py +++ b/release/scripts/ui/buttons_data_modifier.py diff --git a/release/ui/buttons_data_text.py b/release/scripts/ui/buttons_data_text.py index 0d46d5f8a0d..0d46d5f8a0d 100644 --- a/release/ui/buttons_data_text.py +++ b/release/scripts/ui/buttons_data_text.py diff --git a/release/ui/buttons_game.py b/release/scripts/ui/buttons_game.py index 5f5d4f916d0..5f5d4f916d0 100644 --- a/release/ui/buttons_game.py +++ b/release/scripts/ui/buttons_game.py diff --git a/release/ui/buttons_material.py b/release/scripts/ui/buttons_material.py index 448cb36e130..448cb36e130 100644 --- a/release/ui/buttons_material.py +++ b/release/scripts/ui/buttons_material.py diff --git a/release/ui/buttons_object.py b/release/scripts/ui/buttons_object.py index 9e043cfeaf3..9e043cfeaf3 100644 --- a/release/ui/buttons_object.py +++ b/release/scripts/ui/buttons_object.py diff --git a/release/ui/buttons_object_constraint.py b/release/scripts/ui/buttons_object_constraint.py index e089cff264f..e089cff264f 100644 --- a/release/ui/buttons_object_constraint.py +++ b/release/scripts/ui/buttons_object_constraint.py diff --git a/release/ui/buttons_particle.py b/release/scripts/ui/buttons_particle.py index e72bd38e563..e72bd38e563 100644 --- a/release/ui/buttons_particle.py +++ b/release/scripts/ui/buttons_particle.py diff --git a/release/ui/buttons_physics_cloth.py b/release/scripts/ui/buttons_physics_cloth.py index f6493951a34..f6493951a34 100644 --- a/release/ui/buttons_physics_cloth.py +++ b/release/scripts/ui/buttons_physics_cloth.py diff --git a/release/ui/buttons_physics_field.py b/release/scripts/ui/buttons_physics_field.py index 7d14690856a..7d14690856a 100644 --- a/release/ui/buttons_physics_field.py +++ b/release/scripts/ui/buttons_physics_field.py diff --git a/release/ui/buttons_physics_fluid.py b/release/scripts/ui/buttons_physics_fluid.py index e178a831ddd..e178a831ddd 100644 --- a/release/ui/buttons_physics_fluid.py +++ b/release/scripts/ui/buttons_physics_fluid.py diff --git a/release/ui/buttons_physics_smoke.py b/release/scripts/ui/buttons_physics_smoke.py index 1541b0bae14..1541b0bae14 100644 --- a/release/ui/buttons_physics_smoke.py +++ b/release/scripts/ui/buttons_physics_smoke.py diff --git a/release/ui/buttons_physics_softbody.py b/release/scripts/ui/buttons_physics_softbody.py index 3bdbb1b8b90..3bdbb1b8b90 100644 --- a/release/ui/buttons_physics_softbody.py +++ b/release/scripts/ui/buttons_physics_softbody.py diff --git a/release/ui/buttons_scene.py b/release/scripts/ui/buttons_scene.py index 8bb172e8cd1..8bb172e8cd1 100644 --- a/release/ui/buttons_scene.py +++ b/release/scripts/ui/buttons_scene.py diff --git a/release/ui/buttons_texture.py b/release/scripts/ui/buttons_texture.py index c95fa266aaa..c95fa266aaa 100644 --- a/release/ui/buttons_texture.py +++ b/release/scripts/ui/buttons_texture.py diff --git a/release/ui/buttons_world.py b/release/scripts/ui/buttons_world.py index 3134c0ce46b..3134c0ce46b 100644 --- a/release/ui/buttons_world.py +++ b/release/scripts/ui/buttons_world.py diff --git a/release/ui/space_buttons.py b/release/scripts/ui/space_buttons.py index aa89c06ea08..aa89c06ea08 100644 --- a/release/ui/space_buttons.py +++ b/release/scripts/ui/space_buttons.py diff --git a/release/ui/space_console.py b/release/scripts/ui/space_console.py index 4641d7900cb..4641d7900cb 100644 --- a/release/ui/space_console.py +++ b/release/scripts/ui/space_console.py diff --git a/release/ui/space_filebrowser.py b/release/scripts/ui/space_filebrowser.py index f1ea5555787..f1ea5555787 100644 --- a/release/ui/space_filebrowser.py +++ b/release/scripts/ui/space_filebrowser.py diff --git a/release/ui/space_image.py b/release/scripts/ui/space_image.py index b14bec0e40e..b14bec0e40e 100644 --- a/release/ui/space_image.py +++ b/release/scripts/ui/space_image.py diff --git a/release/ui/space_info.py b/release/scripts/ui/space_info.py index 7162716e73e..7162716e73e 100644 --- a/release/ui/space_info.py +++ b/release/scripts/ui/space_info.py diff --git a/release/ui/space_logic.py b/release/scripts/ui/space_logic.py index 5748d15a53a..5748d15a53a 100644 --- a/release/ui/space_logic.py +++ b/release/scripts/ui/space_logic.py diff --git a/release/ui/space_node.py b/release/scripts/ui/space_node.py index b32e6a9f61a..b32e6a9f61a 100644 --- a/release/ui/space_node.py +++ b/release/scripts/ui/space_node.py diff --git a/release/ui/space_outliner.py b/release/scripts/ui/space_outliner.py index 522b620e29d..522b620e29d 100644 --- a/release/ui/space_outliner.py +++ b/release/scripts/ui/space_outliner.py diff --git a/release/ui/space_sequencer.py b/release/scripts/ui/space_sequencer.py index a804998cdaa..a804998cdaa 100644 --- a/release/ui/space_sequencer.py +++ b/release/scripts/ui/space_sequencer.py diff --git a/release/ui/space_text.py b/release/scripts/ui/space_text.py index 117033c50a1..117033c50a1 100644 --- a/release/ui/space_text.py +++ b/release/scripts/ui/space_text.py diff --git a/release/ui/space_time.py b/release/scripts/ui/space_time.py index 696dcf18623..696dcf18623 100644 --- a/release/ui/space_time.py +++ b/release/scripts/ui/space_time.py diff --git a/release/ui/space_userpref.py b/release/scripts/ui/space_userpref.py index 9798e0ccab6..9798e0ccab6 100644 --- a/release/ui/space_userpref.py +++ b/release/scripts/ui/space_userpref.py diff --git a/release/ui/space_view3d.py b/release/scripts/ui/space_view3d.py index 23f3b8a10ac..23f3b8a10ac 100644 --- a/release/ui/space_view3d.py +++ b/release/scripts/ui/space_view3d.py diff --git a/release/ui/space_view3d_toolbar.py b/release/scripts/ui/space_view3d_toolbar.py index 4c1b54ea8e6..4c1b54ea8e6 100644 --- a/release/ui/space_view3d_toolbar.py +++ b/release/scripts/ui/space_view3d_toolbar.py diff --git a/release/scripts/unweld.py b/release/scripts/unweld.py deleted file mode 100644 index 3385e66e2d8..00000000000 --- a/release/scripts/unweld.py +++ /dev/null @@ -1,247 +0,0 @@ -#!BPY -""" Registration info for Blender menus: <- these words are ignored -Name: 'Unweld vertex/ices' -Blender: 243 -Group: 'Mesh' -Tip: 'Unweld all faces from a (or several) selected and common vertex. Made vertex bevelling' -""" - -__author__ = "Jean-Michel Soler (jms)" -__url__ = ("blender", "blenderartists.org", -"Script's homepage, http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_faces2vertex.htm#exemple", -"Communicate problems and errors, http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender") -__version__ = "0.4.6 " -__bpydoc__ = """\ -This script unwelds faces from one or several selected vertex/vertices. - -Usage: - -In edit mode Select at least one vertex, then run this script. - -The options are: - -- unbind points;<br> - a new point is added to each face connected to the selected one. - -- with noise;<br> - the new points location is varied with noise - -- middle face;<br> - the new point is located at the center of face to which it is connected -""" - -# ------------------------------------------ -# Un-Weld script 0.4.6 -# name="UnWeld" -# Tip= 'Unweld all faces from a selected and common vertex.' -# date='06/08/2006' -# split all faces from one selected vertex -# (c) 2004 J-M Soler released under GPL licence -#---------------------------------------------- -# Official Page : -# website = 'http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_faces2vertex.htm#exemple' -# Communicate problems and errors on: -# community = 'http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender' -#---------------------------------------------- -# Blender Artistic License -# http://download.blender.org/documentation/html/x21254.html -#--------------------------------------------- -# Changelog -#---------------------------------------------- -# 25/05 : -# -- separate choice, normal (same place) or spread at random, middle of the face -# -- works on several vertices too -# -- Quite vertex bevelling on <<lone>> vertex : create hole in faces around this -# vertex -# 03/06 : -# -- a sort of "bevelled vertex" extrusion controled by horizontal mouse -# displacement. just a beta test to the mouse control. -# 08/08 : -# -- minor correction to completely disconnect face. -#---------------------------------------------- -# Page officielle : -# http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_faces2vertex.htm#exemple -# Commsoler les problemes et erreurs sur: -# http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender -# Blender Artistic License -# http://download.blender.org/documentation/html/x21254.html -#--------------------------------------------- -# Changelog -#---------------------------------------------- -# 25/05 : -# -- separation du choix, normal ou dispersion hasardeuse, -# milieu de face -# -- sommets multiples / -# -- presque unvertex bevelling sur un vertex solitaire : cree -# un trou dans la facette autour du sommet -# 03/06 : -# -- une sorte de vertex extruder en biseau, controle par -# movement horizontal de la souris -# 08/08 : -# -- correction mineure pour s'assurer que les faces soient -# entierment deconnectees -#---------------------------------------------- - -import Blender -from Blender import Noise -from Blender.Draw import * -from Blender.BGL import * -import BPyMessages -# $Id$ - -NR=Noise.random -DECAL=0.03 -t=[0.0,0.0,0.0] -pl=[] -orig=[] - -DEBUG = 0 -SUBSURF=0 -DIM=Create(1.0) - -def Buffer(v,t): - if DEBUG : print dir(v) - for n in range(len(v)): t[n]=t[n]+v[n] - return t - -def freeBuffer(t): - for n in range(3): t[n]=0.0 - return t - -def ModalBuffer(t,f): - for n in range(3): t[n]/=len(f) - return t - -def applyModalValue(v,t): - for n in range(len(v)): v[n]=t[n] - return v - -def docF(f0,f): - - if f0 and f: - f0.mat=f.mat - if f.uv : - f0.uv=f.uv - if f.col : - f0.col=f.col - if f.image : - f0.image=f.image - f0.smooth=f.smooth - f0.mode=f.mode - f0.flag=f.flag - return f0 - - -def connectedFacesList(me,thegood): - listf2v={} - #tri des faces connectees aux sommets selectionnes - for f in me.faces: - for v in f.v: - if v==thegood: - if v.index not in listf2v: # .keys() - listf2v[me.verts.index(v)]=[f] - elif f not in listf2v[me.verts.index(v)]: - listf2v[me.verts.index(v)].append(f) - return listf2v - - -def createAdditionalFace(me,thegood,listf2v): - global t - for f in listf2v[thegood.index]: - f0=Blender.NMesh.Face() - if result==3: t=freeBuffer(t) - for v in f.v: - if result==3: t=Buffer(v,t) - if v!=thegood: - f0.append(v) - else: - if result==2: - nv=Blender.NMesh.Vert(thegood.co[0]+NR()*DECAL, - thegood.co[1]+NR()*DECAL, - thegood.co[2]+NR()*DECAL) - else: - nv=Blender.NMesh.Vert(thegood.co[0], - thegood.co[1], - thegood.co[2]) - nv.sel=1 - me.verts.append(nv) - f0.append(me.verts[me.verts.index(nv)]) - localise=me.verts.index(nv) - docF(f0,f) - if result==3: - t=ModalBuffer(t,f0.v) - me.verts[localise]=applyModalValue(me.verts[localise],t) - me.faces.append(f0) - del me.verts[me.verts.index(thegood)] - for f in listf2v[thegood.index]: - del me.faces[me.faces.index(f)] - return me - -def collecte_edge(listf2v,me,thegood): - back=0 - edgelist = [] - vertlist = [] - if DEBUG : print listf2v - for face in listf2v[thegood.index]: - if len(face.v) == 4: - vlist = [0,1,2,3,0] - elif len(face.v) == 3: - vlist = [0,1,2,0] - else: - vlist = [0,1] - for i in xrange(len(vlist)-1): - vert0 = min(face.v[vlist[i]].index,face.v[vlist[i+1]].index) - vert1 = max(face.v[vlist[i]].index,face.v[vlist[i+1]].index) - edgeinlist = 0 - if vert0==thegood.index or vert1==thegood.index: - for edge in edgelist: - if ((edge[0]==vert0) and (edge[1]==vert1)): - edgeinlist = 1 - edge[2] = edge[2]+1 - edge.append(me.faces.index(face)) - break - if edgeinlist==0: - edge = [vert0,vert1,1,me.faces.index(face)] - edgelist.append(edge) - - for i, edge in enumerate(edgelist): - #print edge - if len(edge)==4: - del edgelist[i] - - edges=len(edgelist) - if DEBUG : print 'number of edges : ',edges," Edge list : " ,edgelist - return edges, edgelist - -import bpy -OBJECT= bpy.data.scenes.active.objects.active - -if OBJECT and OBJECT.type=='Mesh': - if OBJECT.getData(mesh=1).multires: - BPyMessages.Error_NoMeshMultiresEdit() - elif not BPyMessages.Warning_MeshDistroyLayers(OBJECT.getData(mesh=1)): - pass - else: - EDITMODE=Blender.Window.EditMode() - Blender.Window.EditMode(0) - name = "Unweld %t|Unbind Points %x1|With Noise %x2|Middle Face %x3" - result = Blender.Draw.PupMenu(name) - if result: - me=OBJECT.getData() - - for v in me.verts: - if v.sel: - thegood=v - if DEBUG : print thegood - listf2v=connectedFacesList(me,thegood) - if listf2v: - me=createAdditionalFace(me,thegood,listf2v) - #OBJECT.link(me) - me.update() - - OBJECT.makeDisplayList() - - Blender.Window.EditMode(EDITMODE) - -else: - BPyMessages.Error_NoMeshActive() diff --git a/release/scripts/uv_export.py b/release/scripts/uv_export.py deleted file mode 100644 index 5977a3b76f6..00000000000 --- a/release/scripts/uv_export.py +++ /dev/null @@ -1,498 +0,0 @@ -#!BPY - -""" -Name: 'Save UV Face Layout...' -Blender: 242 -Group: 'UV' -Tooltip: 'Export the UV face layout of the selected object to a .TGA or .SVG file' -""" - -__author__ = "Martin 'theeth' Poirier" -__url__ = ("http://www.blender.org", "http://blenderartists.org/") -__version__ = "2.5" - -__bpydoc__ = """\ -This script exports the UV face layout of the selected mesh object to -a TGA image file or a SVG vector file. Then you can, for example, paint details -in this image using an external 2d paint program of your choice and bring it back -to be used as a texture for the mesh. - -Usage: - -Open this script from UV/Image Editor's "UVs" menu, make sure there is a mesh -selected, define size and wire size parameters and push "Export" button. - -There are more options to configure, like setting export path, if image should -use object's name and more. - -Notes:<br>See change logs in scripts for a list of contributors. -""" - - -# $Id$ -# -# -------------------------------------------------------------------------- -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Copyright (C) 2003: Martin Poirier, theeth@yahoo.com -# -# 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 ***** -# -------------------------------------------------------------------------- -# thanks to jms for the tga functions: -# Writetga and buffer functions -# (c) 2002-2004 J-M Soler released under GPL licence -# Official Page : -# http://jmsoler.free.fr/didacticiel/blender/tutor/write_tga_pic.htm -# Communicate problems and errors on: -# http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender -# -------------------------- -# Version 1.1 -# Clear a bug that crashed the script when UV coords overlapped in the same faces -# -------------------------- -# Version 1.2 -# Now with option to use the object's name as filename -# -------------------------- -# Version 1.3 Updates by Zaz from Elysiun.com -# Default path is now the directory of the last saved .blend -# New options: Work on selected face only & Scale image when face wraps -# -------------------------- -# Version 1.3a -# Corrected a minor typo and added the tga extension to both export call -# -------------------------- -# Version 1.4 Updates by Macouno from Elysiun.com -# Fixed rounding error that can cause breaks in lines. -# -------------------------- -# Version 2.0 -# New interface using PupBlock and FileSelector -# Save/Load config to Registry -# Edit in external program -# -------------------------- -# Version 2.1 Updates by Jarod from blenderartists.org -# New exportformat SVG -# simple memory optimations, two third less memory usage -# tga filewriting speed improvements, 3times faster now -# -------------------------- -# Version 2.2 -# Cleanup code -# Filename handling enhancement and bug fixes -# -------------------------- -# Version 2.3 -# Added check for excentric UVs (only affects TGA) -# -------------------------- -# Version 2.4 -# Port from NMesh to Mesh by Daniel Salazar (zanqdo) -# -------------------------- -# Version 2.5 -# Fixed some old off by one rasterizing errors (didn't render points at 1.0 in the UV scale properly). -# Fixed wire drawing for non 1 wire size (didn't wrap or stretch properly -# and would often raise exceptions) -# -------------------------- - - -FullPython = False - -import Blender -import bpy -import BPyMessages - -try: - import os - FullPython = True -except: - pass - -from math import * - -def ExportConfig(): - conf = {} - - conf["SIZE"] = bSize.val - conf["WSIZE"] = bWSize.val - conf["OBFILE"] = bObFile.val - conf["WRAP"] = bWrap.val - conf["ALLFACES"] = bAllFaces.val - conf["EDIT"] = bEdit.val - conf["EXTERNALEDITOR"] = bEditPath.val - conf["UVFORMATSVG"] = bSVG.val - conf["SVGFILL"] = bSVGFill.val - - Blender.Registry.SetKey("UVEXPORT", conf, True) - -def ImportConfig(): - global bSize, bWSize, bObFile, bWrap, bAllFaces - - conf = Blender.Registry.GetKey("UVEXPORT", True) - - if not conf: - return - - try: - bSize.val = conf["SIZE"] - bWSize.val = conf["WSIZE"] - bObFile.val = conf["OBFILE"] - bWrap.val = conf["WRAP"] - bAllFaces.val = conf["ALLFACES"] - bEdit.val = conf["EDIT"] - editor = conf["EXTERNALEDITOR"] - bSVG.val = conf["UVFORMATSVG"] - bSVGFill.val = conf["SVGFILL"] - if editor: - bEditPath.val = editor - except KeyError: - # If one of the key is not in the dict, don't worry, it'll use the defaults - pass - - -def PrintConfig(): - print - print "Imagesize: %ipx" % bSize.val - print "Wiresize : %ipx" % bWSize.val - - if bWrap.val: - print "Wrap : yes" - else: - print "Wrap : no" - - if bAllFaces.val: - print "AllFaces : yes" - else: - print "AllFaces : no" - - if bSVG.val: - print "Format : *.svg" - else: - print "Format : *.tga" - - -def ExportCallback(f): - obj = Blender.Scene.GetCurrent().objects.active - - time1= Blender.sys.time() - - if not obj or obj.type != "Mesh": - BPyMessages.Error_NoMeshActive() - return - - is_editmode = Blender.Window.EditMode() - if is_editmode: Blender.Window.EditMode(0) - - mesh = obj.getData(mesh=1) - if not mesh.faceUV: - if is_editmode: Blender.Window.EditMode(1) - BPyMessages.Error_NoMeshUvActive() - return - - # just for information... - PrintConfig() - - # taking care of filename - if bObFile.val: - name = AddExtension(f, obj.name) - else: - name = AddExtension(f, None) - - - print "Target :", name - print - - UVFaces = ExtractUVFaces(mesh, bAllFaces.val) - - if is_editmode: Blender.Window.EditMode(1) - - if not bSVG.val: - print "TGA export is running..." - UV_Export_TGA(UVFaces, bSize.val, bWSize.val, bWrap.val, name) - else: - print "SVG export is running..." - if bSVGFill.val: - SVGFillColor="#F2DAF2" - else: - SVGFillColor="none" - - UV_Export_SVG(UVFaces, bSize.val, bWSize.val, bWrap.val, name, obj.name, SVGFillColor) - - print - print " ...finished exporting in %.4f sec." % (Blender.sys.time()-time1) - - if FullPython and bEdit.val and bEditPath.val: - filepath = os.path.realpath(name) - print filepath - os.spawnl(os.P_NOWAIT, bEditPath.val, "", filepath) - - -def GetExtension(): - if bSVG.val: - ext = "svg" - else: - ext = "tga" - - return ext - -def AddExtension(filename, object_name): - ext = "." + GetExtension() - - hasExtension = (ext in filename or ext.upper() in filename) - - if object_name and hasExtension: - filename = filename.replace(ext, "") - hasExtension = False - - if object_name: - filename += "_" + object_name - - if not hasExtension: - filename += ext - - return filename - -def GetDefaultFilename(): - filename = Blender.Get("filename") - - filename = filename.replace(".blend", "") - filename += "." + GetExtension() - - return filename - -def ExtractUVFaces(mesh, allface): - - if allface: return [f.uv for f in mesh.faces] - else: return [f.uv for f in mesh.faces if f.sel] - -def Buffer(height=16, width=16, profondeur=1,rvb=255 ): - """ - reserve l'espace memoire necessaire - """ - p=[rvb] - myb=height*width*profondeur - print"Memory : %ikB" % (myb/1024) - b=p*myb - return b - -def write_tgafile(loc2,bitmap,width,height,profondeur): - - f=open(loc2,'wb') - - Origine_en_haut_a_gauche=32 - Origine_en_bas_a_gauche=0 - - Data_Type_2=2 - RVB=profondeur*8 - RVBA=32 - entete0=[] - for t in range(18): - entete0.append(chr(0)) - - entete0[2]=chr(Data_Type_2) - entete0[13]=chr(width/256) - entete0[12]=chr(width % 256) - entete0[15]=chr(height/256) - entete0[14]=chr(height % 256) - entete0[16]=chr(RVB) - entete0[17]=chr(Origine_en_bas_a_gauche) - - # Origine_en_haut_a_gauche - print" ...writing tga..." - for t in entete0: - f.write(t) - - redpx=chr(0) + chr(0) + chr(255) - blackpx=chr(0) + chr(0) + chr(0) - whitepx=chr(255) + chr(255) + chr(255) - - for t in bitmap: - if t==255: - f.write(whitepx) - elif t==0: - f.write(blackpx) - else: - f.write(redpx) - - f.close() - - -def UV_Export_TGA(vList, size, wsize, wrap, file): - extreme_warning = False - - minx = 0 - miny = 0 - scale = 1.0 - - step = 0 - - img = Buffer(size,size) - - if wrap: - wrapSize = size - else: - wrapSize = size - maxx = -100000 - maxy = -100000 - for f in vList: - for v in f: - x = int(v[0] * size) - maxx = max (x + wsize - 1, maxx) - minx = min (x - wsize + 1, minx) - - y = int(v[1] * size) - maxy = max (y + wsize - 1, maxy) - miny = min (y - wsize + 1, miny) - wrapSize = max (maxx - minx + 1, maxy - miny + 1) - scale = float (size) / float (wrapSize) - - max_index = size - 1 # max index of the buffer (height or width) - fnum = 0 - fcnt = len (vList) - - for f in vList: - fnum = fnum + 1 - if not fnum % 100: - print "%i of %i Faces completed" % (fnum, fcnt) - - for index in range(len(f)): - co1 = f[index] - if index < len(f) - 1: - co2 = f[index + 1] - else: - co2 = f[0] - - step = int(ceil(size*sqrt((co1[0]-co2[0])**2+(co1[1]-co2[1])**2))) - if step: - try: - for t in xrange(step): - x = int(floor((co1[0] + t*(co2[0]-co1[0])/step) * max_index)) - y = int(floor((co1[1] + t*(co2[1]-co1[1])/step) * max_index)) - - for dx in range(-1*wsize + 1, wsize): - if wrap: - wx = (x + dx) % wrapSize - else: - wx = int ((x - minx + dx) * scale) - - for dy in range(-1*wsize + 1, wsize): - if wrap: - wy = (y + dy) % wrapSize - else: - wy = int ((y - miny + dy) * scale) - - co = wx * 1 + wy * 1 * size - img[co] = 0 - except OverflowError: - if not extreme_warning: - print "Skipping extremely long UV edges, check your layout for excentric values" - extreme_warning = True - - for v in f: - x = int(v[0] * max_index) - y = int(v[1] * max_index) - - if wrap: - x = x % wrapSize - y = y % wrapSize - else: - x = int ((x - minx) * scale) - y = int ((y - miny) * scale) - - co = x * 1 + y * 1 * size - img[co] = 1 - - - write_tgafile(file,img,size,size,3) - -def UV_Export_SVG(vList, size, wsize, wrap, file, objname, facesfillcolor): - fl=open(file,'wb') - fl.write('<?xml version="1.0"?>\r\n<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\r\n') - fl.write('<svg width="' + str(size) + 'px" height="' + str(size) + 'px" viewBox="0 0 ' + str(size) + ' ' + str(size) + '" xmlns="http://www.w3.org/2000/svg" version="1.1">\r\n') - fl.write('<desc>UV-Map from Object: ' + str(objname) +'. Exported from Blender3D with UV Exportscript</desc>\r\n') - fl.write('<rect x="0" y="0" width="' + str(size) + '" height="' + str(size) + '" fill="none" stroke="blue" stroke-width="' + str(wsize) + 'px" />\r\n') - fl.write('<g style="fill:' + str(facesfillcolor) + '; stroke:black; stroke-width:' + str(wsize) + 'px;">\r\n') - - fnum = 0 - fcnt = len (vList) - fnumv = (long) (fcnt/10) - - for f in vList: - fnum = fnum + 1 - - if fnum == fnumv: - print ".", - fnumv = fnumv + ((long) (fcnt/10)) - - fl.write('<polygon points="') - for index in range(len(f)): - co = f[index] - fl.write("%.3f,%.3f " % (co[0]*size, size-co[1]*size)) - fl.write('" />\r\n') - - print "%i Faces completed." % fnum - fl.write('</g>\r\n') - fl.write('</svg>') - fl.close() - -def SetEditorAndExportCallback(f): - global bEditPath - bEditPath.val = f - - ExportConfig() - - Export() - -def Export(): - Blender.Window.FileSelector(ExportCallback, "Save UV (%s)" % GetExtension(), GetDefaultFilename()) - -def SetEditorAndExport(): - Blender.Window.FileSelector(SetEditorAndExportCallback, "Select Editor") - -# ###################################### MAIN SCRIPT BODY ############################### - -# Create user values and fill with defaults -bSize = Blender.Draw.Create(512) -bWSize = Blender.Draw.Create(1) -bObFile = Blender.Draw.Create(1) -bWrap = Blender.Draw.Create(1) -bAllFaces = Blender.Draw.Create(1) -bEdit = Blender.Draw.Create(0) -bEditPath = Blender.Draw.Create("") -bSVG = Blender.Draw.Create(0) -bSVGFill = Blender.Draw.Create(1) - -# Import saved configurations -ImportConfig() - - -Block = [] - -Block.append(("Size: ", bSize, 64, 16384, "Size of the exported image")) -Block.append(("Wire: ", bWSize, 1, 9, "Size of the wire of the faces")) -Block.append(("Wrap", bWrap, "Wrap to image size, scale otherwise")) -Block.append(("All Faces", bAllFaces, "Export all or only selected faces")) -Block.append(("Object", bObFile, "Use object name in filename")) -Block.append(("SVG", bSVG, "save as *.svg instead of *.tga")) -Block.append(("Fill SVG faces", bSVGFill, "SVG faces will be filled, none filled otherwise")) - -if FullPython: - Block.append(("Edit", bEdit, "Edit resulting file in an external program")) - Block.append(("Editor: ", bEditPath, 0, 399, "Path to external editor (leave blank to select a new one)")) - -retval = Blender.Draw.PupBlock("UV Image Export", Block) - -if retval: - ExportConfig() - - if bEdit.val and not bEditPath.val: - SetEditorAndExport() - else: - Export()
\ No newline at end of file diff --git a/release/scripts/uv_seams_from_islands.py b/release/scripts/uv_seams_from_islands.py deleted file mode 100644 index 7f156efde7d..00000000000 --- a/release/scripts/uv_seams_from_islands.py +++ /dev/null @@ -1,101 +0,0 @@ -#!BPY -""" -Name: 'Seams from Islands' -Blender: 246 -Group: 'UV' -Tooltip: 'Add seams onto the mesh at the bounds of UV islands' -""" - -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Script copyright (C) Campbell Barton -# -# 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 ***** -# -------------------------------------------------------------------------- - -from Blender import Scene, Mesh, Window, sys -import BPyMessages - -def seams_from_islands(me): - # This function runs out of editmode with a mesh - # error cases are alredy checked for - - # next intex - wrap_q = [1,2,3,0] - wrap_t = [1,2,0] - edge_uvs = {} - for f in me.faces: - f_uv = [(round(uv.x, 6), round(uv.y, 6)) for uv in f.uv] - f_vi = [v.index for v in f] - for i, key in enumerate(f.edge_keys): - if len(f)==3: - uv1, uv2 = f_uv[i], f_uv[wrap_t[i]] - vi1, vi2 = f_vi[i], f_vi[wrap_t[i]] - else: # quad - uv1, uv2 = f_uv[i], f_uv[wrap_q[i]] - vi1, vi2 = f_vi[i], f_vi[wrap_q[i]] - - if vi1 > vi2: uv1,uv2 = uv2,uv1 - - edge_uvs.setdefault(key, []).append((uv1, uv2)) - - # add seams - SEAM = Mesh.EdgeFlags.SEAM - for ed in me.edges: - try: # the edge might not be in a face - if len(set(edge_uvs[ed.key])) > 1: - ed.flag |= SEAM - except: - pass - -def main(): - - # Gets the current scene, there can be many scenes in 1 blend file. - sce = Scene.GetCurrent() - - # Get the active object, there can only ever be 1 - # and the active object is always the editmode object. - ob_act = sce.objects.active - me = ob_act.getData(mesh=1) - - if not ob_act or ob_act.type != 'Mesh' or not me.faceUV: - BPyMessages.Error_NoMeshUvActive() - return - - # Saves the editmode state and go's out of - # editmode if its enabled, we cant make - # changes to the mesh data while in editmode. - is_editmode = Window.EditMode() - if is_editmode: Window.EditMode(0) - - Window.WaitCursor(1) - - t = sys.time() - - # Run the mesh editing function - seams_from_islands(me) - - if is_editmode: Window.EditMode(1) - - # Timing the script is a good way to be aware on any speed hits when scripting - print 'UV Seams from Islands finished in %.2f seconds' % (sys.time()-t) - Window.WaitCursor(0) - - -# This lets you can import the script without running it -if __name__ == '__main__': - main() diff --git a/release/scripts/uvcalc_follow_active_coords.py b/release/scripts/uvcalc_follow_active_coords.py deleted file mode 100644 index 83df200991f..00000000000 --- a/release/scripts/uvcalc_follow_active_coords.py +++ /dev/null @@ -1,254 +0,0 @@ -#!BPY -""" -Name: 'Follow Active (quads)' -Blender: 242 -Group: 'UVCalculation' -Tooltip: 'Follow from active quads.' -""" -__author__ = "Campbell Barton" -__url__ = ("blender", "blenderartists.org") -__version__ = "1.0 2006/02/07" - -__bpydoc__ = """\ -This script sets the UV mapping and image of selected faces from adjacent unselected faces. - -for full docs see... -http://mediawiki.blender.org/index.php/Scripts/Manual/UV_Calculate/Follow_active_quads -""" - -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Script copyright (C) Campbell J Barton -# -# 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 ***** -# -------------------------------------------------------------------------- - - -from Blender import * -import bpy -import BPyMesh - -def extend(EXTEND_MODE,ob): - if EXTEND_MODE == -1: - return - me = ob.getData(mesh=1) - me_verts = me.verts - # Toggle Edit mode - is_editmode = Window.EditMode() - if is_editmode: - Window.EditMode(0) - Window.WaitCursor(1) - t = sys.time() - edge_average_lengths = {} - - OTHER_INDEX = 2,3,0,1 - FAST_INDICIES = 0,2,1,3 # order is faster - def extend_uvs(face_source, face_target, edge_key): - ''' - Takes 2 faces, - Projects its extends its UV coords onto the face next to it. - Both faces must share an edge. - ''' - - def face_edge_vs(vi): - # assunme a quad - return [(vi[0], vi[1]), (vi[1], vi[2]), (vi[2], vi[3]), (vi[3], vi[0])] - - uvs_source = face_source.uv - uvs_target = face_target.uv - - vidx_source = [v.index for v in face_source] - vidx_target = [v.index for v in face_target] - - # vertex index is the key, uv is the value - uvs_vhash_source = dict( [ (vindex, uvs_source[i]) for i, vindex in enumerate(vidx_source)] ) - uvs_vhash_target = dict( [ (vindex, uvs_target[i]) for i, vindex in enumerate(vidx_target)] ) - - edge_idxs_source = face_edge_vs(vidx_source) - edge_idxs_target = face_edge_vs(vidx_target) - - source_matching_edge = -1 - target_matching_edge = -1 - - edge_key_swap = edge_key[1], edge_key[0] - - try: source_matching_edge = edge_idxs_source.index(edge_key) - except: source_matching_edge = edge_idxs_source.index(edge_key_swap) - try: target_matching_edge = edge_idxs_target.index(edge_key) - except: target_matching_edge = edge_idxs_target.index(edge_key_swap) - - - - edgepair_inner_source = edge_idxs_source[source_matching_edge] - edgepair_inner_target = edge_idxs_target[target_matching_edge] - edgepair_outer_source = edge_idxs_source[OTHER_INDEX[source_matching_edge]] - edgepair_outer_target = edge_idxs_target[OTHER_INDEX[target_matching_edge]] - - if edge_idxs_source[source_matching_edge] == edge_idxs_target[target_matching_edge]: - iA= 0; iB= 1 # Flipped, most common - else: # The normals of these faces must be different - iA= 1; iB= 0 - - - # Set the target UV's touching source face, no tricky calc needed, - uvs_vhash_target[edgepair_inner_target[0]][:] = uvs_vhash_source[edgepair_inner_source[iA]] - uvs_vhash_target[edgepair_inner_target[1]][:] = uvs_vhash_source[edgepair_inner_source[iB]] - - - # Set the 2 UV's on the target face that are not touching - # for this we need to do basic expaning on the source faces UV's - if EXTEND_MODE == 2: - - try: # divide by zero is possible - ''' - measure the length of each face from the middle of each edge to the opposite - allong the axis we are copying, use this - ''' - i1a= edgepair_outer_target[iB] - i2a= edgepair_inner_target[iA] - if i1a>i2a: i1a, i2a = i2a, i1a - - i1b= edgepair_outer_source[iB] - i2b= edgepair_inner_source[iA] - if i1b>i2b: i1b, i2b = i2b, i1b - # print edge_average_lengths - factor = edge_average_lengths[i1a, i2a][0] / edge_average_lengths[i1b, i2b][0] - except: - # Div By Zero? - factor = 1.0 - - uvs_vhash_target[edgepair_outer_target[iB]][:] = uvs_vhash_source[edgepair_inner_source[0]] +factor * (uvs_vhash_source[edgepair_inner_source[0]] - uvs_vhash_source[edgepair_outer_source[1]]) - uvs_vhash_target[edgepair_outer_target[iA]][:] = uvs_vhash_source[edgepair_inner_source[1]] +factor * (uvs_vhash_source[edgepair_inner_source[1]] - uvs_vhash_source[edgepair_outer_source[0]]) - - else: - # same as above but with no factor - uvs_vhash_target[edgepair_outer_target[iB]][:] = uvs_vhash_source[edgepair_inner_source[0]] + (uvs_vhash_source[edgepair_inner_source[0]] - uvs_vhash_source[edgepair_outer_source[1]]) - uvs_vhash_target[edgepair_outer_target[iA]][:] = uvs_vhash_source[edgepair_inner_source[1]] + (uvs_vhash_source[edgepair_inner_source[1]] - uvs_vhash_source[edgepair_outer_source[0]]) - - if not me.faceUV: - me.faceUV= True - - face_act = me.activeFace - if face_act == -1: - Draw.PupMenu('ERROR: No active face') - return - - face_sel= [f for f in me.faces if len(f) == 4 and f.sel] - - face_act_local_index = -1 - for i, f in enumerate(face_sel): - if f.index == face_act: - face_act_local_index = i - break - - if face_act_local_index == -1: - Draw.PupMenu('ERROR: Active face not selected') - return - - - - # Modes - # 0 unsearched - # 1:mapped, use search from this face. - removed!! - # 2:all siblings have been searched. dont search again. - face_modes = [0] * len(face_sel) - face_modes[face_act_local_index] = 1 # extend UV's from this face. - - - # Edge connectivty - edge_faces = {} - for i, f in enumerate(face_sel): - for edkey in f.edge_keys: - try: edge_faces[edkey].append(i) - except: edge_faces[edkey] = [i] - - SEAM = Mesh.EdgeFlags.SEAM - - if EXTEND_MODE == 2: - edge_loops = BPyMesh.getFaceLoopEdges(face_sel, [ed.key for ed in me.edges if ed.flag & SEAM] ) - me_verts = me.verts - for loop in edge_loops: - looplen = [0.0] - for ed in loop: - edge_average_lengths[ed] = looplen - looplen[0] += (me_verts[ed[0]].co - me_verts[ed[1]].co).length - looplen[0] = looplen[0] / len(loop) - - - - # remove seams, so we dont map accross seams. - for ed in me.edges: - if ed.flag & SEAM: - # remove the edge pair if we can - try: del edge_faces[ed.key] - except: pass - # Done finding seams - - - # face connectivity - faces around each face - # only store a list of indicies for each face. - face_faces = [[] for i in xrange(len(face_sel))] - - for edge_key, faces in edge_faces.iteritems(): - if len(faces) == 2: # Only do edges with 2 face users for now - face_faces[faces[0]].append((faces[1], edge_key)) - face_faces[faces[1]].append((faces[0], edge_key)) - - - # Now we know what face is connected to what other face, map them by connectivity - ok = True - while ok: - ok = False - for i in xrange(len(face_sel)): - if face_modes[i] == 1: # searchable - for f_sibling, edge_key in face_faces[i]: - if face_modes[f_sibling] == 0: - face_modes[f_sibling] = 1 # mapped and search from. - extend_uvs(face_sel[i], face_sel[f_sibling], edge_key) - face_modes[i] = 1 # we can map from this one now. - ok= True # keep searching - - face_modes[i] = 2 # dont search again - print sys.time() - t - - if is_editmode: - Window.EditMode(1) - else: - me.update() - - Window.RedrawAll() - Window.WaitCursor(0) - - -def main(): - sce = bpy.data.scenes.active - ob = sce.objects.active - - # print ob, ob.type - if ob == None or ob.type != 'Mesh': - Draw.PupMenu('ERROR: No mesh object.') - return - - - - # 0:normal extend, 1:edge length - EXTEND_MODE = Draw.PupMenu("Use Face Area%t|Loop Average%x2|None%x0") - extend(EXTEND_MODE,ob) - -if __name__ == '__main__': - main() - diff --git a/release/scripts/uvcalc_lightmap.py b/release/scripts/uvcalc_lightmap.py deleted file mode 100644 index 1433ccbd13a..00000000000 --- a/release/scripts/uvcalc_lightmap.py +++ /dev/null @@ -1,599 +0,0 @@ -#!BPY -""" -Name: 'Lightmap UVPack' -Blender: 242 -Group: 'UVCalculation' -Tooltip: 'Give each face non overlapping space on a texture.' -""" -__author__ = "Campbell Barton aka ideasman42" -__url__ = ("blender", "blenderartists.org") -__version__ = "1.0 2006/02/07" - -__bpydoc__ = """\ -""" - -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Script copyright (C) Campbell Barton -# -# 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 ***** -# -------------------------------------------------------------------------- - - -from Blender import * -import bpy -import BPyMesh -# reload(BPyMesh) - -from math import sqrt - -def AngleBetweenVecs(a1,a2): - try: - return Mathutils.AngleBetweenVecs(a1,a2) - except: - return 180.0 - -# python 2.3 has no reversed() iterator. this will only work on lists and tuples -try: - reversed -except: - def reversed(l): return l[::-1] - -class prettyface(object): - __slots__ = 'uv', 'width', 'height', 'children', 'xoff', 'yoff', 'has_parent', 'rot' - def __init__(self, data): - - self.has_parent = False - self.rot = False # only used for triables - self.xoff = 0 - self.yoff = 0 - - if type(data) == list: # list of data - self.uv = None - - # join the data - if len(data) == 2: - # 2 vertical blocks - data[1].xoff = data[0].width - self.width = data[0].width * 2 - self.height = data[0].height - - elif len(data) == 4: - # 4 blocks all the same size - d = data[0].width # dimension x/y are the same - - data[1].xoff += d - data[2].yoff += d - - data[3].xoff += d - data[3].yoff += d - - self.width = self.height = d*2 - - #else: - # print len(data), data - # raise "Error" - - for pf in data: - pf.has_parent = True - - - self.children = data - - elif type(data) == tuple: - # 2 blender faces - # f, (len_min, len_mid, len_max) - self.uv = data - - f1, lens1, lens1ord = data[0] - if data[1]: - f2, lens2, lens2ord = data[1] - self.width = (lens1[lens1ord[0]] + lens2[lens2ord[0]])/2 - self.height = (lens1[lens1ord[1]] + lens2[lens2ord[1]])/2 - else: # 1 tri :/ - self.width = lens1[0] - self.height = lens1[1] - - self.children = [] - - - else: # blender face - self.uv = data.uv - - cos = [v.co for v in data] - self.width = ((cos[0]-cos[1]).length + (cos[2]-cos[3]).length)/2 - self.height = ((cos[1]-cos[2]).length + (cos[0]-cos[3]).length)/2 - - self.children = [] - - - def spin(self): - if self.uv and len(self.uv) == 4: - self.uv = self.uv[1], self.uv[2], self.uv[3], self.uv[0] - - self.width, self.height = self.height, self.width - self.xoff, self.yoff = self.yoff, self.xoff # not needed? - self.rot = not self.rot # only for tri pairs. - # print 'spinning' - for pf in self.children: - pf.spin() - - - def place(self, xoff, yoff, xfac, yfac, margin_w, margin_h): - - xoff += self.xoff - yoff += self.yoff - - for pf in self.children: - pf.place(xoff, yoff, xfac, yfac, margin_w, margin_h) - - uv = self.uv - if not uv: - return - - x1 = xoff - y1 = yoff - x2 = xoff + self.width - y2 = yoff + self.height - - # Scale the values - x1 = x1/xfac + margin_w - x2 = x2/xfac - margin_w - y1 = y1/yfac + margin_h - y2 = y2/yfac - margin_h - - # 2 Tri pairs - if len(uv) == 2: - # match the order of angle sizes of the 3d verts with the UV angles and rotate. - def get_tri_angles(v1,v2,v3): - a1= AngleBetweenVecs(v2-v1,v3-v1) - a2= AngleBetweenVecs(v1-v2,v3-v2) - a3 = 180 - (a1+a2) #a3= AngleBetweenVecs(v2-v3,v1-v3) - - - return [(a1,0),(a2,1),(a3,2)] - - def set_uv(f, p1, p2, p3): - - # cos = - #v1 = cos[0]-cos[1] - #v2 = cos[1]-cos[2] - #v3 = cos[2]-cos[0] - angles_co = get_tri_angles(*[v.co for v in f]) - angles_co.sort() - I = [i for a,i in angles_co] - - fuv = f.uv - if self.rot: - fuv[I[2]][:] = p1 - fuv[I[1]][:] = p2 - fuv[I[0]][:] = p3 - else: - fuv[I[2]][:] = p1 - fuv[I[0]][:] = p2 - fuv[I[1]][:] = p3 - - f, lens, lensord = uv[0] - - set_uv(f, (x1,y1), (x1, y2-margin_h), (x2-margin_w, y1)) - - if uv[1]: - f, lens, lensord = uv[1] - set_uv(f, (x2,y2), (x2, y1+margin_h), (x1+margin_w, y2)) - - else: # 1 QUAD - uv[1][:] = x1,y1 - uv[2][:] = x1,y2 - uv[3][:] = x2,y2 - uv[0][:] = x2,y1 - - def __hash__(self): - # None unique hash - return self.width, self.height - - -def lightmap_uvpack( meshes,\ -PREF_SEL_ONLY= True,\ -PREF_NEW_UVLAYER= False,\ -PREF_PACK_IN_ONE= False,\ -PREF_APPLY_IMAGE= False,\ -PREF_IMG_PX_SIZE= 512,\ -PREF_BOX_DIV= 8,\ -PREF_MARGIN_DIV= 512): - ''' - BOX_DIV if the maximum division of the UV map that - a box may be consolidated into. - Basicly, a lower value will be slower but waist less space - and a higher value will have more clumpy boxes but more waisted space - ''' - - if not meshes: - return - - t = sys.time() - - if PREF_PACK_IN_ONE: - if PREF_APPLY_IMAGE: - image = Image.New('lightmap', PREF_IMG_PX_SIZE, PREF_IMG_PX_SIZE, 24) - face_groups = [[]] - else: - face_groups = [] - - for me in meshes: - # Add face UV if it does not exist. - # All new faces are selected. - me.faceUV = True - - if PREF_SEL_ONLY: - faces = [f for f in me.faces if f.sel] - else: - faces = list(me.faces) - - if PREF_PACK_IN_ONE: - face_groups[0].extend(faces) - else: - face_groups.append(faces) - - if PREF_NEW_UVLAYER: - uvname_org = uvname = 'lightmap' - uvnames = me.getUVLayerNames() - i = 1 - while uvname in uvnames: - uvname = '%s.%03d' % (uvname_org, i) - i+=1 - - me.addUVLayer(uvname) - me.activeUVLayer = uvname - - del uvnames, uvname_org, uvname - - for face_sel in face_groups: - print "\nStarting unwrap" - - if len(face_sel) <4: - print '\tWarning, less then 4 faces, skipping' - continue - - pretty_faces = [prettyface(f) for f in face_sel if len(f) == 4] - - - # Do we have any tri's - if len(pretty_faces) != len(face_sel): - - # Now add tri's, not so simple because we need to pair them up. - def trylens(f): - # f must be a tri - cos = [v.co for v in f] - lens = [(cos[0] - cos[1]).length, (cos[1] - cos[2]).length, (cos[2] - cos[0]).length] - - lens_min = lens.index(min(lens)) - lens_max = lens.index(max(lens)) - for i in xrange(3): - if i != lens_min and i!= lens_max: - lens_mid = i - break - lens_order = lens_min, lens_mid, lens_max - - return f, lens, lens_order - - tri_lengths = [trylens(f) for f in face_sel if len(f) == 3] - del trylens - - def trilensdiff(t1,t2): - return\ - abs(t1[1][t1[2][0]]-t2[1][t2[2][0]])+\ - abs(t1[1][t1[2][1]]-t2[1][t2[2][1]])+\ - abs(t1[1][t1[2][2]]-t2[1][t2[2][2]]) - - while tri_lengths: - tri1 = tri_lengths.pop() - - if not tri_lengths: - pretty_faces.append(prettyface((tri1, None))) - break - - best_tri_index = -1 - best_tri_diff = 100000000.0 - - for i, tri2 in enumerate(tri_lengths): - diff = trilensdiff(tri1, tri2) - if diff < best_tri_diff: - best_tri_index = i - best_tri_diff = diff - - pretty_faces.append(prettyface((tri1, tri_lengths.pop(best_tri_index)))) - - - # Get the min, max and total areas - max_area = 0.0 - min_area = 100000000.0 - tot_area = 0 - for f in face_sel: - area = f.area - if area > max_area: max_area = area - if area < min_area: min_area = area - tot_area += area - - max_len = sqrt(max_area) - min_len = sqrt(min_area) - side_len = sqrt(tot_area) - - # Build widths - - curr_len = max_len - - print '\tGenerating lengths...', - - lengths = [] - while curr_len > min_len: - lengths.append(curr_len) - curr_len = curr_len/2 - - # Dont allow boxes smaller then the margin - # since we contract on the margin, boxes that are smaller will create errors - # print curr_len, side_len/MARGIN_DIV - if curr_len/4 < side_len/PREF_MARGIN_DIV: - break - - if not lengths: - lengths.append(curr_len) - - # convert into ints - lengths_to_ints = {} - - l_int = 1 - for l in reversed(lengths): - lengths_to_ints[l] = l_int - l_int*=2 - - lengths_to_ints = lengths_to_ints.items() - lengths_to_ints.sort() - print 'done' - - # apply quantized values. - - for pf in pretty_faces: - w = pf.width - h = pf.height - bestw_diff = 1000000000.0 - besth_diff = 1000000000.0 - new_w = 0.0 - new_h = 0.0 - for l, i in lengths_to_ints: - d = abs(l - w) - if d < bestw_diff: - bestw_diff = d - new_w = i # assign the int version - - d = abs(l - h) - if d < besth_diff: - besth_diff = d - new_h = i # ditto - - pf.width = new_w - pf.height = new_h - - if new_w > new_h: - pf.spin() - - print '...done' - - - # Since the boxes are sized in powers of 2, we can neatly group them into bigger squares - # this is done hierarchily, so that we may avoid running the pack function - # on many thousands of boxes, (under 1k is best) because it would get slow. - # Using an off and even dict us usefull because they are packed differently - # where w/h are the same, their packed in groups of 4 - # where they are different they are packed in pairs - # - # After this is done an external pack func is done that packs the whole group. - - print '\tConsolidating Boxes...', - even_dict = {} # w/h are the same, the key is an int (w) - odd_dict = {} # w/h are different, the key is the (w,h) - - for pf in pretty_faces: - w,h = pf.width, pf.height - if w==h: even_dict.setdefault(w, []).append( pf ) - else: odd_dict.setdefault((w,h), []).append( pf ) - - # Count the number of boxes consolidated, only used for stats. - c = 0 - - # This is tricky. the total area of all packed boxes, then squt that to get an estimated size - # this is used then converted into out INT space so we can compare it with - # the ints assigned to the boxes size - # and divided by BOX_DIV, basicly if BOX_DIV is 8 - # ...then the maximum box consolidataion (recursive grouping) will have a max width & height - # ...1/8th of the UV size. - # ...limiting this is needed or you end up with bug unused texture spaces - # ...however if its too high, boxpacking is way too slow for high poly meshes. - float_to_int_factor = lengths_to_ints[0][0] - if float_to_int_factor > 0: - max_int_dimension = int(((side_len / float_to_int_factor)) / PREF_BOX_DIV) - ok = True - else: - max_int_dimension = 0.0 # wont be used - ok = False - - # RECURSIVE prettyface grouping - while ok: - ok = False - - # Tall boxes in groups of 2 - for d, boxes in odd_dict.items(): - if d[1] < max_int_dimension: - #\boxes.sort(key = lambda a: len(a.children)) - while len(boxes) >= 2: - # print "foo", len(boxes) - ok = True - c += 1 - pf_parent = prettyface([boxes.pop(), boxes.pop()]) - pretty_faces.append(pf_parent) - - w,h = pf_parent.width, pf_parent.height - - if w>h: raise "error" - - if w==h: - even_dict.setdefault(w, []).append(pf_parent) - else: - odd_dict.setdefault((w,h), []).append(pf_parent) - - # Even boxes in groups of 4 - for d, boxes in even_dict.items(): - if d < max_int_dimension: - # py 2.3 compat - try: boxes.sort(key = lambda a: len(a.children)) - except: boxes.sort(lambda a, b: cmp(len(a.children), len(b.children))) - - while len(boxes) >= 4: - # print "bar", len(boxes) - ok = True - c += 1 - - pf_parent = prettyface([boxes.pop(), boxes.pop(), boxes.pop(), boxes.pop()]) - pretty_faces.append(pf_parent) - w = pf_parent.width # width and weight are the same - even_dict.setdefault(w, []).append(pf_parent) - - del even_dict - del odd_dict - - orig = len(pretty_faces) - - pretty_faces = [pf for pf in pretty_faces if not pf.has_parent] - - # spin every second prettyface - # if there all vertical you get less efficiently used texture space - i = len(pretty_faces) - d = 0 - while i: - i -=1 - pf = pretty_faces[i] - if pf.width != pf.height: - d += 1 - if d % 2: # only pack every second - pf.spin() - # pass - - print 'Consolidated', c, 'boxes, done' - # print 'done', orig, len(pretty_faces) - - - # boxes2Pack.append([islandIdx, w,h]) - print '\tPacking Boxes', len(pretty_faces), '...', - boxes2Pack = [ [0.0, 0.0, pf.width, pf.height, i] for i, pf in enumerate(pretty_faces)] - packWidth, packHeight = Geometry.BoxPack2D(boxes2Pack) - - # print packWidth, packHeight - - packWidth = float(packWidth) - packHeight = float(packHeight) - - margin_w = ((packWidth) / PREF_MARGIN_DIV)/ packWidth - margin_h = ((packHeight) / PREF_MARGIN_DIV) / packHeight - - # print margin_w, margin_h - print 'done' - - # Apply the boxes back to the UV coords. - print '\twriting back UVs', - for i, box in enumerate(boxes2Pack): - pretty_faces[i].place(box[0], box[1], packWidth, packHeight, margin_w, margin_h) - # pf.place(box[1][1], box[1][2], packWidth, packHeight, margin_w, margin_h) - print 'done' - - - if PREF_APPLY_IMAGE: - if not PREF_PACK_IN_ONE: - image = Image.New('lightmap', PREF_IMG_PX_SIZE, PREF_IMG_PX_SIZE, 24) - - for f in face_sel: - f.image = image - - for me in meshes: - me.update() - - print 'finished all %.2f ' % (sys.time() - t) - - Window.RedrawAll() - -def main(): - scn = bpy.data.scenes.active - - PREF_ACT_ONLY = Draw.Create(1) - PREF_SEL_ONLY = Draw.Create(1) - PREF_NEW_UVLAYER = Draw.Create(0) - PREF_PACK_IN_ONE = Draw.Create(0) - PREF_APPLY_IMAGE = Draw.Create(0) - PREF_IMG_PX_SIZE = Draw.Create(512) - PREF_BOX_DIV = Draw.Create(12) - PREF_MARGIN_DIV = Draw.Create(0.1) - - if not Draw.PupBlock('Lightmap Pack', [\ - 'Context...', - ('Active Object', PREF_ACT_ONLY, 'If disabled, include other selected objects for packing the lightmap.'),\ - ('Selected Faces', PREF_SEL_ONLY, 'Use only selected faces from all selected meshes.'),\ - 'Image & UVs...', - ('Share Tex Space', PREF_PACK_IN_ONE, 'Objects Share texture space, map all objects into 1 uvmap'),\ - ('New UV Layer', PREF_NEW_UVLAYER, 'Create a new UV layer for every mesh packed'),\ - ('New Image', PREF_APPLY_IMAGE, 'Assign new images for every mesh (only one if shared tex space enabled)'),\ - ('Image Size', PREF_IMG_PX_SIZE, 64, 5000, 'Width and Height for the new image'),\ - 'UV Packing...', - ('Pack Quality: ', PREF_BOX_DIV, 1, 48, 'Pre Packing before the complex boxpack'),\ - ('Margin: ', PREF_MARGIN_DIV, 0.001, 1.0, 'Size of the margin as a division of the UV')\ - ]): - return - - - if PREF_ACT_ONLY.val: - ob = scn.objects.active - if ob == None or ob.type != 'Mesh': - Draw.PupMenu('Error%t|No mesh object.') - return - meshes = [ ob.getData(mesh=1) ] - else: - meshes = dict([ (me.name, me) for ob in scn.objects.context if ob.type == 'Mesh' for me in (ob.getData(mesh=1),) if not me.lib if len(me.faces)]) - meshes = meshes.values() - if not meshes: - Draw.PupMenu('Error%t|No mesh objects selected.') - return - - # Toggle Edit mode - is_editmode = Window.EditMode() - if is_editmode: - Window.EditMode(0) - - - Window.WaitCursor(1) - lightmap_uvpack(meshes,\ - PREF_SEL_ONLY.val,\ - PREF_NEW_UVLAYER.val,\ - PREF_PACK_IN_ONE.val,\ - PREF_APPLY_IMAGE.val,\ - PREF_IMG_PX_SIZE.val,\ - PREF_BOX_DIV.val,\ - int(1/(PREF_MARGIN_DIV.val/100))) - - if is_editmode: - Window.EditMode(1) - - Window.WaitCursor(0) - -if __name__ == '__main__': - main() diff --git a/release/scripts/uvcalc_quad_clickproj.py b/release/scripts/uvcalc_quad_clickproj.py deleted file mode 100644 index 298103e4d5f..00000000000 --- a/release/scripts/uvcalc_quad_clickproj.py +++ /dev/null @@ -1,271 +0,0 @@ -#!BPY - -""" Registration info for Blender menus: <- these words are ignored -Name: 'Click project from face' -Blender: 245 -Group: 'UVCalculation' -Tooltip: '3 Clicks to project uvs onto selected faces.' -""" - -__author__ = "Campbell Barton aka ideasman42" -__url__ = ["www.blender.org", "blenderartists.org", "www.python.org"] -__version__ = "0.1" -__bpydoc__=\ -''' -http://mediawiki.blender.org/index.php/Scripts/Manual/UV_Calculate/Click_project_from_face -" - -''' - -# -------------------------------------------------------------------------- -# Click project v0.1 by Campbell Barton (AKA Ideasman) -# -------------------------------------------------------------------------- -# ***** 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 ***** -# -------------------------------------------------------------------------- - -import Blender -import bpy -import BPyMesh -import BPyWindow - -mouseViewRay= BPyWindow.mouseViewRay -from Blender import Mathutils, Window, Scene, Draw, sys -from Blender.Mathutils import Vector, Matrix, LineIntersect, Intersect #, AngleBetweenVecs, Intersect -LMB= Window.MButs.L -RMB= Window.MButs.R - -def using_modifier(ob): - for m in ob.modifiers: - if m[Blender.Modifier.Settings.REALTIME]: - return True - return False - -def mouseup(): - # Loop until click - mouse_buttons = Window.GetMouseButtons() - while not mouse_buttons & LMB: - sys.sleep(10) - mouse_buttons = Window.GetMouseButtons() - while mouse_buttons & LMB: - sys.sleep(10) - mouse_buttons = Window.GetMouseButtons() - -def mousedown_wait(): - # If the menu has just been pressed dont use its mousedown, - mouse_buttons = Window.GetMouseButtons() - while mouse_buttons & LMB: - mouse_buttons = Window.GetMouseButtons() - sys.sleep(10) - -def main(): - - scn = bpy.data.scenes.active - ob = scn.objects.active - if not ob or ob.type!='Mesh': - return - - is_editmode = Window.EditMode() - if is_editmode: - Window.EditMode(0) - - mousedown_wait() # so the menu items clicking dosnt trigger the mouseclick - - Window.DrawProgressBar (0.0, '') - Window.DrawProgressBar (0.1, '(1 of 3) Click on a face corner') - - # wait for a click - mouse_buttons = Window.GetMouseButtons() - while not mouse_buttons & LMB: - sys.sleep(10) - mouse_buttons = Window.GetMouseButtons() - - # Allow for RMB cancel - if mouse_buttons & RMB: - return - - while mouse_buttons & LMB: - sys.sleep(10) - mouse_buttons = Window.GetMouseButtons() - - - Window.DrawProgressBar (0.2, '(2 of 3 ) Click confirms the U coords') - - mousedown_wait() - - obmat= ob.matrixWorld - screen_x, screen_y = Window.GetMouseCoords() - mouseInView, OriginA, DirectionA = mouseViewRay(screen_x, screen_y, obmat) - - if not mouseInView or not OriginA: - return - - me = ob.getData(mesh=1) - - # Get the face under the mouse - face_click, isect, side = BPyMesh.pickMeshRayFace(me, OriginA, DirectionA) - if not face_click: - return - - proj_z_component = face_click.no - if not face_click: - return - - # Find the face vertex thats closest to the mouse, - # this vert will be used as the corner to map from. - best_v= None - best_length = 10000000 - vi1 = None - for i, v in enumerate(face_click.v): - l = (v.co-isect).length - if l < best_length: - best_v = v - best_length = l - vi1 = i - - # now get the 2 edges in the face that connect to v - # we can work it out fairly easerly - if len(face_click)==4: - if vi1==0: vi2, vi3= 3,1 - elif vi1==1: vi2, vi3= 0,2 - elif vi1==2: vi2, vi3= 1,3 - elif vi1==3: vi2, vi3= 2,0 - else: - if vi1==0: vi2, vi3= 2,1 - elif vi1==1: vi2, vi3= 0,2 - elif vi1==2: vi2, vi3= 1,0 - - face_corner_main =face_click.v[vi1].co - face_corner_a =face_click.v[vi2].co - face_corner_b =face_click.v[vi3].co - - line_a_len = (face_corner_a-face_corner_main).length - line_b_len = (face_corner_b-face_corner_main).length - - orig_cursor = Window.GetCursorPos() - Window.SetCursorPos(face_corner_main.x, face_corner_main.y, face_corner_main.z) - - SHIFT = Window.Qual.SHIFT - MODE = 0 # firstclick, 1, secondclick - mouse_buttons = Window.GetMouseButtons() - - project_mat = Matrix([0,0,0], [0,0,0], [0,0,0]) - - - def get_face_coords(f): - f_uv = f.uv - return [(v.co-face_corner_main, f_uv[i]) for i,v in enumerate(f.v)] - - if me.faceUV==False: - me.faceUV= True - - coords = [ (co,uv) for f in me.faces if f.sel for co, uv in get_face_coords(f)] - - coords_orig = [uv.copy() for co, uv in coords] - USE_MODIFIER = using_modifier(ob) - - while 1: - if mouse_buttons & LMB: - if MODE == 0: - mousedown_wait() - Window.DrawProgressBar (0.8, '(3 of 3 ) Click confirms the V coords') - MODE = 1 # second click - - # Se we cont continually set the length and get float error - proj_y_component_orig = proj_y_component.copy() - else: - break - - elif mouse_buttons & RMB: - # Restore old uvs - for i, uv_orig in enumerate(coords_orig): - coords[i][1][:] = uv_orig - break - - mouse_buttons = Window.GetMouseButtons() - screen_x, screen_y = Window.GetMouseCoords() - mouseInView, OriginA, DirectionA = mouseViewRay(screen_x, screen_y, obmat) - - if not mouseInView: - continue - - # Do a ray tri intersection, not clipped by the tri - new_isect = Intersect(face_corner_main, face_corner_a, face_corner_b, DirectionA, OriginA, False) - new_isect_alt = new_isect + DirectionA*0.0001 - - - # The distance from the mouse cursor ray vector to the edge - line_isect_a_pair = LineIntersect(new_isect, new_isect_alt, face_corner_main, face_corner_a) - line_isect_b_pair = LineIntersect(new_isect, new_isect_alt, face_corner_main, face_corner_b) - - # SHIFT to flip the axis. - is_shift = Window.GetKeyQualifiers() & SHIFT - - if MODE == 0: - line_dist_a = (line_isect_a_pair[0]-line_isect_a_pair[1]).length - line_dist_b = (line_isect_b_pair[0]-line_isect_b_pair[1]).length - - if line_dist_a < line_dist_b: - proj_x_component = face_corner_a - face_corner_main - y_axis_length = line_b_len - x_axis_length = (line_isect_a_pair[1]-face_corner_main).length - else: - proj_x_component = face_corner_b - face_corner_main - y_axis_length = line_a_len - x_axis_length = (line_isect_b_pair[1]-face_corner_main).length - - proj_y_component = proj_x_component.cross(proj_z_component) - - proj_y_component.length = 1/y_axis_length - proj_x_component.length = 1/x_axis_length - - if is_shift: proj_x_component.negate() - - else: - proj_y_component[:] = proj_y_component_orig - if line_dist_a < line_dist_b: - proj_y_component.length = 1/(line_isect_a_pair[1]-new_isect).length - else: - proj_y_component.length = 1/(line_isect_b_pair[1]-new_isect).length - - if is_shift: proj_y_component.negate() - - # Use the existing matrix to make a new 3x3 projecton matrix - project_mat[0][:] = -proj_y_component - project_mat[1][:] = -proj_x_component - project_mat[2][:] = proj_z_component - - # Apply the projection matrix - for proj_co, uv in coords: - uv[:] = (project_mat * proj_co)[0:2] - - if USE_MODIFIER: - me.update() - - Window.Redraw(Window.Types.VIEW3D) - - Window.SetCursorPos(*orig_cursor) - if is_editmode: - Window.EditMode(1) - - Window.RedrawAll() - -if __name__=='__main__': - main() - Window.DrawProgressBar(1.0, '') - diff --git a/release/scripts/uvcalc_smart_project.py b/release/scripts/uvcalc_smart_project.py deleted file mode 100644 index 9d9bd2aaefd..00000000000 --- a/release/scripts/uvcalc_smart_project.py +++ /dev/null @@ -1,1132 +0,0 @@ -#!BPY - -""" Registration info for Blender menus: <- these words are ignored -Name: 'Unwrap (smart projections)' -Blender: 240 -Group: 'UVCalculation' -Tooltip: 'UV Unwrap mesh faces for all select mesh objects' -""" - - -__author__ = "Campbell Barton" -__url__ = ("blender", "blenderartists.org") -__version__ = "1.1 12/18/05" - -__bpydoc__ = """\ -This script projection unwraps the selected faces of a mesh. - -it operates on all selected mesh objects, and can be used unwrap -selected faces, or all faces. -""" - -# -------------------------------------------------------------------------- -# Smart Projection UV Projection Unwrapper v1.1 by Campbell Barton (AKA Ideasman) -# -------------------------------------------------------------------------- -# ***** 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 ***** -# -------------------------------------------------------------------------- - - -from Blender import Object, Draw, Window, sys, Mesh, Geometry -from Blender.Mathutils import Matrix, Vector, RotationMatrix -import bpy -from math import cos - -DEG_TO_RAD = 0.017453292519943295 # pi/180.0 -SMALL_NUM = 0.000000001 -BIG_NUM = 1e15 - -global USER_FILL_HOLES -global USER_FILL_HOLES_QUALITY -USER_FILL_HOLES = None -USER_FILL_HOLES_QUALITY = None - -dict_matrix = {} - -def pointInTri2D(v, v1, v2, v3): - global dict_matrix - - key = v1.x, v1.y, v2.x, v2.y, v3.x, v3.y - - # Commented because its slower to do teh bounds check, we should realy cache the bounds info for each face. - ''' - # BOUNDS CHECK - xmin= 1000000 - ymin= 1000000 - - xmax= -1000000 - ymax= -1000000 - - for i in (0,2,4): - x= key[i] - y= key[i+1] - - if xmax<x: xmax= x - if ymax<y: ymax= y - if xmin>x: xmin= x - if ymin>y: ymin= y - - x= v.x - y= v.y - - if x<xmin or x>xmax or y < ymin or y > ymax: - return False - # Done with bounds check - ''' - try: - mtx = dict_matrix[key] - if not mtx: - return False - except: - side1 = v2 - v1 - side2 = v3 - v1 - - nor = side1.cross(side2) - - l1 = [side1[0], side1[1], side1[2]] - l2 = [side2[0], side2[1], side2[2]] - l3 = [nor[0], nor[1], nor[2]] - - mtx = Matrix(l1, l2, l3) - - # Zero area 2d tri, even tho we throw away zerop area faces - # the projection UV can result in a zero area UV. - if not mtx.determinant(): - dict_matrix[key] = None - return False - - mtx.invert() - - dict_matrix[key] = mtx - - uvw = (v - v1) * mtx - return 0 <= uvw[0] and 0 <= uvw[1] and uvw[0] + uvw[1] <= 1 - - -def boundsIsland(faces): - minx = maxx = faces[0].uv[0][0] # Set initial bounds. - miny = maxy = faces[0].uv[0][1] - # print len(faces), minx, maxx, miny , maxy - for f in faces: - for uv in f.uv: - x= uv.x - y= uv.y - if x<minx: minx= x - if y<miny: miny= y - if x>maxx: maxx= x - if y>maxy: maxy= y - - return minx, miny, maxx, maxy - -""" -def boundsEdgeLoop(edges): - minx = maxx = edges[0][0] # Set initial bounds. - miny = maxy = edges[0][1] - # print len(faces), minx, maxx, miny , maxy - for ed in edges: - for pt in ed: - print 'ass' - x= pt[0] - y= pt[1] - if x<minx: x= minx - if y<miny: y= miny - if x>maxx: x= maxx - if y>maxy: y= maxy - - return minx, miny, maxx, maxy -""" - -# Turns the islands into a list of unpordered edges (Non internal) -# Onlt for UV's -# only returns outline edges for intersection tests. and unique points. - -def island2Edge(island): - - # Vert index edges - edges = {} - - unique_points= {} - - for f in island: - f_uvkey= map(tuple, f.uv) - - - for vIdx, edkey in enumerate(f.edge_keys): - unique_points[f_uvkey[vIdx]] = f.uv[vIdx] - - if f.v[vIdx].index > f.v[vIdx-1].index: - i1= vIdx-1; i2= vIdx - else: - i1= vIdx; i2= vIdx-1 - - try: edges[ f_uvkey[i1], f_uvkey[i2] ] *= 0 # sets eny edge with more then 1 user to 0 are not returned. - except: edges[ f_uvkey[i1], f_uvkey[i2] ] = (f.uv[i1] - f.uv[i2]).length, - - # If 2 are the same then they will be together, but full [a,b] order is not correct. - - # Sort by length - - - length_sorted_edges = [(Vector(key[0]), Vector(key[1]), value) for key, value in edges.iteritems() if value != 0] - - try: length_sorted_edges.sort(key = lambda A: -A[2]) # largest first - except: length_sorted_edges.sort(lambda A, B: cmp(B[2], A[2])) - - # Its okay to leave the length in there. - #for e in length_sorted_edges: - # e.pop(2) - - # return edges and unique points - return length_sorted_edges, [v.__copy__().resize3D() for v in unique_points.itervalues()] - -# ========================= NOT WORKING???? -# Find if a points inside an edge loop, un-orderd. -# pt is and x/y -# edges are a non ordered loop of edges. -# #offsets are the edge x and y offset. -""" -def pointInEdges(pt, edges): - # - x1 = pt[0] - y1 = pt[1] - - # Point to the left of this line. - x2 = -100000 - y2 = -10000 - intersectCount = 0 - for ed in edges: - xi, yi = lineIntersection2D(x1,y1, x2,y2, ed[0][0], ed[0][1], ed[1][0], ed[1][1]) - if xi != None: # Is there an intersection. - intersectCount+=1 - - return intersectCount % 2 -""" - -def pointInIsland(pt, island): - vec1 = Vector(); vec2 = Vector(); vec3 = Vector() - for f in island: - vec1.x, vec1.y = f.uv[0] - vec2.x, vec2.y = f.uv[1] - vec3.x, vec3.y = f.uv[2] - - if pointInTri2D(pt, vec1, vec2, vec3): - return True - - if len(f.v) == 4: - vec1.x, vec1.y = f.uv[0] - vec2.x, vec2.y = f.uv[2] - vec3.x, vec3.y = f.uv[3] - if pointInTri2D(pt, vec1, vec2, vec3): - return True - return False - - -# box is (left,bottom, right, top) -def islandIntersectUvIsland(source, target, SourceOffset): - # Is 1 point in the box, inside the vertLoops - edgeLoopsSource = source[6] # Pretend this is offset - edgeLoopsTarget = target[6] - - # Edge intersect test - for ed in edgeLoopsSource: - for seg in edgeLoopsTarget: - i = Geometry.LineIntersect2D(\ - seg[0], seg[1], SourceOffset+ed[0], SourceOffset+ed[1]) - if i: - return 1 # LINE INTERSECTION - - # 1 test for source being totally inside target - SourceOffset.resize3D() - for pv in source[7]: - if pointInIsland(pv+SourceOffset, target[0]): - return 2 # SOURCE INSIDE TARGET - - # 2 test for a part of the target being totaly inside the source. - for pv in target[7]: - if pointInIsland(pv-SourceOffset, source[0]): - return 3 # PART OF TARGET INSIDE SOURCE. - - return 0 # NO INTERSECTION - - - - -# Returns the X/y Bounds of a list of vectors. -def testNewVecLs2DRotIsBetter(vecs, mat=-1, bestAreaSoFar = -1): - - # UV's will never extend this far. - minx = miny = BIG_NUM - maxx = maxy = -BIG_NUM - - for i, v in enumerate(vecs): - - # Do this allong the way - if mat != -1: - v = vecs[i] = v*mat - x= v.x - y= v.y - if x<minx: minx= x - if y<miny: miny= y - if x>maxx: maxx= x - if y>maxy: maxy= y - - # Spesific to this algo, bail out if we get bigger then the current area - if bestAreaSoFar != -1 and (maxx-minx) * (maxy-miny) > bestAreaSoFar: - return (BIG_NUM, None), None - w = maxx-minx - h = maxy-miny - return (w*h, w,h), vecs # Area, vecs - -# Takes a list of faces that make up a UV island and rotate -# until they optimally fit inside a square. -ROTMAT_2D_POS_90D = RotationMatrix( 90, 2) -ROTMAT_2D_POS_45D = RotationMatrix( 45, 2) - -RotMatStepRotation = [] -rot_angle = 22.5 #45.0/2 -while rot_angle > 0.1: - RotMatStepRotation.append([\ - RotationMatrix( rot_angle, 2),\ - RotationMatrix( -rot_angle, 2)]) - - rot_angle = rot_angle/2.0 - - -def optiRotateUvIsland(faces): - global currentArea - - # Bestfit Rotation - def best2dRotation(uvVecs, MAT1, MAT2): - global currentArea - - newAreaPos, newfaceProjectionGroupListPos =\ - testNewVecLs2DRotIsBetter(uvVecs[:], MAT1, currentArea[0]) - - - # Why do I use newpos here? May as well give the best area to date for an early bailout - # some slight speed increase in this. - # If the new rotation is smaller then the existing, we can - # avoid copying a list and overwrite the old, crappy one. - - if newAreaPos[0] < currentArea[0]: - newAreaNeg, newfaceProjectionGroupListNeg =\ - testNewVecLs2DRotIsBetter(uvVecs, MAT2, newAreaPos[0]) # Reuse the old bigger list. - else: - newAreaNeg, newfaceProjectionGroupListNeg =\ - testNewVecLs2DRotIsBetter(uvVecs[:], MAT2, currentArea[0]) # Cant reuse, make a copy. - - - # Now from the 3 options we need to discover which to use - # we have cerrentArea/newAreaPos/newAreaNeg - bestArea = min(currentArea[0], newAreaPos[0], newAreaNeg[0]) - - if currentArea[0] == bestArea: - return uvVecs - elif newAreaPos[0] == bestArea: - uvVecs = newfaceProjectionGroupListPos - currentArea = newAreaPos - elif newAreaNeg[0] == bestArea: - uvVecs = newfaceProjectionGroupListNeg - currentArea = newAreaNeg - - return uvVecs - - - # Serialized UV coords to Vectors - uvVecs = [uv for f in faces for uv in f.uv] - - # Theres a small enough number of these to hard code it - # rather then a loop. - - # Will not modify anything - currentArea, dummy =\ - testNewVecLs2DRotIsBetter(uvVecs) - - - # Try a 45d rotation - newAreaPos, newfaceProjectionGroupListPos = testNewVecLs2DRotIsBetter(uvVecs[:], ROTMAT_2D_POS_45D, currentArea[0]) - - if newAreaPos[0] < currentArea[0]: - uvVecs = newfaceProjectionGroupListPos - currentArea = newAreaPos - # 45d done - - # Testcase different rotations and find the onfe that best fits in a square - for ROTMAT in RotMatStepRotation: - uvVecs = best2dRotation(uvVecs, ROTMAT[0], ROTMAT[1]) - - # Only if you want it, make faces verticle! - if currentArea[1] > currentArea[2]: - # Rotate 90d - # Work directly on the list, no need to return a value. - testNewVecLs2DRotIsBetter(uvVecs, ROTMAT_2D_POS_90D) - - - # Now write the vectors back to the face UV's - i = 0 # count the serialized uv/vectors - for f in faces: - #f.uv = [uv for uv in uvVecs[i:len(f)+i] ] - for j, k in enumerate(xrange(i, len(f.v)+i)): - f.uv[j][:] = uvVecs[k] - i += len(f.v) - - -# Takes an island list and tries to find concave, hollow areas to pack smaller islands into. -def mergeUvIslands(islandList): - global USER_FILL_HOLES - global USER_FILL_HOLES_QUALITY - - - # Pack islands to bottom LHS - # Sync with island - - #islandTotFaceArea = [] # A list of floats, each island area - #islandArea = [] # a list of tuples ( area, w,h) - - - decoratedIslandList = [] - - islandIdx = len(islandList) - while islandIdx: - islandIdx-=1 - minx, miny, maxx, maxy = boundsIsland(islandList[islandIdx]) - w, h = maxx-minx, maxy-miny - - totFaceArea = 0 - offset= Vector(minx, miny) - for f in islandList[islandIdx]: - for uv in f.uv: - uv -= offset - - totFaceArea += f.area - - islandBoundsArea = w*h - efficiency = abs(islandBoundsArea - totFaceArea) - - # UV Edge list used for intersections as well as unique points. - edges, uniqueEdgePoints = island2Edge(islandList[islandIdx]) - - decoratedIslandList.append([islandList[islandIdx], totFaceArea, efficiency, islandBoundsArea, w,h, edges, uniqueEdgePoints]) - - - # Sort by island bounding box area, smallest face area first. - # no.. chance that to most simple edge loop first. - decoratedIslandListAreaSort =decoratedIslandList[:] - - try: decoratedIslandListAreaSort.sort(key = lambda A: A[3]) - except: decoratedIslandListAreaSort.sort(lambda A, B: cmp(A[3], B[3])) - - - # sort by efficiency, Least Efficient first. - decoratedIslandListEfficSort = decoratedIslandList[:] - # decoratedIslandListEfficSort.sort(lambda A, B: cmp(B[2], A[2])) - - try: decoratedIslandListEfficSort.sort(key = lambda A: -A[2]) - except: decoratedIslandListEfficSort.sort(lambda A, B: cmp(B[2], A[2])) - - # ================================================== THESE CAN BE TWEAKED. - # This is a quality value for the number of tests. - # from 1 to 4, generic quality value is from 1 to 100 - USER_STEP_QUALITY = ((USER_FILL_HOLES_QUALITY - 1) / 25.0) + 1 - - # If 100 will test as long as there is enough free space. - # this is rarely enough, and testing takes a while, so lower quality speeds this up. - - # 1 means they have the same quality - USER_FREE_SPACE_TO_TEST_QUALITY = 1 + (((100 - USER_FILL_HOLES_QUALITY)/100.0) *5) - - #print 'USER_STEP_QUALITY', USER_STEP_QUALITY - #print 'USER_FREE_SPACE_TO_TEST_QUALITY', USER_FREE_SPACE_TO_TEST_QUALITY - - removedCount = 0 - - areaIslandIdx = 0 - ctrl = Window.Qual.CTRL - BREAK= False - while areaIslandIdx < len(decoratedIslandListAreaSort) and not BREAK: - sourceIsland = decoratedIslandListAreaSort[areaIslandIdx] - # Alredy packed? - if not sourceIsland[0]: - areaIslandIdx+=1 - else: - efficIslandIdx = 0 - while efficIslandIdx < len(decoratedIslandListEfficSort) and not BREAK: - - if Window.GetKeyQualifiers() & ctrl: - BREAK= True - break - - # Now we have 2 islands, is the efficience of the islands lowers theres an - # increasing likely hood that we can fit merge into the bigger UV island. - # this ensures a tight fit. - - # Just use figures we have about user/unused area to see if they might fit. - - targetIsland = decoratedIslandListEfficSort[efficIslandIdx] - - - if sourceIsland[0] == targetIsland[0] or\ - not targetIsland[0] or\ - not sourceIsland[0]: - pass - else: - - # ([island, totFaceArea, efficiency, islandArea, w,h]) - # Waisted space on target is greater then UV bounding island area. - - - # if targetIsland[3] > (sourceIsland[2]) and\ # - # print USER_FREE_SPACE_TO_TEST_QUALITY, 'ass' - if targetIsland[2] > (sourceIsland[1] * USER_FREE_SPACE_TO_TEST_QUALITY) and\ - targetIsland[4] > sourceIsland[4] and\ - targetIsland[5] > sourceIsland[5]: - - # DEBUG # print '%.10f %.10f' % (targetIsland[3], sourceIsland[1]) - - # These enough spare space lets move the box until it fits - - # How many times does the source fit into the target x/y - blockTestXUnit = targetIsland[4]/sourceIsland[4] - blockTestYUnit = targetIsland[5]/sourceIsland[5] - - boxLeft = 0 - - - # Distllllance we can move between whilst staying inside the targets bounds. - testWidth = targetIsland[4] - sourceIsland[4] - testHeight = targetIsland[5] - sourceIsland[5] - - # Increment we move each test. x/y - xIncrement = (testWidth / (blockTestXUnit * ((USER_STEP_QUALITY/50)+0.1))) - yIncrement = (testHeight / (blockTestYUnit * ((USER_STEP_QUALITY/50)+0.1))) - - # Make sure were not moving less then a 3rg of our width/height - if xIncrement<sourceIsland[4]/3: - xIncrement= sourceIsland[4] - if yIncrement<sourceIsland[5]/3: - yIncrement= sourceIsland[5] - - - boxLeft = 0 # Start 1 back so we can jump into the loop. - boxBottom= 0 #-yIncrement - - ##testcount= 0 - - while boxBottom <= testHeight: - # Should we use this? - not needed for now. - #if Window.GetKeyQualifiers() & ctrl: - # BREAK= True - # break - - ##testcount+=1 - #print 'Testing intersect' - Intersect = islandIntersectUvIsland(sourceIsland, targetIsland, Vector(boxLeft, boxBottom)) - #print 'Done', Intersect - if Intersect == 1: # Line intersect, dont bother with this any more - pass - - if Intersect == 2: # Source inside target - ''' - We have an intersection, if we are inside the target - then move us 1 whole width accross, - Its possible this is a bad idea since 2 skinny Angular faces - could join without 1 whole move, but its a lot more optimal to speed this up - since we have alredy tested for it. - - It gives about 10% speedup with minimal errors. - ''' - #print 'ass' - # Move the test allong its width + SMALL_NUM - #boxLeft += sourceIsland[4] + SMALL_NUM - boxLeft += sourceIsland[4] - elif Intersect == 0: # No intersection?? Place it. - # Progress - removedCount +=1 - Window.DrawProgressBar(0.0, 'Merged: %i islands, Ctrl to finish early.' % removedCount) - - # Move faces into new island and offset - targetIsland[0].extend(sourceIsland[0]) - offset= Vector(boxLeft, boxBottom) - - for f in sourceIsland[0]: - for uv in f.uv: - uv+= offset - - sourceIsland[0][:] = [] # Empty - - - # Move edge loop into new and offset. - # targetIsland[6].extend(sourceIsland[6]) - #while sourceIsland[6]: - targetIsland[6].extend( [ (\ - (e[0]+offset, e[1]+offset, e[2])\ - ) for e in sourceIsland[6] ] ) - - sourceIsland[6][:] = [] # Empty - - # Sort by edge length, reverse so biggest are first. - - try: targetIsland[6].sort(key = lambda A: A[2]) - except: targetIsland[6].sort(lambda B,A: cmp(A[2], B[2] )) - - - targetIsland[7].extend(sourceIsland[7]) - offset= Vector(boxLeft, boxBottom, 0) - for p in sourceIsland[7]: - p+= offset - - sourceIsland[7][:] = [] - - - # Decrement the efficiency - targetIsland[1]+=sourceIsland[1] # Increment totFaceArea - targetIsland[2]-=sourceIsland[1] # Decrement efficiency - # IF we ever used these again, should set to 0, eg - sourceIsland[2] = 0 # No area if anyone wants to know - - break - - - # INCREMENR NEXT LOCATION - if boxLeft > testWidth: - boxBottom += yIncrement - boxLeft = 0.0 - else: - boxLeft += xIncrement - ##print testcount - - efficIslandIdx+=1 - areaIslandIdx+=1 - - # Remove empty islands - i = len(islandList) - while i: - i-=1 - if not islandList[i]: - del islandList[i] # Can increment islands removed here. - -# Takes groups of faces. assumes face groups are UV groups. -def getUvIslands(faceGroups, me): - - # Get seams so we dont cross over seams - edge_seams = {} # shoudl be a set - SEAM = Mesh.EdgeFlags.SEAM - for ed in me.edges: - if ed.flag & SEAM: - edge_seams[ed.key] = None # dummy var- use sets! - # Done finding seams - - - islandList = [] - - Window.DrawProgressBar(0.0, 'Splitting %d projection groups into UV islands:' % len(faceGroups)) - #print '\tSplitting %d projection groups into UV islands:' % len(faceGroups), - # Find grouped faces - - faceGroupIdx = len(faceGroups) - - while faceGroupIdx: - faceGroupIdx-=1 - faces = faceGroups[faceGroupIdx] - - if not faces: - continue - - # Build edge dict - edge_users = {} - - for i, f in enumerate(faces): - for ed_key in f.edge_keys: - if edge_seams.has_key(ed_key): # DELIMIT SEAMS! ;) - edge_users[ed_key] = [] # so as not to raise an error - else: - try: edge_users[ed_key].append(i) - except: edge_users[ed_key] = [i] - - # Modes - # 0 - face not yet touched. - # 1 - added to island list, and need to search - # 2 - touched and searched - dont touch again. - face_modes = [0] * len(faces) # initialize zero - untested. - - face_modes[0] = 1 # start the search with face 1 - - newIsland = [] - - newIsland.append(faces[0]) - - - ok = True - while ok: - - ok = True - while ok: - ok= False - for i in xrange(len(faces)): - if face_modes[i] == 1: # search - for ed_key in faces[i].edge_keys: - for ii in edge_users[ed_key]: - if i != ii and face_modes[ii] == 0: - face_modes[ii] = ok = 1 # mark as searched - newIsland.append(faces[ii]) - - # mark as searched, dont look again. - face_modes[i] = 2 - - islandList.append(newIsland) - - ok = False - for i in xrange(len(faces)): - if face_modes[i] == 0: - newIsland = [] - newIsland.append(faces[i]) - - face_modes[i] = ok = 1 - break - # if not ok will stop looping - - Window.DrawProgressBar(0.1, 'Optimizing Rotation for %i UV Islands' % len(islandList)) - - for island in islandList: - optiRotateUvIsland(island) - - return islandList - - -def packIslands(islandList): - if USER_FILL_HOLES: - Window.DrawProgressBar(0.1, 'Merging Islands (Ctrl: skip merge)...') - mergeUvIslands(islandList) # Modify in place - - - # Now we have UV islands, we need to pack them. - - # Make a synchronised list with the islands - # so we can box pak the islands. - packBoxes = [] - - # Keep a list of X/Y offset so we can save time by writing the - # uv's and packed data in one pass. - islandOffsetList = [] - - islandIdx = 0 - - while islandIdx < len(islandList): - minx, miny, maxx, maxy = boundsIsland(islandList[islandIdx]) - - w, h = maxx-minx, maxy-miny - - if USER_ISLAND_MARGIN: - minx -= USER_ISLAND_MARGIN# *w - miny -= USER_ISLAND_MARGIN# *h - maxx += USER_ISLAND_MARGIN# *w - maxy += USER_ISLAND_MARGIN# *h - - # recalc width and height - w, h = maxx-minx, maxy-miny - - if w < 0.00001 or h < 0.00001: - del islandList[islandIdx] - islandIdx -=1 - continue - - '''Save the offset to be applied later, - we could apply to the UVs now and allign them to the bottom left hand area - of the UV coords like the box packer imagines they are - but, its quicker just to remember their offset and - apply the packing and offset in 1 pass ''' - islandOffsetList.append((minx, miny)) - - # Add to boxList. use the island idx for the BOX id. - packBoxes.append([0, 0, w, h]) - islandIdx+=1 - - # Now we have a list of boxes to pack that syncs - # with the islands. - - #print '\tPacking UV Islands...' - Window.DrawProgressBar(0.7, 'Packing %i UV Islands...' % len(packBoxes) ) - - time1 = sys.time() - packWidth, packHeight = Geometry.BoxPack2D(packBoxes) - - # print 'Box Packing Time:', sys.time() - time1 - - #if len(pa ckedLs) != len(islandList): - # raise "Error packed boxes differes from original length" - - #print '\tWriting Packed Data to faces' - Window.DrawProgressBar(0.8, 'Writing Packed Data to faces') - - # Sort by ID, so there in sync again - islandIdx = len(islandList) - # Having these here avoids devide by 0 - if islandIdx: - - if USER_STRETCH_ASPECT: - # Maximize to uv area?? Will write a normalize function. - xfactor = 1.0 / packWidth - yfactor = 1.0 / packHeight - else: - # Keep proportions. - xfactor = yfactor = 1.0 / max(packWidth, packHeight) - - while islandIdx: - islandIdx -=1 - # Write the packed values to the UV's - - xoffset = packBoxes[islandIdx][0] - islandOffsetList[islandIdx][0] - yoffset = packBoxes[islandIdx][1] - islandOffsetList[islandIdx][1] - - for f in islandList[islandIdx]: # Offsetting the UV's so they fit in there packed box - for uv in f.uv: - uv.x= (uv.x+xoffset) * xfactor - uv.y= (uv.y+yoffset) * yfactor - - - -def VectoMat(vec): - a3 = vec.__copy__().normalize() - - up = Vector(0,0,1) - if abs(a3.dot(up)) == 1.0: - up = Vector(0,1,0) - - a1 = a3.cross(up).normalize() - a2 = a3.cross(a1) - return Matrix([a1[0], a1[1], a1[2]], [a2[0], a2[1], a2[2]], [a3[0], a3[1], a3[2]]) - - - -class thickface(object): - __slost__= 'v', 'uv', 'no', 'area', 'edge_keys' - def __init__(self, face): - self.v = face.v - self.uv = face.uv - self.no = face.no - self.area = face.area - self.edge_keys = face.edge_keys - -global ob -ob = None -def main(): - global USER_FILL_HOLES - global USER_FILL_HOLES_QUALITY - global USER_STRETCH_ASPECT - global USER_ISLAND_MARGIN - - objects= bpy.data.scenes.active.objects - - # we can will tag them later. - obList = [ob for ob in objects.context if ob.type == 'Mesh'] - - # Face select object may not be selected. - ob = objects.active - if ob and ob.sel == 0 and ob.type == 'Mesh': - # Add to the list - obList =[ob] - del objects - - if not obList: - Draw.PupMenu('error, no selected mesh objects') - return - - # Create the variables. - USER_PROJECTION_LIMIT = Draw.Create(66) - USER_ONLY_SELECTED_FACES = Draw.Create(1) - USER_SHARE_SPACE = Draw.Create(1) # Only for hole filling. - USER_STRETCH_ASPECT = Draw.Create(1) # Only for hole filling. - USER_ISLAND_MARGIN = Draw.Create(0.0) # Only for hole filling. - USER_FILL_HOLES = Draw.Create(0) - USER_FILL_HOLES_QUALITY = Draw.Create(50) # Only for hole filling. - USER_VIEW_INIT = Draw.Create(0) # Only for hole filling. - USER_AREA_WEIGHT = Draw.Create(1) # Only for hole filling. - - - pup_block = [\ - 'Projection',\ - ('Angle Limit:', USER_PROJECTION_LIMIT, 1, 89, 'lower for more projection groups, higher for less distortion.'),\ - ('Selected Faces Only', USER_ONLY_SELECTED_FACES, 'Use only selected faces from all selected meshes.'),\ - ('Init from view', USER_VIEW_INIT, 'The first projection will be from the view vector.'),\ - ('Area Weight', USER_AREA_WEIGHT, 'Weight projections vector by face area.'),\ - '',\ - '',\ - '',\ - 'UV Layout',\ - ('Share Tex Space', USER_SHARE_SPACE, 'Objects Share texture space, map all objects into 1 uvmap.'),\ - ('Stretch to bounds', USER_STRETCH_ASPECT, 'Stretch the final output to texture bounds.'),\ - ('Island Margin:', USER_ISLAND_MARGIN, 0.0, 0.5, 'Margin to reduce bleed from adjacent islands.'),\ - 'Fill in empty areas',\ - ('Fill Holes', USER_FILL_HOLES, 'Fill in empty areas reduced texture waistage (slow).'),\ - ('Fill Quality:', USER_FILL_HOLES_QUALITY, 1, 100, 'Depends on fill holes, how tightly to fill UV holes, (higher is slower)'),\ - ] - - # Reuse variable - if len(obList) == 1: - ob = "Unwrap %i Selected Mesh" - else: - ob = "Unwrap %i Selected Meshes" - - # HACK, loop until mouse is lifted. - ''' - while Window.GetMouseButtons() != 0: - sys.sleep(10) - ''' - - if not Draw.PupBlock(ob % len(obList), pup_block): - return - del ob - - # Convert from being button types - USER_PROJECTION_LIMIT = USER_PROJECTION_LIMIT.val - USER_ONLY_SELECTED_FACES = USER_ONLY_SELECTED_FACES.val - USER_SHARE_SPACE = USER_SHARE_SPACE.val - USER_STRETCH_ASPECT = USER_STRETCH_ASPECT.val - USER_ISLAND_MARGIN = USER_ISLAND_MARGIN.val - USER_FILL_HOLES = USER_FILL_HOLES.val - USER_FILL_HOLES_QUALITY = USER_FILL_HOLES_QUALITY.val - USER_VIEW_INIT = USER_VIEW_INIT.val - USER_AREA_WEIGHT = USER_AREA_WEIGHT.val - - USER_PROJECTION_LIMIT_CONVERTED = cos(USER_PROJECTION_LIMIT * DEG_TO_RAD) - USER_PROJECTION_LIMIT_HALF_CONVERTED = cos((USER_PROJECTION_LIMIT/2) * DEG_TO_RAD) - - - # Toggle Edit mode - is_editmode = Window.EditMode() - if is_editmode: - Window.EditMode(0) - # Assume face select mode! an annoying hack to toggle face select mode because Mesh dosent like faceSelectMode. - - if USER_SHARE_SPACE: - # Sort by data name so we get consistant results - try: obList.sort(key = lambda ob: ob.getData(name_only=1)) - except: obList.sort(lambda ob1, ob2: cmp( ob1.getData(name_only=1), ob2.getData(name_only=1) )) - - collected_islandList= [] - - Window.WaitCursor(1) - - time1 = sys.time() - - # Tag as False se we dont operate on teh same mesh twice. - bpy.data.meshes.tag = False - - for ob in obList: - me = ob.getData(mesh=1) - - if me.tag or me.lib: - continue - - # Tag as used - me.tag = True - - if not me.faceUV: # Mesh has no UV Coords, dont bother. - me.faceUV= True - - if USER_ONLY_SELECTED_FACES: - meshFaces = [thickface(f) for f in me.faces if f.sel] - else: - meshFaces = map(thickface, me.faces) - - if not meshFaces: - continue - - Window.DrawProgressBar(0.1, 'SmartProj UV Unwrapper, mapping "%s", %i faces.' % (me.name, len(meshFaces))) - - # ======= - # Generate a projection list from face normals, this is ment to be smart :) - - # make a list of face props that are in sync with meshFaces - # Make a Face List that is sorted by area. - # meshFaces = [] - - # meshFaces.sort( lambda a, b: cmp(b.area , a.area) ) # Biggest first. - try: meshFaces.sort( key = lambda a: -a.area ) - except: meshFaces.sort( lambda a, b: cmp(b.area , a.area) ) - - # remove all zero area faces - while meshFaces and meshFaces[-1].area <= SMALL_NUM: - # Set their UV's to 0,0 - for uv in meshFaces[-1].uv: - uv.zero() - meshFaces.pop() - - # Smallest first is slightly more efficient, but if the user cancels early then its better we work on the larger data. - - # Generate Projection Vecs - # 0d is 1.0 - # 180 IS -0.59846 - - - # Initialize projectVecs - if USER_VIEW_INIT: - # Generate Projection - projectVecs = [Vector(Window.GetViewVector()) * ob.matrixWorld.copy().invert().rotationPart()] # We add to this allong the way - else: - projectVecs = [] - - newProjectVec = meshFaces[0].no - newProjectMeshFaces = [] # Popping stuffs it up. - - - # Predent that the most unique angke is ages away to start the loop off - mostUniqueAngle = -1.0 - - # This is popped - tempMeshFaces = meshFaces[:] - - - - # This while only gathers projection vecs, faces are assigned later on. - while 1: - # If theres none there then start with the largest face - - # add all the faces that are close. - for fIdx in xrange(len(tempMeshFaces)-1, -1, -1): - # Use half the angle limit so we dont overweight faces towards this - # normal and hog all the faces. - if newProjectVec.dot(tempMeshFaces[fIdx].no) > USER_PROJECTION_LIMIT_HALF_CONVERTED: - newProjectMeshFaces.append(tempMeshFaces.pop(fIdx)) - - # Add the average of all these faces normals as a projectionVec - averageVec = Vector(0,0,0) - if USER_AREA_WEIGHT: - for fprop in newProjectMeshFaces: - averageVec += (fprop.no * fprop.area) - else: - for fprop in newProjectMeshFaces: - averageVec += fprop.no - - if averageVec.x != 0 or averageVec.y != 0 or averageVec.z != 0: # Avoid NAN - projectVecs.append(averageVec.normalize()) - - - # Get the next vec! - # Pick the face thats most different to all existing angles :) - mostUniqueAngle = 1.0 # 1.0 is 0d. no difference. - mostUniqueIndex = 0 # dummy - - for fIdx in xrange(len(tempMeshFaces)-1, -1, -1): - angleDifference = -1.0 # 180d difference. - - # Get the closest vec angle we are to. - for p in projectVecs: - temp_angle_diff= p.dot(tempMeshFaces[fIdx].no) - - if angleDifference < temp_angle_diff: - angleDifference= temp_angle_diff - - if angleDifference < mostUniqueAngle: - # We have a new most different angle - mostUniqueIndex = fIdx - mostUniqueAngle = angleDifference - - if mostUniqueAngle < USER_PROJECTION_LIMIT_CONVERTED: - #print 'adding', mostUniqueAngle, USER_PROJECTION_LIMIT, len(newProjectMeshFaces) - # Now weight the vector to all its faces, will give a more direct projection - # if the face its self was not representive of the normal from surrounding faces. - - newProjectVec = tempMeshFaces[mostUniqueIndex].no - newProjectMeshFaces = [tempMeshFaces.pop(mostUniqueIndex)] - - - else: - if len(projectVecs) >= 1: # Must have at least 2 projections - break - - - # If there are only zero area faces then its possible - # there are no projectionVecs - if not len(projectVecs): - Draw.PupMenu('error, no projection vecs where generated, 0 area faces can cause this.') - return - - faceProjectionGroupList =[[] for i in xrange(len(projectVecs)) ] - - # MAP and Arrange # We know there are 3 or 4 faces here - - for fIdx in xrange(len(meshFaces)-1, -1, -1): - fvec = meshFaces[fIdx].no - i = len(projectVecs) - - # Initialize first - bestAng = fvec.dot(projectVecs[0]) - bestAngIdx = 0 - - # Cycle through the remaining, first alredy done - while i-1: - i-=1 - - newAng = fvec.dot(projectVecs[i]) - if newAng > bestAng: # Reverse logic for dotvecs - bestAng = newAng - bestAngIdx = i - - # Store the area for later use. - faceProjectionGroupList[bestAngIdx].append(meshFaces[fIdx]) - - # Cull faceProjectionGroupList, - - - # Now faceProjectionGroupList is full of faces that face match the project Vecs list - for i in xrange(len(projectVecs)): - # Account for projectVecs having no faces. - if not faceProjectionGroupList[i]: - continue - - # Make a projection matrix from a unit length vector. - MatProj = VectoMat(projectVecs[i]) - - # Get the faces UV's from the projected vertex. - for f in faceProjectionGroupList[i]: - f_uv = f.uv - for j, v in enumerate(f.v): - f_uv[j][:] = (MatProj * v.co)[:2] - - - if USER_SHARE_SPACE: - # Should we collect and pack later? - islandList = getUvIslands(faceProjectionGroupList, me) - collected_islandList.extend(islandList) - - else: - # Should we pack the islands for this 1 object? - islandList = getUvIslands(faceProjectionGroupList, me) - packIslands(islandList) - - - # update the mesh here if we need to. - - # We want to pack all in 1 go, so pack now - if USER_SHARE_SPACE: - Window.DrawProgressBar(0.9, "Box Packing for all objects...") - packIslands(collected_islandList) - - print "Smart Projection time: %.2f" % (sys.time() - time1) - # Window.DrawProgressBar(0.9, "Smart Projections done, time: %.2f sec." % (sys.time() - time1)) - - if is_editmode: - Window.EditMode(1) - - Window.DrawProgressBar(1.0, "") - Window.WaitCursor(0) - Window.RedrawAll() - -if __name__ == '__main__': - main() diff --git a/release/scripts/uvcopy.py b/release/scripts/uvcopy.py deleted file mode 100644 index 73206e47109..00000000000 --- a/release/scripts/uvcopy.py +++ /dev/null @@ -1,112 +0,0 @@ -#!BPY -""" Registration info for Blender menus: <- these words are ignored -Name: 'UV Copy from Active' -Blender: 242 -Group: 'Object' -Tip: 'Copy UV coords from a mesh to another that has same vertex indices' -""" - -__author__ = "Toni Alatalo, Martin Poirier et. al." -__url__ = ("blender", "blenderartists.org") -__version__ = "0.2 01/2006" - -__bpydoc__ = """\ -This script copies UV coords from a mesh to another (version of the same mesh). -All target meshes must have the same number of faces at the active -""" - -# ***** 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 ***** - -import Blender - -def face_key(me): - ''' - Returns the face lengths for this mesh - only copy between meshes that have matching face_key's - ''' - return tuple([len(f) for f in me.faces]) - -def main(): - scene = Blender.Scene.GetCurrent() - - source_ob = scene.objects.active - - if not source_ob or source_ob.type != 'Mesh': - Blender.Draw.PupMenu("Error%t|No active object to copy UVs from.") - return - - source_me = source_ob.getData(mesh=1) - - target_mes = [ ob.getData(mesh=1) for ob in scene.objects.context if ob != source_ob if ob.type == 'Mesh'] - - # remove double meshes - target_mes = dict([(me.name, me) for me in target_mes]) - target_mes = target_mes.values() - - if not target_mes: - Blender.Draw.PupMenu("Error%t|No selected object(s) to copy UVs to.") - return - - source_me = source_ob.getData(mesh=1) - - if not source_me.faceUV: - Blender.Draw.PupMenu("Error%t|Active mesh has no UVs.") - return - - if not target_mes: - Blender.Draw.PupMenu("Error%t|no selected object other than the source, hence no target defined.") - return - error = False - - source_face_key = face_key(source_me) - source_faces = source_me.faces - - fail_count = 0 - - for target in target_mes: - if len(source_me.faces) != len(target.faces): - print '\ttarget "%s" facelen does not match "%s".' % (target.name, source_me.name) - error = True - fail_count +=1 - else: - # slow but worth comparing - if source_face_key != face_key(target): - print '\t\terror, face len dosnt match for ob "%s" next mesh...' % target.name - error = True - fail_count +=1 - else: - target_faces = target.faces - - # Add uvs if there not there - target.faceUV = True - - for i, f_source in enumerate(source_faces): - target_faces[i].uv = f_source.uv - - target.update() - - msg = 'Copied UVs to %d of %d mesh(s)' % (len(target_mes)-fail_count, len(target_mes)) - - if error: - msg += "|Could not copy some UV's, see console." - - Blender.Draw.PupMenu('UV Copy Finished%t|' + msg) - -if __name__ == '__main__': - main()
\ No newline at end of file diff --git a/release/scripts/vertexpaint_from_material.py b/release/scripts/vertexpaint_from_material.py deleted file mode 100644 index 9668c521f3a..00000000000 --- a/release/scripts/vertexpaint_from_material.py +++ /dev/null @@ -1,99 +0,0 @@ -#!BPY -""" -Name: 'Copy from Material...' -Blender: 242 -Group: 'VertexPaint' -Tooltip: 'Writes material diffuse color as vertex colors.' -""" - -__author__ = "Campbell Barton" -__url__ = ("www.blender.org", "blenderartists.org") -__version__ = "1.0" - -__bpydoc__ = """\ -This script copies material colors to vertex colors. -Optionaly you can operate on all faces and many objects as well as multiplying with the current color. -""" - - -from Blender import * - -def matcol(mat): - ''' - Returns the material color as a tuple 3 from 0 to 255 - ''' - if mat: - return \ - int(mat.R*255),\ - int(mat.G*255),\ - int(mat.B*255) - else: - return None - -def mat2vcol(PREF_SEL_FACES_ONLY, PREF_ACTOB_ONLY, PREF_MULTIPLY_COLOR): - scn= Scene.GetCurrent() - if PREF_ACTOB_ONLY: - obs= [scn.getActiveObject()] - else: - obs= Object.GetSelected() - ob= scn.getActiveObject() - if ob not in obs: - obs.append(ob) - - - for ob in obs: - if ob.type != 'Mesh': - continue - - me= ob.getData(mesh=1) - - try: - me.vertexColors=True - except: # no faces - continue - - matcols= [matcol(mat) for mat in me.materials] - len_matcols= len(matcols) - - for f in me.faces: - if not PREF_SEL_FACES_ONLY or f.sel: - f_mat= f.mat - if f_mat < len_matcols: - mat= matcols[f.mat] - if mat: - if PREF_MULTIPLY_COLOR: - for c in f.col: - c.r= int(((c.r/255.0) * (mat[0]/255.0)) * 255.0) - c.g= int(((c.g/255.0) * (mat[1]/255.0)) * 255.0) - c.b= int(((c.b/255.0) * (mat[2]/255.0)) * 255.0) - else: - for c in f.col: - c.r=mat[0] - c.g=mat[1] - c.b=mat[2] - me.update() - -def main(): - # Create the variables. - - PREF_SEL_FACES_ONLY= Draw.Create(1) - PREF_ACTOB_ONLY= Draw.Create(1) - PREF_MULTIPLY_COLOR = Draw.Create(0) - - pup_block = [\ - ('Sel Faces Only', PREF_SEL_FACES_ONLY, 'Only apply to selected faces.'),\ - ('Active Only', PREF_ACTOB_ONLY, 'Operate on all selected objects.'),\ - ('Multiply Existing', PREF_MULTIPLY_COLOR, 'Multiplies material color with existing.'),\ - ] - - if not Draw.PupBlock('VCols from Material', pup_block): - return - - PREF_SEL_FACES_ONLY= PREF_SEL_FACES_ONLY.val - PREF_ACTOB_ONLY= PREF_ACTOB_ONLY.val - PREF_MULTIPLY_COLOR= PREF_MULTIPLY_COLOR.val - - mat2vcol(PREF_SEL_FACES_ONLY, PREF_ACTOB_ONLY, PREF_MULTIPLY_COLOR) - -if __name__=='__main__': - main()
\ No newline at end of file diff --git a/release/scripts/vertexpaint_gradient.py b/release/scripts/vertexpaint_gradient.py deleted file mode 100644 index 17eccb4f67f..00000000000 --- a/release/scripts/vertexpaint_gradient.py +++ /dev/null @@ -1,46 +0,0 @@ -#!BPY -""" -Name: 'VCol Gradient...' -Blender: 245 -Group: 'VertexPaint' -Tooltip: 'Click on the start and end grad points for the mesh for selected faces.' -""" - -__author__ = "Campbell Barton aka ideasman42" -__url__ = ["www.blender.org", "blenderartists.org", "www.python.org"] -__version__ = "0.1" - -# ***** 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 ***** - -import mesh_gradient -import Blender - -def main(): - scn= Blender.Scene.GetCurrent() - ob= scn.getActiveObject() - - if not ob or ob.getType() != 'Mesh': - Blender.Draw.PupMenu('Error, no active mesh object, aborting.') - return - - mesh_gradient.vertexGradientPick(ob, 1) - - -if __name__ == '__main__': - main() diff --git a/release/scripts/vertexpaint_selfshadow_ao.py b/release/scripts/vertexpaint_selfshadow_ao.py deleted file mode 100644 index 3554e016f79..00000000000 --- a/release/scripts/vertexpaint_selfshadow_ao.py +++ /dev/null @@ -1,186 +0,0 @@ -#!BPY -""" -Name: 'Self Shadow VCols (AO)...' -Blender: 245 -Group: 'VertexPaint' -Tooltip: 'Generate Fake Ambient Occlusion with vertex colors.' -""" - -__author__ = "Campbell Barton aka ideasman42" -__url__ = ["www.blender.org", "blenderartists.org", "www.python.org"] -__version__ = "0.1" -__bpydoc__ = """\ - -Self Shadow - -This usript uses the angles between faces to shade the mesh, -and optionaly blur the shading to remove artifacts from spesific edges. -""" - -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Script copyright (C) Campbell J Barton -# -# 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 ***** -# -------------------------------------------------------------------------- - -from Blender import Scene, Draw, sys, Window, Mathutils, Mesh -import bpy -import BPyMesh - - -def vertexFakeAO(me, PREF_BLUR_ITERATIONS, PREF_BLUR_STRENGTH, PREF_CLAMP_CONCAVE, PREF_CLAMP_CONVEX, PREF_SHADOW_ONLY, PREF_SEL_ONLY): - Window.WaitCursor(1) - Ang= Mathutils.AngleBetweenVecs - - BPyMesh.meshCalcNormals(me) - - vert_tone= [0.0] * len(me.verts) - vert_tone_count= [0] * len(me.verts) - - min_tone=0 - max_tone=0 - - for i, f in enumerate(me.faces): - fc= f.cent - fno = f.no - - for v in f.v: - vno=v.no # get a scaled down normal. - - dot= vno.dot(v.co) - vno.dot(fc) - vert_tone_count[v.index]+=1 - try: - a= Ang(vno, fno) - except: - continue - - # Convex - if dot>0: - a= min(PREF_CLAMP_CONVEX, a) - if not PREF_SHADOW_ONLY: - vert_tone[v.index] += a - else: - a= min(PREF_CLAMP_CONCAVE, a) - vert_tone[v.index] -= a - - # average vert_tone_list into vert_tonef - for i, tones in enumerate(vert_tone): - if vert_tone_count[i]: - vert_tone[i] = vert_tone[i] / vert_tone_count[i] - - - # Below we use edges to blur along so the edges need counting, not the faces - vert_tone_count= [0] * len(me.verts) - for ed in me.edges: - vert_tone_count[ed.v1.index] += 1 - vert_tone_count[ed.v2.index] += 1 - - - # Blur tone - blur = PREF_BLUR_STRENGTH - blur_inv = 1.0 - PREF_BLUR_STRENGTH - - for i in xrange(PREF_BLUR_ITERATIONS): - - # backup the original tones - orig_vert_tone= list(vert_tone) - - for ed in me.edges: - - i1= ed.v1.index - i2= ed.v2.index - - val1= (orig_vert_tone[i2]*blur) + (orig_vert_tone[i1]*blur_inv) - val2= (orig_vert_tone[i1]*blur) + (orig_vert_tone[i2]*blur_inv) - - # Apply the ton divided by the number of faces connected - vert_tone[i1]+= val1 / max(vert_tone_count[i1], 1) - vert_tone[i2]+= val2 / max(vert_tone_count[i2], 1) - - - min_tone= min(vert_tone) - max_tone= max(vert_tone) - - #print min_tone, max_tone - - tone_range= max_tone-min_tone - if max_tone==min_tone: - return - - for f in me.faces: - if not PREF_SEL_ONLY or f.sel: - f_col= f.col - for i, v in enumerate(f): - col= f_col[i] - tone= vert_tone[v.index] - tone= (tone-min_tone)/tone_range - - col.r= int(tone*col.r) - col.g= int(tone*col.g) - col.b= int(tone*col.b) - - Window.WaitCursor(0) - -def main(): - sce= bpy.data.scenes.active - ob= sce.objects.active - - if not ob or ob.type != 'Mesh': - Draw.PupMenu('Error, no active mesh object, aborting.') - return - - me= ob.getData(mesh=1) - - PREF_BLUR_ITERATIONS= Draw.Create(1) - PREF_BLUR_STRENGTH= Draw.Create(0.5) - PREF_CLAMP_CONCAVE= Draw.Create(90) - PREF_CLAMP_CONVEX= Draw.Create(20) - PREF_SHADOW_ONLY= Draw.Create(0) - PREF_SEL_ONLY= Draw.Create(0) - pup_block= [\ - 'Post AO Blur',\ - ('Strength:', PREF_BLUR_STRENGTH, 0, 1, 'Blur strength per iteration'),\ - ('Iterations:', PREF_BLUR_ITERATIONS, 0, 40, 'Number times to blur the colors. (higher blurs more)'),\ - 'Angle Clipping',\ - ('Highlight Angle:', PREF_CLAMP_CONVEX, 0, 180, 'Less then 180 limits the angle used in the tonal range.'),\ - ('Shadow Angle:', PREF_CLAMP_CONCAVE, 0, 180, 'Less then 180 limits the angle used in the tonal range.'),\ - ('Shadow Only', PREF_SHADOW_ONLY, 'Dont calculate highlights for convex areas.'),\ - ('Sel Faces Only', PREF_SEL_ONLY, 'Only apply to UV/Face selected faces (mix vpain/uvface select).'),\ - ] - - if not Draw.PupBlock('SelfShadow...', pup_block): - return - - if not me.vertexColors: - me.vertexColors= 1 - - t= sys.time() - vertexFakeAO(me, PREF_BLUR_ITERATIONS.val, \ - PREF_BLUR_STRENGTH.val, \ - PREF_CLAMP_CONCAVE.val, \ - PREF_CLAMP_CONVEX.val, \ - PREF_SHADOW_ONLY.val, \ - PREF_SEL_ONLY.val) - - if ob.modifiers: - me.update() - - print 'done in %.6f' % (sys.time()-t) -if __name__=='__main__': - main() - diff --git a/release/scripts/vrml97_export.py b/release/scripts/vrml97_export.py deleted file mode 100644 index bd1a35f7c3b..00000000000 --- a/release/scripts/vrml97_export.py +++ /dev/null @@ -1,1300 +0,0 @@ -#!BPY -""" Registration info for Blender menus: -Name: 'VRML97 (.wrl)...' -Blender: 241 -Group: 'Export' -Tooltip: 'Export to VRML97 file (.wrl)' -""" - -__author__ = ("Rick Kimball", "Ken Miller", "Steve Matthews", "Bart") -__url__ = ["blender", "blenderartists.org", -"Author's (Rick) homepage, http://kimballsoftware.com/blender", -"Author's (Bart) homepage, http://www.neeneenee.de/vrml"] -__email__ = ["Bart, bart:neeneenee*de"] -__version__ = "2006/01/17" -__bpydoc__ = """\ -This script exports to VRML97 format. - -Usage: - -Run this script from "File->Export" menu. A pop-up will ask whether you -want to export only selected or all relevant objects. -""" - - -# $Id$ -# -#------------------------------------------------------------------------ -# VRML97 exporter for blender 2.36 or above -# -# ***** 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 ***** -# - -#################################### -# Library dependancies -#################################### - -import Blender -from Blender import Object, Mesh, Lamp, Draw, BGL, \ - Image, Text, sys, Mathutils, Registry -from Blender.Scene import Render - -import math - -#################################### -# Global Variables -#################################### - -scene = Blender.Scene.getCurrent() -world = Blender.World.GetCurrent() -worldmat = Blender.Texture.Get() -filename = Blender.Get('filename') -_safeOverwrite = True -extension = '' - -# Matrices below are used only when export_rotate_z_to_y.val: -# -# Blender is Z up, VRML is Y up, both are right hand coordinate -# systems, so to go from Blender coords to VRML coords we rotate -# by 90 degrees around the X axis. In matrix notation, we have a -# matrix, and it's inverse, as: -M_blen2vrml = Mathutils.Matrix([1,0,0,0], \ - [0,0,1,0], \ - [0,-1,0,0], \ - [0,0,0,1]) -M_vrml2blen = Mathutils.Matrix([1,0,0,0], \ - [0,0,-1,0], \ - [0,1,0,0], \ - [0,0,0,1]) - - -class DrawTypes: - """Object DrawTypes enum values - BOUNDS - draw only the bounding box of the object - WIRE - draw object as a wire frame - SOLID - draw object with flat shading - SHADED - draw object with OpenGL shading -""" - BOUNDBOX = 1 - WIRE = 2 - SOLID = 3 - SHADED = 4 - TEXTURE = 5 - -if not hasattr(Blender.Object,'DrawTypes'): - Blender.Object.DrawTypes = DrawTypes() - -########################################################## -# Functions for writing output file -########################################################## - -class VRML2Export: - - def __init__(self, filename): - #--- public you can change these --- - self.wire = 0 - self.proto = 1 - self.facecolors = 0 - self.vcolors = 0 - self.billnode = 0 - self.halonode = 0 - self.collnode = 0 - self.tilenode = 0 - self.wire = 0 - self.twosided = 0 - - # level of verbosity in console 0-none, 1-some, 2-most - try: - rt = Blender.Get('rt') - if (rt == 42): - self.verbose = 1 - elif (rt == 43): - self.verbose = 2 - else: - self.verbose = 0 - except: - self.verbose = 0 - - # decimals for material color values 0.000 - 1.000 - self.cp=7 - # decimals for vertex coordinate values 0.000 - n.000 - self.vp=7 - # decimals for texture coordinate values 0.000 - 1.000 - self.tp=7 - - #--- class private don't touch --- - self.texNames={} # dictionary of textureNames - self.matNames={} # dictionary of materialNames - self.meshNames={} # dictionary of meshNames - self.coordNames={} # dictionary of coordNames - self.indentLevel=0 # keeps track of current indenting - self.filename=filename - self.file = open(filename, "w") - self.bNav=0 - self.nodeID=0 - self.namesReserved=[ "Anchor", "Appearance", "AudioClip", - "Background","Billboard", "Box", - "Collision", "Color", "ColorInterpolator", - "Cone", "Coordinate", - "CoordinateInterpolator", "Cylinder", - "CylinderSensor", - "DirectionalLight", - "ElevationGrid", "Extrustion", - "Fog", "FontStyle", "Group", - "ImageTexture", "IndexedFaceSet", - "IndexedLineSet", "Inline", - "LOD", "Material", "MovieTexture", - "NavigationInfo", "Normal", - "NormalInterpolator", - "OrientationInterpolator", "PixelTexture", - "PlaneSensor", "PointLight", "PointSet", - "PositionInterpolator", "ProxmimitySensor", - "ScalarInterpolator", "Script", "Shape", - "Sound", "Sphere", "SphereSensor", - "SpotLight", "Switch", "Text", - "TextureCoordinate", "TextureTransform", - "TimeSensor", "TouchSensor", "Transform", - "Viewpoint", "VisibilitySensor", "WorldInfo" ] - self.namesStandard=[ "Empty", "Empty.000", "Empty.001", - "Empty.002", "Empty.003", "Empty.004", - "Empty.005", "Empty.006", "Empty.007", - "Empty.008", "Empty.009", "Empty.010", - "Empty.011", "Empty.012", - "Scene.001", "Scene.002", "Scene.003", - "Scene.004", "Scene.005", "Scene.06", - "Scene.013", "Scene.006", "Scene.007", - "Scene.008", "Scene.009", "Scene.010", - "Scene.011","Scene.012", - "World", "World.000", "World.001", - "World.002", "World.003", "World.004", - "World.005" ] - self.namesFog=[ "", "LINEAR"," EXPONENTIAL", "" ] - -########################################################## -# Writing nodes routines -########################################################## - - def writeHeader(self): - bfile = sys.expandpath(Blender.Get('filename')) - self.file.write("#VRML V2.0 utf8\n\n") - self.file.write("# This file was authored with Blender " \ - "(http://www.blender.org/)\n") - self.file.write("# Blender version %s\n" % Blender.Get('version')) - self.file.write("# Blender file %s\n" % sys.basename(bfile)) - self.file.write("# Exported using VRML97 exporter " \ - "v1.55 (2006/01/17)\n\n") - - def writeInline(self): - inlines = Blender.Scene.Get() - allinlines = len(inlines) - if scene != inlines[0]: - return - else: - for i in xrange(allinlines): - nameinline=inlines[i].getName() - if (nameinline not in self.namesStandard) and (i > 0): - self.writeIndented("DEF %s Inline {\n" % \ - (self.cleanStr(nameinline)), 1) - nameinline = nameinline+".wrl" - self.writeIndented("url \"%s\" \n" % nameinline) - self.writeIndented("}\n", -1) - self.writeIndented("\n") - - def writeScript(self): - textEditor = Blender.Text.Get() - alltext = len(textEditor) - for i in xrange(alltext): - nametext = textEditor[i].getName() - nlines = textEditor[i].getNLines() - if (self.proto == 1): - if (nametext == "proto" or nametext == "proto.js" or \ - nametext == "proto.txt") and (nlines != None): - nalllines = len(textEditor[i].asLines()) - alllines = textEditor[i].asLines() - for j in xrange(nalllines): - self.writeIndented(alllines[j] + "\n") - elif (self.proto == 0): - if (nametext == "route" or nametext == "route.js" or \ - nametext == "route.txt") and (nlines != None): - nalllines = len(textEditor[i].asLines()) - alllines = textEditor[i].asLines() - for j in xrange(nalllines): - self.writeIndented(alllines[j] + "\n") - self.writeIndented("\n") - - def writeViewpoint(self, thisObj): - # NOTE: The transform node above this will take care of - # the position and orientation of the camera - context = scene.getRenderingContext() - ratio = float(context.imageSizeY()) / float(context.imageSizeX()) - temp = ratio * 16 / thisObj.data.getLens() - lens = 2 * math.atan(temp) - lens = min(lens, math.pi) - - self.writeIndented("DEF %s Viewpoint {\n" % \ - (self.cleanStr(thisObj.name)), 1) - self.writeIndented('description "%s" \n' % thisObj.name) - self.writeIndented("position 0.0 0.0 0.0\n") - # Need camera to point to -y in local space to accomodate - # the transforma node above - self.writeIndented("orientation 1.0 0.0 0.0 %f\n" % (-math.pi/2.0)) - self.writeIndented("fieldOfView %.3f\n" % (lens)) - self.writeIndented("}\n", -1) - self.writeIndented("\n") - - def writeFog(self): - if world: - mtype = world.getMistype() - mparam = world.getMist() - grd = world.getHor() - grd0, grd1, grd2 = grd[0], grd[1], grd[2] - else: - return - if (mtype == 1 or mtype == 2): - self.writeIndented("Fog {\n",1) - self.writeIndented('fogType "%s"\n' % self.namesFog[mtype]) - self.writeIndented("color %s %s %s\n" % \ - (round(grd0,self.cp), \ - round(grd1,self.cp), \ - round(grd2,self.cp))) - self.writeIndented("visibilityRange %s\n" % \ - round(mparam[2],self.cp)) - self.writeIndented("}\n",-1) - self.writeIndented("\n") - else: - return - - def writeNavigationInfo(self, scene): - allObj = [] - allObj = list(scene.objects) - headlight = "TRUE" - vislimit = 0.0 - for thisObj in allObj: - objType=thisObj.type - if objType == "Camera": - vislimit = thisObj.data.getClipEnd() - elif objType == "Lamp": - headlight = "FALSE" - self.writeIndented("NavigationInfo {\n",1) - self.writeIndented("headlight %s\n" % headlight) - self.writeIndented("visibilityLimit %s\n" % \ - (round(vislimit,self.cp))) - self.writeIndented("type [\"EXAMINE\", \"ANY\"]\n") - self.writeIndented("avatarSize [0.25, 1.75, 0.75]\n") - self.writeIndented("} \n",-1) - self.writeIndented(" \n") - - def writeSpotLight(self, object, lamp): - # Note: location and orientation are handled by the - # transform node above this object - if world: - ambi = world.getAmb() - ambientIntensity = ((float(ambi[0] + ambi[1] + ambi[2]))/3)/2.5 - else: - ambi = 0 - ambientIntensity = 0 - - # compute cutoff and beamwidth - intensity=min(lamp.energy/1.75,1.0) - beamWidth=((lamp.spotSize*math.pi)/180.0)*.37; - cutOffAngle=beamWidth*1.3 - - radius = lamp.dist*math.cos(beamWidth) - self.writeIndented("DEF %s SpotLight {\n" % \ - self.cleanStr(object.name),1) - self.writeIndented("radius %s\n" % (round(radius,self.cp))) - self.writeIndented("ambientIntensity %s\n" % \ - (round(ambientIntensity,self.cp))) - self.writeIndented("intensity %s\n" % (round(intensity,self.cp))) - self.writeIndented("color %s %s %s\n" % \ - (round(lamp.col[0],self.cp), \ - round(lamp.col[1],self.cp), \ - round(lamp.col[2],self.cp))) - self.writeIndented("beamWidth %s\n" % (round(beamWidth,self.cp))) - self.writeIndented("cutOffAngle %s\n" % \ - (round(cutOffAngle,self.cp))) - # Note: point down -Y axis, transform node above will rotate - self.writeIndented("direction 0.0 -1.0 0.0\n") - self.writeIndented("location 0.0 0.0 0.0\n") - self.writeIndented("}\n",-1) - self.writeIndented("\n") - - def writeDirectionalLight(self, object, lamp): - # Note: location and orientation are handled by the - # transform node above this object - if world: - ambi = world.getAmb() - ambientIntensity = ((float(ambi[0] + ambi[1] + ambi[2]))/3)/2.5 - else: - ambi = 0 - ambientIntensity = 0 - - intensity=min(lamp.energy/1.75,1.0) - self.writeIndented("DEF %s DirectionalLight {\n" % \ - self.cleanStr(object.name),1) - self.writeIndented("ambientIntensity %s\n" % \ - (round(ambientIntensity,self.cp))) - self.writeIndented("color %s %s %s\n" % \ - (round(lamp.col[0],self.cp), \ - round(lamp.col[1],self.cp), \ - round(lamp.col[2],self.cp))) - self.writeIndented("intensity %s\n" % \ - (round(intensity,self.cp))) - # Note: point down -Y axis, transform node above will rotate - self.writeIndented("direction 0.0 -1.0 0.0\n") - self.writeIndented("}\n",-1) - self.writeIndented("\n") - - def writePointLight(self, object, lamp): - # Note: location is at origin because parent transform node - # takes care of this - if world: - ambi = world.getAmb() - ambientIntensity = ((float(ambi[0] + ambi[1] + ambi[2]))/3)/2.5 - else: - ambi = 0 - ambientIntensity = 0 - om = object.getMatrix() - intensity=min(lamp.energy/1.75,1.0) - radius = lamp.dist - self.writeIndented("DEF %s PointLight {\n" % \ - self.cleanStr(object.name),1) - self.writeIndented("ambientIntensity %s\n" % \ - (round(ambientIntensity,self.cp))) - self.writeIndented("color %s %s %s\n" % \ - (round(lamp.col[0],self.cp), \ - round(lamp.col[1],self.cp), \ - round(lamp.col[2],self.cp))) - self.writeIndented("intensity %s\n" % (round(intensity,self.cp))) - self.writeIndented("location 0.0 0.0 0.0\n") - self.writeIndented("radius %s\n" % radius ) - self.writeIndented("}\n",-1) - self.writeIndented("\n") - - def writeNode(self, thisObj): - # Note: location and orientation are handled by the - # transform node above this object - objectname=str(thisObj.getName()) - if objectname in self.namesStandard: - return - else: - self.writeIndented("%s {\n" % objectname,1) - # May need to check that the direction is done right - self.writeIndented("direction 0.0 -1.0 0.0\n") - self.writeIndented("location 0.0 0.0 0.0\n") - self.writeIndented("}\n",-1) - self.writeIndented("\n") - - def secureName(self, name): - name = name + str(self.nodeID) - self.nodeID += 1 - if len(name) <= 3: - newname = "_" + str(self.nodeID) - return "%s" % (newname) - else: - for bad in ['"','#',"'",',','.','[','\\',']','{','}']: - name=name.replace(bad,'_') - if name in self.namesReserved: - newname = name[0:3] + "_" + str(self.nodeID) - return "%s" % (newname) - elif name[0].isdigit(): - newname = "_" + name + str(self.nodeID) - return "%s" % (newname) - else: - newname = name - return "%s" % (newname) - - def classifyMesh(self, me, ob): - self.halonode = 0 - self.billnode = 0 - self.facecolors = 0 - self.vcolors = 0 - self.tilenode = 0 - self.colnode = 0 - self.wire = 0 - if me.faceUV: - for face in me.faces: - if (face.mode & Mesh.FaceModes['HALO']): - self.halonode = 1 - if (face.mode & Mesh.FaceModes['BILLBOARD']): - self.billnode = 1 - if (face.mode & Mesh.FaceModes['OBCOL']): - self.facecolors = 1 - if (face.mode & Mesh.FaceModes['SHAREDCOL']): - self.vcolors = 1 - if (face.mode & Mesh.FaceModes['TILES']): - self.tilenode = 1 - if not (face.mode & Mesh.FaceModes['DYNAMIC']): - self.collnode = 1 - if (face.mode & Mesh.FaceModes['TWOSIDE']): - self.twosided = 1 - - # Bit of a crufty trick, but if mesh has vertex colors - # (as a non-face property) and if first material has - # vcol paint set, we export the vertex colors - if (me.vertexColors): - if len(me.materials) > 0: - mat = me.materials[0] - if mat: - if (mat.mode & Blender.Material.Modes['VCOL_PAINT']): - self.vcolors = 1 - else: - self.vcolors = 0 - - # check if object is wireframe only - if ob.drawType == Blender.Object.DrawTypes.WIRE: - # user selected WIRE=2 on the Drawtype=Wire on (F9) Edit page - self.wire = 1 - - ### - ### The next few functions nest Collision/Billboard/Halo nodes. - ### For real mesh data export, jump down to writeMeshData() - ### - def writeMesh(self, ob, normals = 0): - - imageMap={} # set of used images - sided={} # 'one':cnt , 'two':cnt - vColors={} # 'multi':1 - - if (len(ob.modifiers) > 0): - me = Mesh.New() - me.getFromObject(ob.name) - # Careful with the name, the temporary mesh may - # reuse the default name for other meshes. So we - # pick our own name. - me.name = "MOD_%s" % (ob.name) - else: - me = ob.getData(mesh = 1) - - self.classifyMesh(me, ob) - - if (self.collnode): - self.writeCollisionMesh(me, ob, normals) - return - else: - self.writeRegularMesh(me, ob, normals) - return - - def writeCollisionMesh(self, me, ob, normals = 0): - self.writeIndented("Collision {\n",1) - self.writeIndented("collide FALSE\n") - self.writeIndented("children [\n") - - self.writeRegularMesh(me, ob, normals) - - self.writeIndented("]\n", -1) - self.writeIndented("}\n", -1) - - def writeRegularMesh(self, me, ob, normals = 0): - if (self.billnode): - self.writeBillboardMesh(me, ob, normals) - elif (self.halonode): - self.writeHaloMesh(me, ob, normals) - else: - self.writeMeshData(me, ob, normals) - - def writeBillboardMesh(self, me, ob, normals = 0): - self.writeIndented("Billboard {\n",1) - self.writeIndented("axisOfRotation 0 1 0\n") - self.writeIndented("children [\n") - - self.writeMeshData(me, ob, normals) - - self.writeIndented("]\n", -1) - self.writeIndented("}\n", -1) - - def writeHaloMesh(self, me, ob, normals = 0): - self.writeIndented("Billboard {\n",1) - self.writeIndented("axisOfRotation 0 0 0\n") - self.writeIndented("children [\n") - - self.writeMeshData(me, ob, normals) - - self.writeIndented("]\n", -1) - self.writeIndented("}\n", -1) - - ### - ### Here is where real mesh data is written - ### - def writeMeshData(self, me, ob, normals = 0): - meshName = self.cleanStr(me.name) - - if self.meshNames.has_key(meshName): - self.writeIndented("USE ME_%s\n" % meshName, 0) - self.meshNames[meshName]+=1 - if (self.verbose == 1): - print " Using Mesh %s (Blender mesh: %s)\n" % \ - (meshName, me.name) - return - self.meshNames[meshName]=1 - - if (self.verbose == 1): - print " Writing Mesh %s (Blender mesh: %s)\n" % \ - (meshName, me.name) - return - - self.writeIndented("DEF ME_%s Group {\n" % meshName,1) - self.writeIndented("children [\n", 1) - - hasImageTexture = 0 - issmooth = 0 - - maters = me.materials - nummats = len(me.materials) - - # Vertex and Face colors trump materials and image textures - if (self.facecolors or self.vcolors): - if nummats > 0: - self.writeShape(ob, me, 0, None) - else: - self.writeShape(ob, me, -1, None) - - # Do meshes with materials, possibly with image textures - elif nummats > 0: - for matnum in xrange(len(maters)): - images = [] - if me.faceUV: - images = self.getImages(me, matnum) - if len(images) > 0: - for image in images: - self.writeShape(ob, me, matnum, image) - else: - self.writeShape(ob, me, matnum, None) - else: - self.writeShape(ob, me, matnum, None) - else: - if me.faceUV: - images = self.getImages(me, -1) - if len(images) > 0: - for image in images: - self.writeShape(ob, me, -1, image) - else: - self.writeShape(ob, me, -1, None) - else: - self.writeShape(ob, me, -1, None) - - - self.writeIndented("]\n", -1) - self.writeIndented("}\n", -1) - - def getImages(self, me, matnum): - imageNames = {} - images = [] - for face in me.faces: - if (matnum == -1) or (face.mat == matnum): - if (face.image): - imName = self.cleanStr(face.image.name) - if not imageNames.has_key(imName): - images.append(face.image) - imageNames[imName]=1 - return images - - def writeCoordinates(self, me, meshName): - coordName = "coord_%s" % (meshName) - # look up coord name, use it if available - if self.coordNames.has_key(coordName): - self.writeIndented("coord USE %s\n" % coordName, 0) - self.coordNames[coordName]+=1 - return; - - self.coordNames[coordName]=1 - - #-- vertices - self.writeIndented("coord DEF %s Coordinate {\n" % (coordName), 1) - self.writeIndented("point [\n", 1) - meshVertexList = me.verts - - for vertex in meshVertexList: - vrmlvert = blenvert = Mathutils.Vector(vertex.co) - if export_rotate_z_to_y.val: - vrmlvert = M_blen2vrml * vrmlvert - self.writeUnindented("%s %s %s\n " % \ - (vrmlvert[0], \ - vrmlvert[1], \ - vrmlvert[2])) - self.writeIndented("]\n", -1) - self.writeIndented("}\n", -1) - self.writeIndented("\n") - - def testShape(self, ob, me, matnum, image): - if ( (matnum == -1) and (image == None) ): - if ( len(me.faces) > 0 ): - return True - # Check if any faces the material or image - for face in me.faces: - if (matnum == -1): - if (face.image == image): - return True - elif (image == None): - if (face.mat == matnum): - return True - else: - if ((face.image == image) and (face.mat == matnum)): - return True - - return False - - def writeShape(self, ob, me, matnum, image): - # matnum == -1 means don't check the face.mat - # image == None means don't check face.image - - if ( not self.testShape(ob, me, matnum, image) ): - return False - - self.writeIndented("Shape {\n",1) - - self.writeIndented("appearance Appearance {\n", 1) - if (matnum != -1): - mater = me.materials[matnum] - if (mater): - self.writeMaterial(mater, self.cleanStr(mater.name,'')) - if (mater.mode & Blender.Material.Modes['TEXFACE']): - if image != None: - self.writeImageTexture(image.name, image.filename) - else: - self.writeDefaultMaterial() - else: - if image != None: - self.writeImageTexture(image.name, image.filename) - - self.writeIndented("}\n", -1) - - self.writeGeometry(ob, me, matnum, image) - - self.writeIndented("}\n", -1) - - return True - - def writeGeometry(self, ob, me, matnum, image): - - #-- IndexedFaceSet or IndexedLineSet - meshName = self.cleanStr(me.name) - - # check if object is wireframe only - if (self.wire): - ifStyle="IndexedLineSet" - else: - # user selected BOUNDS=1, SOLID=3, SHARED=4, or TEXTURE=5 - ifStyle="IndexedFaceSet" - - self.writeIndented("geometry %s {\n" % ifStyle, 1) - if not self.wire: - if self.twosided == 1: - self.writeIndented("solid FALSE\n") - else: - self.writeIndented("solid TRUE\n") - - self.writeCoordinates(me, meshName) - self.writeCoordIndex(me, meshName, matnum, image) - self.writeTextureCoordinates(me, meshName, matnum, image) - if self.facecolors: - self.writeFaceColors(me) - elif self.vcolors: - self.writeVertexColors(me) - self.writeIndented("}\n", -1) - - def writeCoordIndex(self, me, meshName, matnum, image): - meshVertexList = me.verts - self.writeIndented("coordIndex [\n", 1) - coordIndexList=[] - for face in me.faces: - if (matnum == -1) or (face.mat == matnum): - if (image == None) or (face.image == image): - cordStr="" - for v in face.verts: - indx=v.index - cordStr = cordStr + "%s " % indx - self.writeUnindented(cordStr + "-1, \n") - self.writeIndented("]\n", -1) - - def writeTextureCoordinates(self, me, meshName, matnum, image): - if (image == None): - return - - texCoordList=[] - texIndexList=[] - j=0 - - for face in me.faces: - coordStr = "" - indexStr = "" - if (matnum == -1) or (face.mat == matnum): - if (face.image == image): - for i in xrange(len(face.verts)): - uv = face.uv[i] - indexStr += "%s " % (j) - coordStr += "%s %s, " % \ - (round(uv[0], self.tp), \ - round(uv[1], self.tp)) - j=j+1 - indexStr += "-1" - texIndexList.append(indexStr) - texCoordList.append(coordStr) - - self.writeIndented("texCoord TextureCoordinate {\n", 1) - self.writeIndented("point [\n", 1) - for coord in texCoordList: - self.writeUnindented("%s\n" % (coord)) - self.writeIndented("]\n", -1) - self.writeIndented("}\n", -1) - - self.writeIndented("texCoordIndex [\n", 1) - for ind in texIndexList: - self.writeUnindented("%s\n" % (ind)) - self.writeIndented("]\n", -1) - - def writeFaceColors(self, me): - self.writeIndented("colorPerVertex FALSE\n") - self.writeIndented("color Color {\n",1) - self.writeIndented("color [\n", 1) - - for face in me.faces: - if face.col: - c=face.col[0] - if self.verbose >= 2: - print "Debug: face.col r=%d g=%d b=%d" % (c.r, c.g, c.b) - - aColor = self.rgbToFS(c) - self.writeUnindented("%s,\n" % aColor) - self.writeIndented("]\n",-1) - self.writeIndented("}\n",-1) - - def writeVertexColors(self, me): - self.writeIndented("colorPerVertex TRUE\n") - self.writeIndented("color Color {\n",1) - self.writeIndented("color [\n\t\t\t\t\t\t", 1) - - cols = [None] * len(me.verts) - - for face in me.faces: - for vind in xrange(len(face.v)): - vertex = face.v[vind] - i = vertex.index - if cols[i] == None: - cols[i] = face.col[vind] - - for i in xrange(len(me.verts)): - aColor = self.rgbToFS(cols[i]) - self.writeUnindented("%s\n" % aColor) - - self.writeIndented("\n", 0) - self.writeIndented("]\n",-1) - self.writeIndented("}\n",-1) - - def writeDefaultMaterial(self): - matName = "default" - - # look up material name, use it if available - if self.matNames.has_key(matName): - self.writeIndented("material USE MA_%s\n" % matName) - self.matNames[matName]+=1 - return; - - self.matNames[matName]=1 - self.writeIndented("material DEF MA_%s Material {\n" % matName, 1) - self.writeIndented("diffuseColor 0.8 0.8 0.8\n") - self.writeIndented("specularColor 1.0 1.0 1.0\n") - self.writeIndented("shininess 0.5\n") - self.writeIndented("transparency 0.0\n") - self.writeIndented("}\n",-1) - - def writeMaterial(self, mat, matName): - # look up material name, use it if available - if self.matNames.has_key(matName): - self.writeIndented("material USE MA_%s\n" % matName) - self.matNames[matName]+=1 - return; - - self.matNames[matName]=1 - - ambient = mat.amb/3 - diffuseR, diffuseG, diffuseB = \ - mat.rgbCol[0], mat.rgbCol[1],mat.rgbCol[2] - if world: - ambi = world.getAmb() - ambi0, ambi1, ambi2 = (ambi[0]*mat.amb) * 2, \ - (ambi[1]*mat.amb) * 2, \ - (ambi[2]*mat.amb) * 2 - else: - ambi0, ambi1, ambi2 = 0, 0, 0 - emisR, emisG, emisB = (diffuseR*mat.emit+ambi0) / 2, \ - (diffuseG*mat.emit+ambi1) / 2, \ - (diffuseB*mat.emit+ambi2) / 2 - - shininess = mat.hard/512.0 - specR = (mat.specCol[0]+0.001) / (1.25/(mat.getSpec()+0.001)) - specG = (mat.specCol[1]+0.001) / (1.25/(mat.getSpec()+0.001)) - specB = (mat.specCol[2]+0.001) / (1.25/(mat.getSpec()+0.001)) - transp = 1 - mat.alpha - matFlags = mat.getMode() - if matFlags & Blender.Material.Modes['SHADELESS']: - ambient = 1 - shine = 1 - specR = emitR = diffuseR - specG = emitG = diffuseG - specB = emitB = diffuseB - self.writeIndented("material DEF MA_%s Material {\n" % matName, 1) - self.writeIndented("diffuseColor %s %s %s\n" % \ - (round(diffuseR,self.cp), \ - round(diffuseG,self.cp), \ - round(diffuseB,self.cp))) - self.writeIndented("ambientIntensity %s\n" % \ - (round(ambient,self.cp))) - self.writeIndented("specularColor %s %s %s\n" % \ - (round(specR,self.cp), \ - round(specG,self.cp), \ - round(specB,self.cp))) - self.writeIndented("emissiveColor %s %s %s\n" % \ - (round(emisR,self.cp), \ - round(emisG,self.cp), \ - round(emisB,self.cp))) - self.writeIndented("shininess %s\n" % (round(shininess,self.cp))) - self.writeIndented("transparency %s\n" % (round(transp,self.cp))) - self.writeIndented("}\n",-1) - - def writeImageTexture(self, name, filename): - if self.texNames.has_key(name): - self.writeIndented("texture USE %s\n" % self.cleanStr(name)) - self.texNames[name] += 1 - return - else: - self.writeIndented("texture DEF %s ImageTexture {\n" % \ - self.cleanStr(name), 1) - self.writeIndented('url "%s"\n' % \ - filename.split("\\")[-1].split("/")[-1]) - self.writeIndented("}\n",-1) - self.texNames[name] = 1 - - def writeBackground(self): - if world: - worldname = world.getName() - else: - return - blending = world.getSkytype() - grd = world.getHor() - grd0, grd1, grd2 = grd[0], grd[1], grd[2] - sky = world.getZen() - sky0, sky1, sky2 = sky[0], sky[1], sky[2] - mix0, mix1, mix2 = grd[0]+sky[0], grd[1]+sky[1], grd[2]+sky[2] - mix0, mix1, mix2 = mix0/2, mix1/2, mix2/2 - if worldname in self.namesStandard: - self.writeIndented("Background {\n",1) - else: - self.writeIndented("DEF %s Background {\n" % \ - self.secureName(worldname),1) - # No Skytype - just Hor color - if blending == 0: - self.writeIndented("groundColor %s %s %s\n" % \ - (round(grd0,self.cp), \ - round(grd1,self.cp), \ - round(grd2,self.cp))) - self.writeIndented("skyColor %s %s %s\n" % \ - (round(grd0,self.cp), \ - round(grd1,self.cp), \ - round(grd2,self.cp))) - # Blend Gradient - elif blending == 1: - self.writeIndented("groundColor [ %s %s %s, " % \ - (round(grd0,self.cp), \ - round(grd1,self.cp), \ - round(grd2,self.cp))) - self.writeIndented("%s %s %s ]\n" % \ - (round(mix0,self.cp), \ - round(mix1,self.cp), \ - round(mix2,self.cp))) - self.writeIndented("groundAngle [ 1.57, 1.57 ]\n") - self.writeIndented("skyColor [ %s %s %s, " % \ - (round(sky0,self.cp), \ - round(sky1,self.cp), \ - round(sky2,self.cp))) - self.writeIndented("%s %s %s ]\n" % \ - (round(mix0,self.cp), \ - round(mix1,self.cp), \ - round(mix2,self.cp))) - self.writeIndented("skyAngle [ 1.57, 1.57 ]\n") - # Blend+Real Gradient Inverse - elif blending == 3: - self.writeIndented("groundColor [ %s %s %s, " % \ - (round(sky0,self.cp), \ - round(sky1,self.cp), \ - round(sky2,self.cp))) - self.writeIndented("%s %s %s ]\n" % \ - (round(mix0,self.cp), \ - round(mix1,self.cp), \ - round(mix2,self.cp))) - self.writeIndented("groundAngle [ 1.57, 1.57 ]\n") - self.writeIndented("skyColor [ %s %s %s, " % \ - (round(grd0,self.cp), \ - round(grd1,self.cp), \ - round(grd2,self.cp))) - self.writeIndented("%s %s %s ]\n" % \ - (round(mix0,self.cp), \ - round(mix1,self.cp), \ - round(mix2,self.cp))) - self.writeIndented("skyAngle [ 1.57, 1.57 ]\n") - # Paper - just Zen Color - elif blending == 4: - self.writeIndented("groundColor %s %s %s\n" % \ - (round(sky0,self.cp), \ - round(sky1,self.cp), \ - round(sky2,self.cp))) - self.writeIndented("skyColor %s %s %s\n" % \ - (round(sky0,self.cp), \ - round(sky1,self.cp), \ - round(sky2,self.cp))) - # Blend+Real+Paper - komplex gradient - elif blending == 7: - self.writeIndented("groundColor [ %s %s %s, " % \ - (round(sky0,self.cp), \ - round(sky1,self.cp), \ - round(sky2,self.cp))) - self.writeIndented("%s %s %s ]\n" % \ - (round(grd0,self.cp), \ - round(grd1,self.cp), \ - round(grd2,self.cp))) - self.writeIndented("groundAngle [ 1.57, 1.57 ]\n") - self.writeIndented("skyColor [ %s %s %s, " % \ - (round(sky0,self.cp), \ - round(sky1,self.cp), \ - round(sky2,self.cp))) - self.writeIndented("%s %s %s ]\n" % \ - (round(grd0,self.cp), - round(grd1,self.cp), - round(grd2,self.cp))) - self.writeIndented("skyAngle [ 1.57, 1.57 ]\n") - # Any Other two colors - else: - self.writeIndented("groundColor %s %s %s\n" % \ - (round(grd0,self.cp), \ - round(grd1,self.cp), \ - round(grd2,self.cp))) - self.writeIndented("skyColor %s %s %s\n" % \ - (round(sky0,self.cp), \ - round(sky1,self.cp), \ - round(sky2,self.cp))) - alltexture = len(worldmat) - for i in xrange(alltexture): - namemat = worldmat[i].getName() - pic = worldmat[i].getImage() - if pic: - # Stripped path. - pic_path= pic.filename.split('\\')[-1].split('/')[-1] - if namemat == "back": - self.writeIndented('backUrl "%s"\n' % pic_path) - elif namemat == "bottom": - self.writeIndented('bottomUrl "%s"\n' % pic_path) - elif namemat == "front": - self.writeIndented('frontUrl "%s"\n' % pic_path) - elif namemat == "left": - self.writeIndented('leftUrl "%s"\n' % pic_path) - elif namemat == "right": - self.writeIndented('rightUrl "%s"\n' % pic_path) - elif namemat == "top": - self.writeIndented('topUrl "%s"\n' % pic_path) - self.writeIndented("}",-1) - self.writeIndented("\n\n") - - def writeLamp(self, ob): - la = ob.data - laType = la.getType() - - if laType == Lamp.Types.Lamp: - self.writePointLight(ob, la) - elif laType == Lamp.Types.Spot: - self.writeSpotLight(ob, la) - elif laType == Lamp.Types.Sun: - self.writeDirectionalLight(ob, la) - else: - self.writeDirectionalLight(ob, la) - - def writeObject(self, ob): - - obname = self.cleanStr(ob.name) - - try: - obtype=ob.getType() - except AttributeError: - print "Error: Unable to get type info for %s" % obname - return - - if self.verbose >= 1: - print "++ Writing %s object %s (Blender name: %s)\n" % \ - (obtype, obname, ob.name) - - # Note: I am leaving empties out for now -- the original - # script does some really weird stuff with empties - if ( (obtype != "Camera") and \ - (obtype != "Mesh") and \ - (obtype != "Lamp") ): - print "Info: Ignoring [%s], object type [%s] " \ - "not handle yet" % (obname, obtype) - return - - ob_matrix = Mathutils.Matrix(ob.getMatrix('worldspace')) - if export_rotate_z_to_y.val: - matrix = M_blen2vrml * ob_matrix * M_vrml2blen - else: - matrix = ob_matrix - e = matrix.rotationPart().toEuler() - - v = matrix.translationPart() - (axis, angle) = self.eulToVecRot(self.deg2rad(e.x), \ - self.deg2rad(e.y), \ - self.deg2rad(e.z)) - - mrot = e.toMatrix().resize4x4() - try: - mrot.invert() - except: - print "Warning: %s has degenerate transformation!" % (obname) - return - - diag = matrix * mrot - sizeX = diag[0][0] - sizeY = diag[1][1] - sizeZ = diag[2][2] - - if self.verbose >= 1: - print " Transformation:\n" \ - " loc: %f %f %f\n" \ - " size: %f %f %f\n" \ - " Rot: (%f %f %f), %f\n" % \ - (v.x, v.y, v.z, \ - sizeX, sizeY, sizeZ, \ - axis[0], axis[1], axis[2], angle) - - self.writeIndented("DEF OB_%s Transform {\n" % (obname), 1) - self.writeIndented("translation %f %f %f\n" % \ - (v.x, v.y, v.z) ) - - self.writeIndented("rotation %f %f %f %f\n" % \ - (axis[0],axis[1],axis[2],angle) ) - - self.writeIndented("scale %f %f %f\n" % \ - (sizeX, sizeY, sizeZ) ) - - self.writeIndented("children [\n", 1) - - self.writeObData(ob) - - self.writeIndented("]\n", -1) # end object - self.writeIndented("}\n", -1) # end object - - def writeObData(self, ob): - - obtype = ob.getType() - - if obtype == "Camera": - self.writeViewpoint(ob) - elif obtype == "Mesh": - self.writeMesh(ob) - elif obtype == "Lamp": - self.writeLamp(ob) - elif obtype == "Empty": - self.writeNode(ob) - - -########################################################## -# export routine -########################################################## - - def export(self, scene, world, worldmat): - print "Info: starting VRML97 export to " + self.filename + "..." - self.writeHeader() - self.writeScript() - self.writeNavigationInfo(scene) - self.writeBackground() - self.writeFog() - self.proto = 0 - allObj = [] - if export_selection_only.val: - allObj = list(scene.objects.context) - else: - allObj = list(scene.objects) - self.writeInline() - - for thisObj in allObj: - self.writeObject(thisObj) - - if not export_selection_only.val: - self.writeScript() - self.cleanup() - -########################################################## -# Utility methods -########################################################## - - def cleanup(self): - self.file.close() - self.texNames={} - self.matNames={} - self.indentLevel=0 - print "Info: finished VRML97 export to %s\n" % self.filename - - def cleanStr(self, name, prefix='rsvd_'): - """cleanStr(name,prefix) - try to create a valid VRML DEF \ - name from object name""" - - newName=name[:] - if len(newName) == 0: - self.nNodeID+=1 - return "%s%d" % (prefix, self.nNodeID) - - if newName in self.namesReserved: - newName='%s%s' % (prefix,newName) - - if newName[0].isdigit(): - newName='%s%s' % ('_',newName) - - for bad in (' ','"','#',"'",',','.','[','\\',']','{','}'): - newName=newName.replace(bad,'_') - return newName - - def rgbToFS(self, c): - s = "%s %s %s" % \ - (round(c.r/255.0,self.cp), \ - round(c.g/255.0,self.cp), \ - round(c.b/255.0,self.cp)) - return s - - def rad2deg(self, v): - return round(v*180.0/math.pi,4) - - def deg2rad(self, v): - return (v*math.pi)/180.0; - - def eulToVecRot(self, RotX, RotY, RotZ): - - ti = RotX*0.5 - tj = RotY*0.5 - th = RotZ*0.5 - - ci = math.cos(ti) - cj = math.cos(tj) - ch = math.cos(th) - si = math.sin(ti) - sj = math.sin(tj) - sh = math.sin(th) - cc = ci*ch - cs = ci*sh - sc = si*ch - ss = si*sh - - q0 = cj*cc + sj*ss - q1 = cj*sc - sj*cs - q2 = cj*ss + sj*cc - q3 = cj*cs - sj*sc - - angle = 2 * math.acos(q0) - if (math.fabs(angle) < 0.000001): - axis = [1.0, 0.0, 0.0] - else: - sphi = 1.0/math.sqrt(1.0 - (q0*q0)) - axis = [q1 * sphi, q2 * sphi, q3 * sphi] - - a = Mathutils.Vector(axis) - a.normalize() - return ([a.x, a.y, a.z], angle) - - - # For writing well formed VRML code - #---------------------------------- - def writeIndented(self, s, inc=0): - if inc < 1: - self.indentLevel = self.indentLevel + inc - - self.file.write( self.indentLevel*"\t" + s) - - if inc > 0: - self.indentLevel = self.indentLevel + inc - - # Sometimes better to not have too many - # tab characters in a long list, for file size - #---------------------------------- - def writeUnindented(self, s): - self.file.write(s) - -########################################################## -# Callbacks, needed before Main -########################################################## - -def select_file(filename): - if sys.exists(filename) and _safeOverwrite: - result = \ - Draw.PupMenu("File Already Exists, Overwrite?%t|Yes%x1|No%x0") - if(result != 1): - return - - if not filename.endswith(extension): - filename += extension - - wrlexport=VRML2Export(filename) - wrlexport.export(scene, world, worldmat) - -######################################################### -# UI and Registry utilities -######################################################### - -export_selection_only = Draw.Create(0) -export_rotate_z_to_y = Draw.Create(1) -export_compressed = Draw.Create(0) - -def save_to_registry(): - d = {} - d['selection_only'] = export_selection_only.val - d['rotate_z_to_y'] = export_rotate_z_to_y.val - d['compressed'] = export_compressed.val - Registry.SetKey('vrml97_export', d, True) - -def load_from_registry(): - d = Registry.GetKey('vrml97_export', True) - if d: - try: - export_selection_only.val = d['selection_only'] - export_rotate_z_to_y.val = d['rotate_z_to_y'] - export_compressed.val = d['compressed'] - except: save_to_registry() # If data is not valid, rewrite it. - -def show_popup(): - pup_block = [ - ('Selection Only', export_selection_only, 'Only export objects in visible selection. Else export whole scene.'), - ('Rotate +Z to +Y', export_rotate_z_to_y, 'Rotate such that +Z axis (Blender up) becomes +Y (VRML up).'), - ('Compress', export_compressed, 'Generate a .wrz file (normal VRML compressed by gzip).') - ] - return Draw.PupBlock('Export VRML 97...', pup_block) - -######################################################### -# main routine -######################################################### - -load_from_registry() - -# Note that show_popup must be done before Blender.Window.FileSelector, -# because export_compressed affects the suggested extension of resulting -# file. - -if show_popup(): - save_to_registry() - if export_compressed.val: - extension=".wrz" - from gzip import * - else: - extension=".wrl" - Blender.Window.FileSelector(select_file, "Export VRML97", \ - sys.makename(ext=extension)) diff --git a/release/scripts/weightpaint_average.py b/release/scripts/weightpaint_average.py deleted file mode 100644 index 4e8830256b2..00000000000 --- a/release/scripts/weightpaint_average.py +++ /dev/null @@ -1,121 +0,0 @@ -#!BPY -""" -Name: 'Vertex Groups Island Average' -Blender: 243 -Group: 'WeightPaint' -Tooltip: 'Average the vertex weights for each connected set of verts' -""" - -# -------------------------------------------------------------------------- -# ***** 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 ***** -# -------------------------------------------------------------------------- -import Blender -from Blender import Scene, Mesh, Window, sys, Draw -from BPyMesh import meshWeight2List, list2MeshWeight, mesh2linkedFaces - -import BPyMessages -import bpy - -def faceGroups2VertSets(face_groups): - ''' Return the face groups as sets of vert indicies ''' - return [set([v.index for f in fg for v in f]) for fg in face_groups] - - -def vgroup_average(ob_orig, me, sce, PREF_ALL_VGROUPS=True): - if not me.getVertGroupNames(): - return - - weight_names, weight_list = meshWeight2List(me) - - weight_names_len = len(weight_names) - vgroup_dummy = [0.0] * weight_names_len - vgroup_range = range(weight_names_len) - - if not PREF_ALL_VGROUPS: - weight_active_index = weight_names.index(me.activeGroup) - - for vert_set in faceGroups2VertSets( mesh2linkedFaces(me) ): - if not vert_set: - continue - - - if PREF_ALL_VGROUPS: - # We need to average the vgroups - collected_group = vgroup_dummy[:] - for i in vert_set: - vert_group = weight_list[i] # get the original weight - weight_list[i] = collected_group # replace with the collected group - - for j in vgroup_range: # iter through the vgroups - collected_group[j] += vert_group[j] - - for j in vgroup_range: - collected_group[j] /= len(vert_set) - else: - # Active group only - vert_weight = 0.0 - for i in vert_set: - vert_weight += weight_list[i][weight_active_index] - - vert_weight /= len(vert_set) - - for i in vert_set: - weight_list[i][weight_active_index] = vert_weight - - list2MeshWeight(me, weight_names, weight_list) - -def main(): - - # Gets the current scene, there can be many scenes in 1 blend file. - sce = bpy.data.scenes.active - - # Get the active object, there can only ever be 1 - # and the active object is always the editmode object. - ob_act = sce.objects.active - - if not ob_act or ob_act.type != 'Mesh': - BPyMessages.Error_NoMeshActive() - return - - # Saves the editmode state and go's out of - # editmode if its enabled, we cant make - # changes to the mesh data while in editmode. - is_editmode = Window.EditMode() - Window.EditMode(0) - - PREF_ALL_VGROUPS = Draw.PupMenu("All Groups?%t|All Groups%x1|Active Group Only%x0") - if PREF_ALL_VGROUPS==-1: - return - - Window.WaitCursor(1) - me = ob_act.getData(mesh=1) # old NMesh api is default - t = sys.time() - - # Run the mesh editing function - vgroup_average(ob_act, me, sce, PREF_ALL_VGROUPS) - - # Timing the script is a good way to be aware on any speed hits when scripting - print 'Average VGroups in %.2f seconds' % (sys.time()-t) - Window.WaitCursor(0) - if is_editmode: Window.EditMode(1) - - -# This lets you can import the script without running it -if __name__ == '__main__': - main()
\ No newline at end of file diff --git a/release/scripts/weightpaint_clean.py b/release/scripts/weightpaint_clean.py deleted file mode 100644 index ca2184bade4..00000000000 --- a/release/scripts/weightpaint_clean.py +++ /dev/null @@ -1,121 +0,0 @@ -#!BPY -""" -Name: 'Clean Weight...' -Blender: 245 -Group: 'WeightPaint' -Tooltip: 'Removed verts from groups below a weight limit.' -""" - -__author__ = "Campbell Barton aka ideasman42" -__url__ = ["www.blender.org", "blenderartists.org", "www.python.org"] -__version__ = "0.1" -__bpydoc__ = """\ - -Clean Weight - -This Script is to be used only in weight paint mode, -It removes very low weighted verts from the current group with a weight option. -""" - -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Script copyright (C) Campbell J Barton -# -# 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 ***** -# -------------------------------------------------------------------------- - -from Blender import Scene, Draw, Object -import BPyMesh -def weightClean(me, PREF_THRESH, PREF_KEEP_SINGLE, PREF_OTHER_GROUPS): - - groupNames, vWeightDict= BPyMesh.meshWeight2Dict(me) - act_group= me.activeGroup - - rem_count = 0 - - if PREF_OTHER_GROUPS: - for wd in vWeightDict: - l = len(wd) - if not PREF_KEEP_SINGLE or l > 1: - # cant use iteritems because the dict is having items removed - for group in wd.keys(): - w= wd[group] - if w <= PREF_THRESH: - # small weight, remove. - del wd[group] - rem_count +=1 - l-=1 - - if PREF_KEEP_SINGLE and l == 1: - break - - else: - for wd in vWeightDict: - if not PREF_KEEP_SINGLE or len(wd) > 1: - try: - w= wd[act_group] - if w <= PREF_THRESH: - # small weight, remove. - del wd[act_group] - rem_count +=1 - except: - pass - - # Copy weights back to the mesh. - BPyMesh.dict2MeshWeight(me, groupNames, vWeightDict) - return rem_count - - -def main(): - scn= Scene.GetCurrent() - ob= scn.objects.active - - if not ob or ob.type != 'Mesh': - Draw.PupMenu('Error, no active mesh object, aborting.') - return - - me= ob.getData(mesh=1) - - PREF_PEAKWEIGHT= Draw.Create(0.001) - PREF_KEEP_SINGLE= Draw.Create(1) - PREF_OTHER_GROUPS= Draw.Create(0) - - pup_block= [\ - ('Peak Weight:', PREF_PEAKWEIGHT, 0.005, 1.0, 'Remove verts from groups below this weight.'),\ - ('All Other Groups', PREF_OTHER_GROUPS, 'Clean all groups, not just the current one.'),\ - ('Keep Single User', PREF_KEEP_SINGLE, 'Keep verts in at least 1 group.'),\ - ] - - if not Draw.PupBlock('Clean Selected Meshes...', pup_block): - return - - rem_count = weightClean(me, PREF_PEAKWEIGHT.val, PREF_KEEP_SINGLE.val, PREF_OTHER_GROUPS.val) - - # Run on entire blend file. usefull sometimes but dont let users do it. - ''' - rem_count = 0 - for ob in Object.Get(): - if ob.type != 'Mesh': - continue - me= ob.getData(mesh=1) - - rem_count += weightClean(me, PREF_PEAKWEIGHT.val, PREF_KEEP_SINGLE.val, PREF_OTHER_GROUPS.val) - ''' - Draw.PupMenu('Removed %i verts from groups' % rem_count) - -if __name__=='__main__': - main() diff --git a/release/scripts/weightpaint_copy.py b/release/scripts/weightpaint_copy.py deleted file mode 100644 index 976bba0ea2c..00000000000 --- a/release/scripts/weightpaint_copy.py +++ /dev/null @@ -1,101 +0,0 @@ -#!BPY -""" -Name: 'Copy Active Group...' -Blender: 243 -Group: 'WeightPaint' -Tooltip: 'Copy the active group to a new one' -""" - -__author__ = ["Campbell Barton"] -__url__ = ("blender.org",) -__version__ = "0.1" -__bpydoc__ = """\ - -Active Group Copy - -This script makes a copy of the active group -""" - -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Script copyright (C) Campbell J Barton -# -# 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 ***** -# -------------------------------------------------------------------------- - -from Blender import Scene, Draw, Window, Mesh -import BPyMesh -SMALL_NUM= 0.000001 -def copy_act_vgroup(me, PREF_NAME, PREF_SEL_ONLY): - Window.WaitCursor(1) - groupNames, vWeightDict= BPyMesh.meshWeight2Dict(me) - act_group= me.activeGroup - - if not PREF_SEL_ONLY: - for wd in vWeightDict: - try: wd[PREF_NAME] = wd[act_group] - except: pass - else: - # Selected faces only - verts = {} # should use set - for f in me.faces: - if f.sel: - for v in f: - verts[v.index] = None - - for i in verts.iterkeys(): - wd = vWeightDict[i] - try: wd[PREF_NAME] = wd[act_group] - except: pass - - - - groupNames.append(PREF_NAME) - # Copy weights back to the mesh. - BPyMesh.dict2MeshWeight(me, groupNames, vWeightDict) - Window.WaitCursor(0) - -def main(): - scn= Scene.GetCurrent() - ob= scn.objects.active - - if not ob or ob.type != 'Mesh': - Draw.PupMenu('Error, no active mesh object, aborting.') - return - - me= ob.getData(mesh=1) - act_group= me.activeGroup - - PREF_NAME= Draw.Create(act_group + '_copy') - PREF_SEL_ONLY = Draw.Create(0) - - pup_block= [\ - ('', PREF_NAME, 0, 31, 'Name of group copy.'),\ - ('Only Selected', PREF_SEL_ONLY, 'Only include selected faces in the new grop.'),\ - ] - - if not Draw.PupBlock('New Name...', pup_block): - return - PREF_NAME = PREF_NAME.val - PREF_SEL_ONLY = PREF_SEL_ONLY.val - copy_act_vgroup(me, PREF_NAME, PREF_SEL_ONLY) - - try: me.activeGroup = PREF_NAME - except: pass - -if __name__=='__main__': - main()
\ No newline at end of file diff --git a/release/scripts/weightpaint_envelope_assign.py b/release/scripts/weightpaint_envelope_assign.py deleted file mode 100644 index cafa44fef38..00000000000 --- a/release/scripts/weightpaint_envelope_assign.py +++ /dev/null @@ -1,240 +0,0 @@ -#!BPY - -""" -Name: 'Envelope via Group Objects' -Blender: 242 -Group: 'WeightPaint' -Tooltip: 'Assigns weights to vertices via object envelopes' -""" - -__author__ = ["Campbell Barton"] -__url__ = ("blender", "blenderartist.org") -__version__ = "0.1" - -# ***** 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 ***** -# -------------------------------------------------------------------------- - -def intersection_data(ob): - ''' - Takes an object and returns raw triangles and tri bounds. - returns a list of (v1,v2,v3, xmin, ymin, xmax, ymax) - ... to be used for ray intersection - ''' - global tot_ymin, tot_xmin, tot_ymax, tot_xmax, tot_zmin, tot_zmax - tot_zmin = tot_ymin = tot_xmin = 100000000.0 - tot_zmax = tot_ymax = tot_xmax = -100000000.0 - - def tribounds_xy(v1,v2,v3): - ''' - return the 3 vecs with bounds, also update tot_*min/max - ''' - global tot_ymin, tot_xmin, tot_ymax, tot_xmax, tot_zmin, tot_zmax - xmin = xmax = v1.x - ymin = ymax = v1.y - - x = v2.x - y = v2.y - if x>xmax: xmax = x - if y>ymax: ymax = y - if x<xmin: xmin = x - if y<ymin: ymin = y - - - x = v3.x - y = v3.y - if x>xmax: xmax = x - if y>ymax: ymax = y - if x<xmin: xmin = x - if y<ymin: ymin = y - - # totbounds - for z in v1.z, v2.z, v3.z: - if z>tot_zmax: tot_zmax = z - if z<tot_zmin: tot_zmin = z - - # maintain global min/max for x and y - if xmax>tot_xmax: tot_xmax = xmax - if xmin<tot_xmin: tot_xmin = xmin - - if ymax>tot_ymax: tot_ymax = ymax - if ymin<tot_ymin: tot_ymin = ymin - - return v1,v2,v3, xmin, ymin, xmax, ymax - - me = BPyMesh.getMeshFromObject(ob) - - if not me: - return [] - - me.transform(ob.matrixWorld) - - mesh_data = [] - - # copy all the vectors so when the mesh is free'd we still have access. - mesh_vert_cos= [v.co.copy() for v in me.verts] - - for f in me.faces: - f_v = [mesh_vert_cos[v.index] for v in f] - mesh_data.append( tribounds_xy(f_v[0], f_v[1], f_v[2]) ) - if len(f) == 4: - mesh_data.append( tribounds_xy(f_v[0], f_v[2], f_v[3]) ) - - me.verts = None # free some memory - - return ob.name, mesh_data, tot_xmin, tot_ymin, tot_zmin, tot_xmax, tot_ymax, tot_zmax - -from Blender import * -ray = Mathutils.Vector(0,0,-1) -def point_in_data(point, mesh_data_tuple): - ob_name, mesh_data, tot_xmin, tot_ymin, tot_zmin, tot_xmax, tot_ymax, tot_zmax = mesh_data_tuple - - Intersect = Mathutils.Intersect - x = point.x - y = point.y - z = point.z - - # Bouds check for all mesh data - if not (\ - tot_zmin < z < tot_zmax and\ - tot_ymin < y < tot_ymax and\ - tot_xmin < x < tot_xmax\ - ): - return False - - def isect(tri_data): - v1,v2,v3, xmin, ymin, xmax, ymax = tri_data - if not (xmin < x < xmax and ymin < y < ymax): - return False - - if v1.z < z and v2.z < z and v3.z < z: - return False - - isect = Intersect(v1, v2,v3, ray, point, 1) # Clipped. - if isect and isect.z > z: # This is so the ray only counts if its above the point. - return True - else: - return False - - # return len([None for tri_data in mesh_data if isect(tri_data)]) % 2 - return len( filter(isect, mesh_data) ) % 2 - -import BPyMesh -def env_from_group(ob_act, grp, PREF_UPDATE_ACT=True): - - me = ob_act.getData(mesh=1) - - if PREF_UPDATE_ACT: - act_group = me.activeGroup - if act_group == None: - Draw.PupMenu('Error%t|No active vertex group.') - return - - try: - ob = Object.Get(act_group) - except: - Draw.PupMenu('Error%t|No object named "'+ act_group +'".') - return - - group_isect = intersection_data(ob) - - else: - - # get intersection data - # group_isect_data = [intersection_data(ob) for ob in group.objects] - group_isect_data = [] - for ob in grp.objects: - if ob != ob_act: # in case we're in the group. - gid = intersection_data(ob) - if gid[1]: # has some triangles? - group_isect_data.append( gid ) - - # we only need 1 for the active group - if PREF_UPDATE_ACT: - break - - # sort by name - group_isect_data.sort() - - if PREF_UPDATE_ACT: - group_names, vweight_list = BPyMesh.meshWeight2List(me) - group_index = group_names.index(act_group) - else: - group_names = [gid[0] for gid in group_isect_data] - vweight_list= [[0.0]* len(group_names) for i in xrange(len(me.verts))] - - - - ob_act_mat = ob_act.matrixWorld - for vi, v in enumerate(me.verts): - # Get all the groups for this vert - co = v.co * ob_act_mat - - if PREF_UPDATE_ACT: - # only update existing - if point_in_data(co, group_isect): w = 1.0 - else: w = 0.0 - vweight_list[vi][group_index] = w - - else: - # generate new vgroup weights. - for group_index, group_isect in enumerate(group_isect_data): - if point_in_data(co, group_isect): - vweight_list[vi][group_index] = 1.0 - - BPyMesh.list2MeshWeight(me, group_names, vweight_list) - -import BPyMessages -def main(): - - scn= Scene.GetCurrent() - ob_act = scn.objects.active - if not ob_act or ob_act.type != 'Mesh': - BPyMessages.Error_NoMeshActive() - return - - PREF_ENV_GROUPNAME= Draw.Create('') - PREF_UPDATE_ACT= Draw.Create(True) - pup_block= [\ - ('Update Active', PREF_UPDATE_ACT, 'Only apply envelope weights to the active group.'),\ - '...or initialize from group',\ - ('GR:', PREF_ENV_GROUPNAME, 0, 21, 'The name of an existing groups, each member will be used as a weight envelope'),\ - ] - - if not Draw.PupBlock('Envelope From Group...', pup_block): - return - - PREF_UPDATE_ACT= PREF_UPDATE_ACT.val - - if not PREF_UPDATE_ACT: - try: - grp = Group.Get(PREF_ENV_GROUPNAME.val) - except: - Draw.PupMenu('Error%t|Group "' + PREF_ENV_GROUPNAME.val + '" does not exist.') - return - else: - grp = None - - Window.WaitCursor(1) - t = sys.time() - env_from_group(ob_act, grp, PREF_UPDATE_ACT) - print 'assigned envelopes in:', sys.time() - t - Window.WaitCursor(0) - -if __name__ == '__main__': - main() diff --git a/release/scripts/weightpaint_gradient.py b/release/scripts/weightpaint_gradient.py deleted file mode 100644 index eb7aff7eb89..00000000000 --- a/release/scripts/weightpaint_gradient.py +++ /dev/null @@ -1,59 +0,0 @@ -#!BPY -""" -Name: 'Weight Gradient...' -Blender: 245 -Group: 'WeightPaint' -Tooltip: 'Click on the start and end grad points for the mesh for selected faces.' -""" - -__author__ = "Campbell Barton aka ideasman42" -__url__ = ["www.blender.org", "blenderartists.org", "www.python.org"] -__version__ = "0.1" -__bpydoc__=\ -''' -This script is used to fill the selected faces with a gradient -To use the script, switch to "Face Select" mode then "Vertex Paint" mode -Select the faces you wish to apply the gradient to. -Click twice on the mesh to set the start and end points of the gradient. -The color under the mouse will be used for the start and end blend colors. -Note: -Holding Shift or clicking outside the mesh on the second click will blend the first colour to nothing. -''' - -# ***** 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 ***** - -import mesh_gradient -import Blender - -def main(): - scn= Blender.Scene.GetCurrent() - ob= scn.objects.active - - if not ob or ob.type != 'Mesh': - Blender.Draw.PupMenu('Error, no active mesh object, aborting.') - return - # MODE 0 == VCOL - # MODE 1 == WEIGHT - MODE= 0 - mesh_gradient.vertexGradientPick(ob, MODE) - - -if __name__ == '__main__': - main() - diff --git a/release/scripts/weightpaint_grow_shrink.py b/release/scripts/weightpaint_grow_shrink.py deleted file mode 100644 index 5c0f28685f9..00000000000 --- a/release/scripts/weightpaint_grow_shrink.py +++ /dev/null @@ -1,131 +0,0 @@ -#!BPY -""" -Name: 'Grow/Shrink Weight...' -Blender: 245 -Group: 'WeightPaint' -Tooltip: 'Grow/Shrink active vertex group.' -""" - -__author__ = "Campbell Barton aka ideasman42" -__url__ = ["www.blender.org", "blenderartists.org", "www.python.org"] -__version__ = "0.1" -__bpydoc__ = """\ - -Grow Shrink Weight - -This Script is to be used only in weight paint mode, -It grows/shrinks the bounds of the weight painted area -""" - -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Script copyright (C) Campbell J Barton -# -# 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 ***** -# -------------------------------------------------------------------------- - -from Blender import Scene, Draw, Window -import BPyMesh -def actWeightNormalize(me, PREF_MODE, PREF_MAX_DIST, PREF_STRENGTH, PREF_ITERATIONS): - Window.WaitCursor(1) - groupNames, vWeightDict= BPyMesh.meshWeight2Dict(me) - act_group= me.activeGroup - - # Start with assumed zero weights - orig_vert_weights= [0.0] * len(vWeightDict) # Will be directly assigned to orig_vert_weights - - - # fill in the zeros with real weights. - for i, wd in enumerate(vWeightDict): - try: - orig_vert_weights[i]= wd[act_group] - except: - pass - - new_vert_weights= list(orig_vert_weights) - - for dummy in xrange(PREF_ITERATIONS): - # Minimize or maximize the weights. connection based. - - if PREF_MODE==0: # Grow - op= max - else: # Shrink - op= min - - for ed in me.edges: - if not PREF_MAX_DIST or ed.length < PREF_MAX_DIST: - - i1= ed.v1.index - i2= ed.v2.index - new_weight= op(orig_vert_weights[i1], orig_vert_weights[i2]) - - if PREF_STRENGTH==1.0: # do a full copy - new_vert_weights[i1]= op(new_weight, new_vert_weights[i1]) - new_vert_weights[i2]= op(new_weight, new_vert_weights[i2]) - - else: # Do a faded copy - new_vert_weights[i1]= op(new_weight, new_vert_weights[i1]) - new_vert_weights[i2]= op(new_weight, new_vert_weights[i2]) - - # Face the copy with the original (orig is updated per iteration) - new_vert_weights[i1]= (new_vert_weights[i1]*PREF_STRENGTH) + (orig_vert_weights[i1]*(1-PREF_STRENGTH)) - new_vert_weights[i2]= (new_vert_weights[i2]*PREF_STRENGTH) + (orig_vert_weights[i2]*(1-PREF_STRENGTH)) - - - for i, wd in enumerate(vWeightDict): - new_weight= new_vert_weights[i] - if new_weight != orig_vert_weights[i]: - wd[act_group]= new_weight - - if dummy+1 != PREF_ITERATIONS: # dont copy the list on the last round. - orig_vert_weights= list(new_vert_weights) - - - # Copy weights back to the mesh. - BPyMesh.dict2MeshWeight(me, groupNames, vWeightDict) - Window.WaitCursor(0) - -def main(): - scn= Scene.GetCurrent() - ob= scn.objects.active - - if not ob or ob.type != 'Mesh': - Draw.PupMenu('Error, no active mesh object, aborting.') - return - - me= ob.getData(mesh=1) - - PREF_MAXDIST= Draw.Create(0.0) - PREF_STRENGTH= Draw.Create(1.0) - PREF_MODE= Draw.Create(0) - PREF_ITERATIONS= Draw.Create(1) - - pup_block= [\ - ('Bleed Dist:', PREF_MAXDIST, 0.0, 1.0, 'Set a distance limit for bleeding.'),\ - ('Bleed Strength:', PREF_STRENGTH, 0.01, 1.0, 'Bleed strength between adjacent verts weight. 1:full, 0:None'),\ - ('Iterations', PREF_ITERATIONS, 1, 20, 'Number of times to run the blending calculation.'),\ - ('Contract (Shrink)', PREF_MODE, 'Shrink instead of growing.'),\ - ] - - if not Draw.PupBlock('Grow/Shrink...', pup_block): - return - - actWeightNormalize(me, PREF_MODE.val, PREF_MAXDIST.val, PREF_STRENGTH.val, PREF_ITERATIONS.val) - - -if __name__=='__main__': - main()
\ No newline at end of file diff --git a/release/scripts/weightpaint_invert.py b/release/scripts/weightpaint_invert.py deleted file mode 100644 index cdae83a9d50..00000000000 --- a/release/scripts/weightpaint_invert.py +++ /dev/null @@ -1,95 +0,0 @@ -#!BPY -""" -Name: 'Invert Active Group' -Blender: 245 -Group: 'WeightPaint' -Tooltip: 'Invert the active vertex group' -""" - -# -------------------------------------------------------------------------- -# ***** 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 ***** -# -------------------------------------------------------------------------- -import Blender -from Blender import Scene, Mesh, Window, sys - -import BPyMessages -import bpy - -def vgroup_invert(ob_orig, me): - if not me.getVertGroupNames(): - return - group_act = me.activeGroup - if group_act == None: - return - - group_data = me.getVertsFromGroup(group_act, 1) - - weights= [1.0] * len(me.verts) # 1.0 - initialize inverted - - group_data = me.getVertsFromGroup(group_act, 1) # (i,w) tuples. - - me.removeVertGroup(group_act) # messes up the active group. - for i,w in group_data: - weights[i] = 1.0-w - - me.addVertGroup(group_act) - - rep = Blender.Mesh.AssignModes.REPLACE - vertList= [None] - for i,weight in enumerate(weights): - vertList[0] = i - me.assignVertsToGroup(group_act, vertList, weight, rep) - - me.activeGroup = group_act - me.update() - -def main(): - - # Gets the current scene, there can be many scenes in 1 blend file. - sce = bpy.data.scenes.active - - # Get the active object, there can only ever be 1 - # and the active object is always the editmode object. - ob_act = sce.objects.active - - if not ob_act or ob_act.type != 'Mesh': - BPyMessages.Error_NoMeshActive() - return - - # Saves the editmode state and go's out of - # editmode if its enabled, we cant make - # changes to the mesh data while in editmode. - is_editmode = Window.EditMode() - Window.EditMode(0) - - Window.WaitCursor(1) - me = ob_act.getData(mesh=1) # old NMesh api is default - t = sys.time() - - # Run the mesh editing function - vgroup_invert(ob_act, me) - - # Timing the script is a good way to be aware on any speed hits when scripting - print 'Invert VGroup in %.2f seconds' % (sys.time()-t) - Window.WaitCursor(0) - if is_editmode: Window.EditMode(1) - -# This lets you can import the script without running it -if __name__ == '__main__': - main()
\ No newline at end of file diff --git a/release/scripts/weightpaint_normalize.py b/release/scripts/weightpaint_normalize.py deleted file mode 100644 index 6059922eecb..00000000000 --- a/release/scripts/weightpaint_normalize.py +++ /dev/null @@ -1,170 +0,0 @@ -#!BPY -""" -Name: 'Normalize/Scale Weight...' -Blender: 245 -Group: 'WeightPaint' -Tooltip: 'Normalize the weight of the active weightgroup.' -""" - -__author__ = "Campbell Barton aka ideasman42" -__url__ = ["www.blender.org", "blenderartists.org", "www.python.org"] -__version__ = "0.1" -__bpydoc__ = """\ - -Normalize Weights - -This Script is to be used only in weight paint mode, -It Normalizes the weights of the current group, to the desired peak -optionaly scaling groups that are shared by these verts so the -proportion of the veighting is unchanged. -""" - -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Script copyright (C) Campbell J Barton -# -# 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 ***** -# -------------------------------------------------------------------------- - -from Blender import Scene, Draw, Object, Modifier -import BPyMesh -SMALL_NUM= 0.000001 - -def getArmatureGroups(ob, me): - - arm_obs = [] - - arm = ob.parent - if arm and arm.type == 'Armature' and ob.parentType == Object.ParentTypes.ARMATURE: - arm_obs.append(arm) - - for m in ob.modifiers: - if m.type== Modifier.Types.ARMATURE: - arm = m[Modifier.Settings.OBJECT] - if arm: - arm_obs.append(arm) - - # convert to a dict and back, should be a set! :/ - python 2.3 dosnt like. - return dict([ (bonename, None) for arm in arm_obs for bonename in arm.data.bones.keys() ]).keys() - - - -def actWeightNormalize(me, ob, PREF_PEAKWEIGHT, PREF_ACTIVE_ONLY, PREF_ARMATURE_ONLY, PREF_KEEP_PROPORTION): - - groupNames, vWeightDict= BPyMesh.meshWeight2Dict(me) - new_weight= max_weight= -1.0 - act_group= me.activeGroup - - if PREF_ACTIVE_ONLY: - normalizeGroups = [act_group] - else: - normalizeGroups = groupNames[:] - - if PREF_ARMATURE_ONLY: - - armature_groups = getArmatureGroups(ob, me) - - i = len(normalizeGroups) - while i: - i-=1 - if not normalizeGroups[i] in armature_groups: - del normalizeGroups[i] - - - for act_group in normalizeGroups: - vWeightDictUsed=[False] * len(vWeightDict) - - for i, wd in enumerate(vWeightDict): - try: - new_weight= wd[act_group] - if new_weight > max_weight: - max_weight= new_weight - vWeightDictUsed[i]=wd - except: - pass - - # These can be skipped for now, they complicate things when using multiple vgroups, - ''' - if max_weight < SMALL_NUM or new_weight == -1: - Draw.PupMenu('No verts to normalize. exiting.') - #return - - if abs(max_weight-PREF_PEAKWEIGHT) < SMALL_NUM: - Draw.PupMenu('Vert Weights are alredy normalized.') - #return - ''' - max_weight= max_weight/PREF_PEAKWEIGHT - - if PREF_KEEP_PROPORTION: - # TODO, PROPORTIONAL WEIGHT SCALING. - for wd in vWeightDictUsed: - if wd: # not false. - if len(wd) == 1: - # Only 1 group for thsi vert. Simple - wd[act_group] /= max_weight - else: - # More then 1 group. will need to scale all users evenly. - if PREF_ARMATURE_ONLY: - local_maxweight= max([v for k, v in wd.iteritems() if k in armature_groups]) / PREF_PEAKWEIGHT - if local_maxweight > 0.0: - # So groups that are not used in any bones are ignored. - for weight in wd.iterkeys(): - if weight in armature_groups: - wd[weight] /= local_maxweight - else: - local_maxweight= max(wd.itervalues()) / PREF_PEAKWEIGHT - for weight in wd.iterkeys(): - wd[weight] /= local_maxweight - - else: # Simple, just scale the weights up. we alredy know this is in an armature group (if needed) - for wd in vWeightDictUsed: - if wd: # not false. - wd[act_group] /= max_weight - - # Copy weights back to the mesh. - BPyMesh.dict2MeshWeight(me, groupNames, vWeightDict) - - -def main(): - scn= Scene.GetCurrent() - ob= scn.objects.active - - if not ob or ob.type != 'Mesh': - Draw.PupMenu('Error, no active mesh object, aborting.') - return - - me= ob.getData(mesh=1) - - PREF_PEAKWEIGHT= Draw.Create(1.0) - PREF_ACTIVE_ONLY= Draw.Create(1) - PREF_KEEP_PROPORTION= Draw.Create(1) - PREF_ARMATURE_ONLY= Draw.Create(0) - - pup_block= [\ - ('Peak Weight:', PREF_PEAKWEIGHT, 0.01, 1.0, 'Upper weight for normalizing.'),\ - ('Active Only', PREF_ACTIVE_ONLY, 'Only Normalize groups that have matching bones in an armature (when an armature is used).'),\ - ('Proportional', PREF_KEEP_PROPORTION, 'Scale other weights so verts (Keep weights with other groups in proportion).'),\ - ('Armature Only', PREF_ARMATURE_ONLY, 'Only Normalize groups that have matching bones in an armature (when an armature is used).'),\ - ] - - if not Draw.PupBlock('Clean Selected Meshes...', pup_block): - return - - actWeightNormalize(me, ob, PREF_PEAKWEIGHT.val, PREF_ACTIVE_ONLY.val, PREF_ARMATURE_ONLY.val, PREF_KEEP_PROPORTION.val) - -if __name__=='__main__': - main()
\ No newline at end of file diff --git a/release/scripts/widgetwizard.py b/release/scripts/widgetwizard.py deleted file mode 100644 index a7ddd68268a..00000000000 --- a/release/scripts/widgetwizard.py +++ /dev/null @@ -1,917 +0,0 @@ -#!BPY - -""" -Name: 'Shape Widget Wizard' -Blender: 238 -Group: 'Animation' -Tip: 'Adds Widgets for Driven Shapes' -""" - -__author__ = ["Johnny Matthews (guitargeek)"] -__url__ = ("blender", "blenderartists.org") -__version__ = "0.0.9 12/15/05" - -__bpydoc__ = """\ -"Shape Widget Wizard" creates objects that drive shape channels. - -Explanation: - -Shapes define morph targets and sometimes it is helpful to animate with a GUI -control panel of widgets. This script lets you define several different types -of controls that (depending on the type) control 1 to 4 shapes with a single -controller. - -Usage: - -1. Click where you want the widget to go<br> -2. Highlight the object that has shapes<br> -3. Run the script<br> -4. Choose the type of widget (there are next and back buttons if you pick the wrong kind)<br> -5. Click next and choose what shapes go where on the widget<br> -6. Choose a display name for the widget<br> -7. Click finish - -The widget is added and you are returned to the first screen for adding another widget. - -""" - -################################################################### -# # -# Shape Widget Wizard # -# # -# all versions (C) December 2005 Johnny Matthews (guitargeek) # -# # -# Released under the GPL # -# # -# Works in Blender 2.4 and higher # -# # -# This script can be found online at: # -# http://guitargeek.superihost.com/widgetmaker # -# # -# email: johnny.matthews@gmail.com # -################################################################### -# History # -# 0.9 # -# Added Name Objects # -# 0.81 # -# Added Single Shape Toggle # -# # -# 0.8 # -# Controller is Transform Locked and can only move # -# in appropriate directions # -# # -# 0.7 # -# Controller is named the same as the range + ".ctrl" # -# # -################################################################### - -import Blender -import bpy -from Blender import Mesh,Object,Material,Window,IpoCurve,Ipo,Text3d -from Blender.BGL import * -from Blender.Draw import * -print "----------------------" - -SHAPE1_ONE_MONE = 1 -SHAPE1_ONE_ZERO = 2 -SHAPE1_ZERO_MONE = 3 -SHAPE1_TOGGLE = 12 -SHAPE2_EXCLUSIVE = 4 -SHAPE2_V = 5 -SHAPE2_T = 6 -SHAPE2_INVT = 7 -SHAPE2_PLUS = 8 -SHAPE3_T = 9 -SHAPE3_INVT = 10 -SHAPE4_X = 11 - - -stage = 1 -numshapes = Create(1) -widmenu = Create(1) -rangename = Create("Range") -shapes = [Create(0),Create(0),Create(0),Create(0)] -drawtype = 0 - - -#get rid of an ipo curve by deleting all its points -def delCurve(ipo): - while len(ipo.bezierPoints) > 0: - ipo.delBezier(0) - ipo.recalc() - -#if a given ipocurve is not there create it, otherwise get it -def verifyIpocurve(ky,index): - ipo = ky.ipo - if ipo == None: - nip = bpy.data.ipos.new("keyipo", "Key") - ky.ipo = nip - ipo = ky.ipo - if index == 0: - idx = "Basis" - else: - idx = "Key " + str(index) - crv = ipo[idx] - if crv == None: - # print idx - crv = ipo.addCurve(idx) - crv.interpolation = IpoCurve.InterpTypes.LINEAR - return crv - -# Add the Drivers and Curves -def setupDrivers(ob,ctrl,type): - global shapes - me = ob.getData(mesh=1) - ky = me.key - - # Should we add an error here?? - if not ky: - return - - if type in [SHAPE1_ONE_MONE,SHAPE1_ONE_ZERO,SHAPE1_ZERO_MONE]: - ctrl.protectFlags = int("111111011",2) - ipo = verifyIpocurve(ky,shapes[0].val) - ipo.driver = 1 - ipo.driverObject = ctrl - ipo.driverChannel = IpoCurve.LOC_Z - ipo.recalc() - - delCurve(ipo) - if type == 1: - ipo.append((-1,-1)) - ipo.append((0,0)) - ipo.append((1,1)) - if type == 2: - ipo.append((0,0)) - ipo.append((1,1)) - if type == 3: - ipo.append((-1,-1)) - ipo.append((0,0)) - ipo.recalc() - - if type == SHAPE1_TOGGLE: - ctrl.protectFlags = int("111111011",2) - ipo = verifyIpocurve(ky,shapes[0].val) - ipo.driver = 1 - ipo.driverObject = ctrl - ipo.driverChannel = IpoCurve.LOC_Z - ipo.recalc() - delCurve(ipo) - ipo.append((0,0)) - ipo.append((0.5,0)) - ipo.append((0.500001,1)) - ipo.append((1,1)) - ipo.recalc() - - if type == SHAPE2_EXCLUSIVE: - ctrl.protectFlags = int("111111011",2) - ipo = verifyIpocurve(ky,shapes[0].val) - ipo.driver = 1 - ipo.driverObject = ctrl - ipo.driverChannel = IpoCurve.LOC_Z - ipo.recalc() - delCurve(ipo) - ipo.append((0,0)) - ipo.append((1,1)) - ipo.recalc() - - ipo2 = verifyIpocurve(ky,shapes[1].val) - ipo2.driver = 1 - ipo2.driverObject = ctrl - ipo2.driverChannel = IpoCurve.LOC_Z - ipo2.recalc() - delCurve(ipo2) - ipo2.append((-1,1)) - ipo2.append((0,0)) - ipo2.recalc() - - if type == SHAPE2_T: - ctrl.protectFlags = int("111111010",2) - ipo = verifyIpocurve(ky,shapes[0].val) - ipo.driver = 1 - ipo.driverObject = ctrl - ipo.driverChannel = IpoCurve.LOC_Z - ipo.recalc() - delCurve(ipo) - ipo.append((-1,-1)) - ipo.append((0,0)) - ipo.recalc() - - ipo2 = verifyIpocurve(ky,shapes[1].val) - ipo2.driver = 1 - ipo2.driverObject = ctrl - ipo2.driverChannel = IpoCurve.LOC_X - ipo2.recalc() - delCurve(ipo2) - ipo2.append((-1,-1)) - ipo2.append((1,1)) - ipo2.recalc() - - if type == SHAPE2_INVT: - ctrl.protectFlags = int("111111010",2) - ipo = verifyIpocurve(ky,shapes[0].val) - ipo.driver = 1 - ipo.driverObject = ctrl - ipo.driverChannel = IpoCurve.LOC_Z - ipo.recalc() - delCurve(ipo) - ipo.append((0,0)) - ipo.append((1,1)) - ipo.recalc() - - ipo2 = verifyIpocurve(ky,shapes[1].val) - ipo2.driver = 1 - ipo2.driverObject = ctrl - ipo2.driverChannel = IpoCurve.LOC_X - ipo2.recalc() - delCurve(ipo2) - ipo2.append((-1,-1)) - ipo2.append((1,1)) - ipo2.recalc() - - if type == SHAPE2_PLUS: - ctrl.protectFlags = int("111111010",2) - ipo = verifyIpocurve(ky,shapes[0].val) - ipo.driver = 1 - ipo.driverObject = ctrl - ipo.driverChannel = IpoCurve.LOC_Z - ipo.recalc() - delCurve(ipo) - ipo.append((-1,-1)) - ipo.append((1,1)) - ipo.recalc() - - ipo2 = verifyIpocurve(ky,shapes[1].val) - ipo2.driver = 1 - ipo2.driverObject = ctrl - ipo2.driverChannel = IpoCurve.LOC_X - ipo2.recalc() - delCurve(ipo2) - ipo2.append((-1,-1)) - ipo2.append((1,1)) - ipo2.recalc() - - if type == SHAPE2_V: # 2 Shape Mix - ctrl.protectFlags = int("111111010",2) - ipo = verifyIpocurve(ky,shapes[0].val) - ipo.driver = 1 - ipo.driverObject = ctrl - ipo.driverChannel = IpoCurve.LOC_Z - delCurve(ipo) - ipo.append((0,0)) - ipo.append((1,1)) - ipo.recalc() - - ipo2 = verifyIpocurve(ky,shapes[1].val) - ipo2.driver = 1 - ipo2.driverObject = ctrl - ipo2.driverChannel = IpoCurve.LOC_X - delCurve(ipo2) - ipo2.append((0,0)) - ipo2.append((1,1)) - ipo2.recalc() - - - if type == SHAPE3_INVT: - ctrl.protectFlags = int("111111010",2) - ipo = verifyIpocurve(ky,shapes[0].val) - ipo.driver = 1 - ipo.driverObject = ctrl - ipo.driverChannel = IpoCurve.LOC_Z - ipo.recalc() - delCurve(ipo) - ipo.append((0,0)) - ipo.append((1,1)) - ipo.recalc() - - ipo2 = verifyIpocurve(ky,shapes[1].val) - ipo2.driver = 1 - ipo2.driverObject = ctrl - ipo2.driverChannel = IpoCurve.LOC_X - ipo2.recalc() - delCurve(ipo2) - ipo2.append((-1,1)) - ipo2.append((0,0)) - ipo2.recalc() - - ipo2 = verifyIpocurve(ky,shapes[2].val) - ipo2.driver = 1 - ipo2.driverObject = ctrl - ipo2.driverChannel = IpoCurve.LOC_X - ipo2.recalc() - delCurve(ipo2) - ipo2.append((0,0)) - ipo2.append((1,1)) - ipo2.recalc() - - if type == SHAPE3_T: - ctrl.protectFlags = int("111111010",2) - ipo = verifyIpocurve(ky,shapes[0].val) - ipo.driver = 1 - ipo.driverObject = ctrl - ipo.driverChannel = IpoCurve.LOC_Z - ipo.recalc() - delCurve(ipo) - ipo.append((-1,-1)) - ipo.append((0,0)) - ipo.recalc() - - ipo2 = verifyIpocurve(ky,shapes[1].val) - ipo2.driver = 1 - ipo2.driverObject = ctrl - ipo2.driverChannel = IpoCurve.LOC_X - ipo2.recalc() - delCurve(ipo2) - ipo2.append((-1,1)) - ipo2.append((0,0)) - ipo2.recalc() - - ipo2 = verifyIpocurve(ky,shapes[2].val) - ipo2.driver = 1 - ipo2.driverObject = ctrl - ipo2.driverChannel = IpoCurve.LOC_X - ipo2.recalc() - delCurve(ipo2) - ipo2.append((0,0)) - ipo2.append((1,1)) - ipo2.recalc() - - if type == SHAPE4_X: - ctrl.protectFlags = int("111111010",2) - ipo = verifyIpocurve(ky,shapes[0].val) - ipo.driver = 1 - ipo.driverObject = ctrl - ipo.driverChannel = IpoCurve.LOC_Z - delCurve(ipo) - ipo.append((0,0)) - ipo.append((1,1)) - ipo.recalc() - - ipo2 = verifyIpocurve(ky,shapes[1].val) - ipo2.driver = 1 - ipo2.driverObject = ctrl - ipo2.driverChannel = IpoCurve.LOC_X - delCurve(ipo2) - ipo2.append((0,0)) - ipo2.append((1,1)) - ipo2.recalc() - - ipo3 = verifyIpocurve(ky,shapes[2].val) - ipo3.driver = 1 - ipo3.driverObject = ctrl - ipo3.driverChannel = IpoCurve.LOC_X - delCurve(ipo3) - ipo3.append((-1,1)) - ipo3.append((0,0)) - ipo3.recalc() - - ipo4 = verifyIpocurve(ky,shapes[3].val) - ipo4.driver = 1 - ipo4.driverObject = ctrl - ipo4.driverChannel = IpoCurve.LOC_Z - delCurve(ipo4) - ipo4.append((-1,1)) - ipo4.append((0,0)) - ipo4.recalc() - -#The Main Call to Build the Widget - -def build(type): - global shapes,widmenu,rangename - sce = bpy.data.scenes.active - ob = sce.objects.active - - try: - ob.getData(mesh=1).key - except: - Blender.Draw.PupMenu('Aborting%t|Object has no keys') - return - - loc = Window.GetCursorPos() - range = makeRange(sce, type,rangename.val) - controller = makeController(sce, rangename.val) - text = makeText(sce, rangename.val) - - range.restrictRender = True - controller.restrictRender = True - text.restrictRender = True - - range.setLocation(loc) - controller.setLocation(loc) - text.setLocation(loc) - - range.makeParent([controller],1) - range.makeParent([text],0) - - sce.update() - - setupDrivers(ob,controller,widmenu.val) - -#Create the text - -def makeText(sce, name): - txt = bpy.data.curves.new(name+'.name', 'Text3d') - - txt.setDrawMode(Text3d.DRAW3D) - txt.setAlignment(Text3d.MIDDLE) - txt.setText(name) - ob = sce.objects.new(txt) - ob.setEuler((3.14159/2,0,0)) - return ob - - -#Create the mesh controller - -def makeController(sce, name): - me = bpy.data.meshes.new(name+".ctrl") - ob = sce.objects.new(me) - me.verts.extend([\ - (-0.15,0, 0),\ - ( 0,0, 0.15),\ - ( 0.15,0, 0),\ - ( 0,0,-0.15)]) - - me.edges.extend([(0,1,2,3)]) - return ob - -#Create the mesh range - -def makeRange(sce,type,name): - #ob.setDrawMode(8) # Draw Name - me = bpy.data.meshes.new(name) - ob = sce.objects.new(me) - - if type == SHAPE1_ONE_ZERO: - me.verts.extend([\ - (-0.15,0,0),\ - ( 0.15,0,0),\ - (-0.15,0,1),\ - ( 0.15,0,1),\ - (-0.25,0,.1),\ - (-0.25,0,-.10),\ - (0.25,0,.1),\ - (0.25,0,-0.10)]) - - me.edges.extend([(0,1,3,2),(4,5,0),(6,7,1)]) - - elif type == SHAPE1_TOGGLE: - me.verts.extend([\ - (-0.15,0,-0.5),\ - ( 0.15,0,-0.5),\ - ( 0.15,0, 0.5),\ - (-0.15,0, 0.5),\ - (-0.15,0, 1.5),\ - ( 0.15,0, 1.5)]) - - me.edges.extend([(0,1,2,3),(3,4,5,2)]) - - elif type == SHAPE1_ZERO_MONE: - me.verts.extend([\ - (-0.15,0,0),\ - ( 0.15,0,0),\ - (-0.15,0,-1),\ - ( 0.15,0,-1),\ - (-0.25,0,.1),\ - (-0.25,0,-.10),\ - (0.25,0,.1),\ - (0.25,0,-0.10)]) - - me.edges.extend([(0,1,3,2),(4,5,0),(6,7,1)]) - - elif type in [SHAPE1_ONE_MONE,SHAPE2_EXCLUSIVE]: - me.verts.extend([\ - (-0.15,0,-1),\ - ( 0.15,0,-1),\ - (-0.15,0,1),\ - ( 0.15,0,1),\ - (-0.25,0,.1),\ - (-0.25,0,-.10),\ - (0.25,0,.1),\ - (0.25,0,-0.10),\ - (-0.15,0,0),\ - ( 0.15,0,0)]) - - l = [(0,1,3,2),(4,5,8),(6,7,9)] - me.edges.extend(l) - - elif type == SHAPE2_T: - me.verts.extend([\ - (-1,0,0),\ - ( 1,0,0),\ - ( 1,0,-1),\ - (-1,0,-1)]) - - me.edges.extend([(0,1,2,3)]) - - elif type == SHAPE2_INVT: - me.verts.extend([\ - (-1,0,0),\ - ( 1,0,0),\ - ( 1,0,1),\ - (-1,0,1)]) - - me.edges.extend([(0,1,2,3)]) - - elif type == SHAPE2_PLUS: - me.verts.extend([\ - (-1,0,-1),\ - ( 1,0,-1),\ - ( 1,0,1),\ - (-1,0,1)]) - me.edges.extend([(0,1,2,3)]) - - elif type == SHAPE2_V: - me.verts.extend([\ - (0,0,0),\ - (1,0,0),\ - (1,0,1),\ - (0,0,1)]) - - me.edges.extend([(0,1,2,3)]) - ob.setEuler((0,-0.78539,0)) - - elif type == SHAPE3_INVT: - me.verts.extend([\ - (-1,0,0),\ - ( 1,0,0),\ - ( 1,0,1),\ - (-1,0,1)]) - - me.edges.extend([(0,1,2,3)]) - - elif type == SHAPE3_T: - me.verts.extend([\ - (-1,0,0),\ - ( 1,0,0),\ - ( 1,0,-1),\ - (-1,0,-1)]) - - me.edges.extend([(0,1,2,3)]) - - - elif type == SHAPE4_X: - me.verts.extend([\ - (0,0,-1),\ - (1,0,-1),\ - (1,0,0),\ - (1,0,1),\ - (0,0,1),\ - (-1,0,1),\ - (-1,0,0),\ - (-1,0,-1)]) - - me.edges.extend([(0,1),(1,2),(2,3),(3,4),(4,5),(5,6),(6,7),(7,0)]) - ob.setEuler((0,-0.78539,0)) - - return ob - - -def create(): - main() - -####################### gui ###################### - - -EVENT_NONE = 1 -EVENT_EXIT = 100 -EVENT_WIDGET_MENU = 101 -EVENT_NEXT = 102 -EVENT_BACK = 103 - -#get the list of shapes from the selected object - -def shapeMenuText(): - ob = bpy.data.scenes.active.objects.active - if not ob: - return "" - - me = ob.getData(mesh=1) - try: key= me.key - except: key = None - - if key == None: - return "" - - blocks = key.blocks - menu = "Choose Shape %t|" - for i, block in enumerate(blocks): - menu = menu + block.name + " %x" + str(i) + "|" - return menu - - -#draw the widget for the gui - -def drawWidget(type): - glColor3f(0.0,0.0,0.0) - global shapes - if type == SHAPE1_ONE_MONE:# 1 to -1 Single Shape - glBegin(GL_LINE_STRIP) - glVertex2i(150,50) - glVertex2i(170,50) - glVertex2i(170,150) - glVertex2i(150,150) - glVertex2i(150,50) - glEnd() - glBegin(GL_LINE_STRIP) - glVertex2i(140,100) - glVertex2i(190,100) - glEnd() - glRasterPos2d(180,140) - Text("1","normal") - glRasterPos2d(180,60) - Text("-1","normal") - shapes[0] = Menu(shapeMenuText(), EVENT_NONE, 190, 100, 100, 18, shapes[0].val, "Choose Shape.") - elif type == SHAPE1_TOGGLE:# Toggle Single Shape - glBegin(GL_LINE_STRIP) - glVertex2i(150,50) - glVertex2i(170,50) - glVertex2i(170,100) - glVertex2i(150,100) - glVertex2i(150,50) - glEnd() - glBegin(GL_LINE_STRIP) - glVertex2i(170,100) - glVertex2i(170,150) - glVertex2i(150,150) - glVertex2i(150,100) - glEnd() - glRasterPos2d(180,140) - Text("On","normal") - glRasterPos2d(180,60) - Text("Off","normal") - shapes[0] = Menu(shapeMenuText(), EVENT_NONE, 190, 100, 100, 18, shapes[0].val, "Choose Shape.") - elif type == SHAPE1_ONE_ZERO: # 1 to 0 Single Shape - glBegin(GL_LINE_STRIP) - glVertex2i(150,50) - glVertex2i(170,50) - glVertex2i(170,150) - glVertex2i(150,150) - glVertex2i(150,50) - glEnd() - glBegin(GL_LINE_STRIP) - glVertex2i(140,50) - glVertex2i(190,50) - glEnd() - glRasterPos2d(180,140) - Text("1","normal") - glRasterPos2d(180,60) - Text("0","normal") - shapes[0] = Menu(shapeMenuText(), EVENT_NONE, 190, 100, 100, 18, shapes[0].val, "Choose Shape.") - elif type == SHAPE1_ZERO_MONE: - glBegin(GL_LINE_STRIP) - glVertex2i(150,50) - glVertex2i(170,50) - glVertex2i(170,150) - glVertex2i(150,150) - glVertex2i(150,50) - glEnd() - glBegin(GL_LINE_STRIP) - glVertex2i(140,150) - glVertex2i(190,150) - glEnd() - glRasterPos2d(180,140) - Text("0","normal") - glRasterPos2d(180,60) - Text("-1","normal") - shapes[0] = Menu(shapeMenuText(), EVENT_NONE, 190, 100, 100, 18, shapes[0].val, "Choose Shape.") - elif type == SHAPE2_EXCLUSIVE: - glBegin(GL_LINE_STRIP) - glVertex2i(150,50) - glVertex2i(170,50) - glVertex2i(170,150) - glVertex2i(150,150) - glVertex2i(150,50) - glEnd() - glBegin(GL_LINE_STRIP) - glVertex2i(140,100) - glVertex2i(190,100) - glEnd() - glRasterPos2d(180,140) - Text("1","normal") - glRasterPos2d(180,60) - Text("1","normal") - shapes[0] = Menu(shapeMenuText(), EVENT_NONE, 195, 135, 100, 18, shapes[0].val, "Choose Shape 1.") - shapes[1] = Menu(shapeMenuText(), EVENT_NONE, 195, 52, 100, 18, shapes[1].val, "Choose Shape 2.") - elif type == SHAPE2_T: - glBegin(GL_LINE_STRIP) - glVertex2i(150,75) - glVertex2i(250,75) - glVertex2i(250,125) - glVertex2i(150,125) - glVertex2i(150,75) - glEnd() - glBegin(GL_LINE_STRIP) - glVertex2i(140,125) - glVertex2i(260,125) - glEnd() - glRasterPos2d(200,140) - Text("0","normal") - glRasterPos2d(200,60) - Text("-1","normal") - glRasterPos2d(250,140) - Text("1","normal") - glRasterPos2d(150,140) - Text("-1","normal") - shapes[0] = Menu(shapeMenuText(), EVENT_NONE, 220, 52, 100, 18, shapes[0].val, "Choose Shape 1.") - shapes[1] = Menu(shapeMenuText(), EVENT_NONE, 260, 135, 100, 18, shapes[1].val, "Choose Shape 2.") - elif type == SHAPE2_INVT: - glBegin(GL_LINE_STRIP) - glVertex2i(150,75) - glVertex2i(250,75) - glVertex2i(250,125) - glVertex2i(150,125) - glVertex2i(150,75) - glEnd() - glBegin(GL_LINE_STRIP) - glVertex2i(140,75) - glVertex2i(260,75) - glEnd() - glRasterPos2d(200,60) - Text("0","normal") - glRasterPos2d(200,140) - Text("1","normal") - glRasterPos2d(250,60) - Text("1","normal") - glRasterPos2d(150,60) - Text("-1","normal") - shapes[0] = Menu(shapeMenuText(), EVENT_NONE, 220, 135, 100, 18, shapes[0].val, "Choose Shape 1.") - shapes[1] = Menu(shapeMenuText(), EVENT_NONE, 260, 52, 100, 18, shapes[1].val, "Choose Shape 2.") - elif type == SHAPE2_PLUS: - glBegin(GL_LINE_STRIP) - glVertex2i(150,50) - glVertex2i(250,50) - glVertex2i(250,150) - glVertex2i(150,150) - glVertex2i(150,50) - glEnd() - glBegin(GL_LINE_STRIP) - glVertex2i(140,100) - glVertex2i(260,100) - glEnd() - glRasterPos2d(200,105) - Text("0","normal") - glRasterPos2d(200,140) - Text("1","normal") - glRasterPos2d(200,55) - Text("-1","normal") - glRasterPos2d(250,105) - Text("1","normal") - glRasterPos2d(150,105) - Text("-1","normal") - shapes[0] = Menu(shapeMenuText(), EVENT_NONE, 220, 155, 100, 18, shapes[0].val, "Choose Shape 1.") - shapes[1] = Menu(shapeMenuText(), EVENT_NONE, 260, 100, 100, 18, shapes[1].val, "Choose Shape 2.") - elif type == SHAPE2_V: - glBegin(GL_LINE_STRIP) - glVertex2i(150,70) - glVertex2i(185,105) - glVertex2i(150,141) - glVertex2i(115,105) - glVertex2i(150,70) - glEnd() - glRasterPos2d(110,105) - Text("1","normal") - glRasterPos2d(190,105) - Text("1","normal") - glRasterPos2d(150,80) - Text("0","normal") - shapes[0] = Menu(shapeMenuText(), EVENT_NONE, 20, 125, 100, 18, shapes[0].val, "Choose Shape 1.") - shapes[1] = Menu(shapeMenuText(), EVENT_NONE, 195, 125, 100, 18, shapes[1].val, "Choose Shape 2.") - - - - elif type == SHAPE3_T: - glBegin(GL_LINE_STRIP) - glVertex2i(150,75) - glVertex2i(250,75) - glVertex2i(250,125) - glVertex2i(150,125) - glVertex2i(150,75) - glEnd() - glBegin(GL_LINE_STRIP) - glVertex2i(140,125) - glVertex2i(260,125) - glEnd() - glRasterPos2d(200,140) - Text("0","normal") - glRasterPos2d(200,60) - Text("-1","normal") - glRasterPos2d(250,140) - Text("1","normal") - glRasterPos2d(150,140) - Text("1","normal") - shapes[0] = Menu(shapeMenuText(), EVENT_NONE, 220, 52, 100, 18, shapes[0].val, "Choose Shape 1.") - shapes[1] = Menu(shapeMenuText(), EVENT_NONE, 45, 135, 100, 18, shapes[1].val, "Choose Shape 2.") - shapes[2] = Menu(shapeMenuText(), EVENT_NONE, 260, 135, 100, 18, shapes[2].val, "Choose Shape 3.") - elif type == SHAPE3_INVT: - glBegin(GL_LINE_STRIP) - glVertex2i(150,75) - glVertex2i(250,75) - glVertex2i(250,125) - glVertex2i(150,125) - glVertex2i(150,75) - glEnd() - glBegin(GL_LINE_STRIP) - glVertex2i(140,75) - glVertex2i(260,75) - glEnd() - glRasterPos2d(200,60) - Text("0","normal") - glRasterPos2d(200,140) - Text("1","normal") - glRasterPos2d(250,60) - Text("1","normal") - glRasterPos2d(150,60) - Text("1","normal") - shapes[0] = Menu(shapeMenuText(), EVENT_NONE, 220, 135, 100, 18, shapes[0].val, "Choose Shape 1.") - shapes[1] = Menu(shapeMenuText(), EVENT_NONE, 45, 52, 100, 18, shapes[1].val, "Choose Shape 2.") - shapes[2] = Menu(shapeMenuText(), EVENT_NONE, 260, 52, 100, 18, shapes[2].val, "Choose Shape 3.") - - - elif type == SHAPE4_X: - glBegin(GL_LINE_STRIP) - glVertex2i(150,70) - glVertex2i(185,105) - glVertex2i(150,141) - glVertex2i(115,105) - glVertex2i(150,70) - glEnd() - glRasterPos2d(120,125) - Text("1","normal") - glRasterPos2d(180,125) - Text("1","normal") - glRasterPos2d(120,80) - Text("1","normal") - glRasterPos2d(180,80) - Text("1","normal") - - glRasterPos2d(145,105) - Text("0","normal") - shapes[0] = Menu(shapeMenuText(), EVENT_NONE, 10, 125, 100, 18, shapes[0].val, "Choose Shape 1.") - shapes[1] = Menu(shapeMenuText(), EVENT_NONE, 195, 125, 100, 18, shapes[1].val, "Choose Shape 2.") - shapes[2] = Menu(shapeMenuText(), EVENT_NONE, 10, 60, 100, 18, shapes[2].val, "Choose Shape 3.") - shapes[3] = Menu(shapeMenuText(), EVENT_NONE, 195, 60, 100, 18, shapes[3].val, "Choose Shape 4.") - -#the gui callback - -def draw(): - global widmenu,numshapes,stage,type, shapes,rangename - #glRasterPos2d(5,200) - #Text("Shape Widget Wizard","large") - Label("Shape Widget Wizard", 5,200, 200, 12) - - PushButton("Quit", EVENT_EXIT, 5, 5, 50, 18) - - if stage == 1: - name = "Choose Widget Type %t|\ -1 Shape: 1 / -1 %x" +str(SHAPE1_ONE_MONE) +"|\ -1 Shape: 1,0 %x" +str(SHAPE1_ONE_ZERO) +"|\ -1 Shape: 0,-1 %x" +str(SHAPE1_ZERO_MONE)+"|\ -1 Shape: Toggle %x" +str(SHAPE1_TOGGLE) +"|\ -2 Shape Exclusive %x"+str(SHAPE2_EXCLUSIVE)+"|\ -2 Shape - V %x" +str(SHAPE2_V) +"|\ -2 Shape - T %x" +str(SHAPE2_T) +"|\ -2 Shape - Inv T %x" +str(SHAPE2_INVT) +"|\ -2 Shape - + %x" +str(SHAPE2_PLUS) +"|\ -3 Shape - T %x" +str(SHAPE3_T) +"|\ -3 Shape - Inv T%x" +str(SHAPE3_INVT) +"|\ -4 Shape - Mix %x" +str(SHAPE4_X) - widmenu = Menu(name, EVENT_NONE, 5, 120, 200, 40, widmenu.val, "Choose Widget Type.") - PushButton("Next", EVENT_NEXT, 5, 25, 50, 18) - - elif stage == 2: - glRasterPos2d(60,140) - rangename = String("Name: ", EVENT_NONE, 5, 170, 200, 18, rangename.val, 50, "Name for Range Object") - drawWidget(widmenu.val) - BeginAlign() - PushButton("Back", EVENT_BACK, 5, 25, 50, 18, "Choose another shape type") - PushButton("Finish", EVENT_NEXT, 55, 25, 50, 18, "Add Objects at the cursor location") - EndAlign() - return - - - -def event(evt, val): - if (evt == QKEY and not val): - Exit() - - -def bevent(evt): - global widmenu,stage,drawtype - ######### Manages GUI events - if evt==EVENT_EXIT: - Exit() - elif evt==EVENT_BACK: - if stage == 2: - stage = 1 - Redraw() - elif evt==EVENT_NEXT: - if stage == 1: - stage = 2 - Redraw() - elif stage == 2: - build(widmenu.val) - stage = 1 - Window.RedrawAll() - - -Register(draw, event, bevent) diff --git a/release/scripts/wizard_bolt_factory.py b/release/scripts/wizard_bolt_factory.py deleted file mode 100644 index 2d653b211d5..00000000000 --- a/release/scripts/wizard_bolt_factory.py +++ /dev/null @@ -1,2811 +0,0 @@ -#!BPY -# -*- coding: latin-1 -*- -""" -Name: 'Bolt Factory' -Blender: 248 -Group: 'Wizards' -Tooltip: 'Create models of various types of screw fasteners.' -""" - -__author__ = " Aaron Keith (Spudmn) " -__version__ = "2.02 2009/06/10" -__url__ = ["Author's site,http://sourceforge.net/projects/boltfactory/", "Blender,http://wiki.blender.org/index.php/Extensions:Py/Scripts/Manual/Misc/Bolt_Factory"] -__bpydoc__ = """\ -Bolt_Factory.py - -Bolt Factory is a Python script for Blender 3D. - -The script allows the user to create models of various types of screw fasteners. - -For best results set the material to smooth and apply a Edge Split modifier -with default settings. - - -History: - V2.02 10/06/09 by Aaron Keith - - -Added changes made by the Blender team. - - V2.01 26/05/09 by Aaron Keith - - - Fixed normal's on Lock Nut - -V2.00 22/05/09 by Aaron Keith - -- Better error checking. -- Lock Nut and Hex Nut meshes added. -- Pre-sets for common metric bolts and nuts. -- Improved GUI. -- Meshes scaled to a smaller size -- Fixed bug when using crest and root percent other than 10% -- Can now create meshes in Edit Mode. This will add to the - current mesh and align with the current view. - -V1.00 01/04/08 by Aaron Keith - -- This version is very much a work in progress. -- This is my first attempt to program in Python. This version is - unpolished and doesn't do much error checking. Therefore - if the user sets strange variable the model created will be - as equally strange. - -- To Do: -- Better error checking. -- More Head and Bit types. -- Better documentation. - - -""" - -# -------------------------------------------------------------------------- -# Bolt_Factory.py -# -------------------------------------------------------------------------- -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Copyright (C) 2009: Aaron Keith -# -# 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 ***** -# -------------------------------------------------------------------------- - - - - -import Blender -from Blender import Draw, BGL,Mesh -from Blender import * -from math import * -from Blender import Mathutils -from Blender.Mathutils import * - - -#Global_Scale = 0.001 #1 blender unit = X mm -Global_Scale = 0.1 #1 blender unit = X mm -#Global_Scale = 1.0 #1 blender unit = X mm -Global_NutRad = 0.0 -MAX_INPUT_NUMBER = 50 - -No_Event,On_Preset_Click,On_Apply_Click,On_Create_Click,On_Hex_Click, On_Cap_Click,On_Dome_Click,On_Pan_Click,On_Bit_None_Click,On_Bit_Allen_Click,On_Bit_Philips_Click,On_Exit_Click,On_Model_Bolt_Click,On_Model_Nut_Click,On_Hex_Nut_Click,On_Lock_Nut_Click,On_Test_Click = range(17) # this is like a ENUM - - -Head_Type={'HEX' : [Draw.Create(1),On_Hex_Click,""], - 'CAP' : [Draw.Create(0),On_Cap_Click,""], - 'DOME': [Draw.Create(0),On_Dome_Click,""], - 'PAN' : [Draw.Create(0),On_Pan_Click,""]} - - -Bit_Type={'NONE' : [Draw.Create(1),On_Bit_None_Click,""], - 'ALLEN' : [Draw.Create(0),On_Bit_Allen_Click,""], - 'PHILLIPS': [Draw.Create(0),On_Bit_Philips_Click,""]} - -Model_Type={'BOLT' : [Draw.Create(1),On_Model_Bolt_Click,"Bolt Settings"], - 'NUT' : [Draw.Create(0),On_Model_Nut_Click,"Nut Settings"]} - -Nut_Type={'HEX' : [Draw.Create(1),On_Hex_Nut_Click,""], - 'LOCK' : [Draw.Create(0),On_Lock_Nut_Click,""]} - - -Phillips_Bit_Depth = Draw.Create(3.27) -Philips_Bit_Dia = Draw.Create(5.20) - -Allen_Bit_Depth = Draw.Create(4.0) -Allen_Bit_Flat_Distance = Draw.Create(6.0) - -Hex_Head_Height = Draw.Create(5.3) -Hex_Head_Flat_Distance = Draw.Create(13.0) - -Cap_Head_Dia = Draw.Create(13.5) -Cap_Head_Height = Draw.Create(8.0) - -Dome_Head_Dia = Draw.Create(16.0) - -Pan_Head_Dia = Draw.Create(16.0) - -Shank_Dia = Draw.Create(8.0) -Shank_Length = Draw.Create(0.0) - -Thread_Length = Draw.Create(16.0) -Major_Dia = Draw.Create(8.0) -Minor_Dia = Draw.Create(6.917) -Pitch = Draw.Create(1.0) -Crest_Percent = Draw.Create(10) -Root_Percent = Draw.Create(10) - -Hex_Nut_Height = Draw.Create(8.0) -Hex_Nut_Flat_Distance = Draw.Create(13.0) - -Preset_Menu = Draw.Create(5) - - -########################################################################################## -########################################################################################## -## Miscellaneous Utilities -########################################################################################## -########################################################################################## - -# Returns a list of verts rotated by the given matrix. Used by SpinDup -def Rot_Mesh(verts,matrix): - return [list(Vector(v) * matrix) for v in verts] - -# Returns a list of faces that has there index incremented by offset -def Copy_Faces(faces,offset): - ret = [] - for f in faces: - fsub = [] - for i in range(len(f)): - fsub.append(f[i]+ offset) - ret.append(fsub) - return ret - - -# Much like Blenders built in SpinDup. -def SpinDup(VERTS,FACES,DEGREE,DIVISIONS,AXIS): - verts=[] - faces=[] - - if DIVISIONS == 0: - DIVISIONS = 1 - - step = DEGREE/DIVISIONS # set step so pieces * step = degrees in arc - - for i in xrange(int(DIVISIONS)): - rotmat = Mathutils.RotationMatrix(step*i, 4, AXIS) # 4x4 rotation matrix, 30d about the x axis. - Rot = Rot_Mesh(VERTS,rotmat) - faces.extend(Copy_Faces(FACES,len(verts))) - verts.extend(Rot) - return verts,faces - - -# Returns a list of verts that have been moved up the z axis by DISTANCE -def Move_Verts_Up_Z(VERTS,DISTANCE): - return [[v[0],v[1],v[2]+DISTANCE] for v in VERTS] - - -# Returns a list of verts and faces that has been mirrored in the AXIS -def Mirror_Verts_Faces(VERTS,FACES,AXIS,FLIP_POINT =0): - ret_vert = [] - ret_face = [] - offset = len(VERTS) - if AXIS == 'y': - for v in VERTS: - Delta = v[0] - FLIP_POINT - ret_vert.append([FLIP_POINT-Delta,v[1],v[2]]) - if AXIS == 'x': - for v in VERTS: - Delta = v[1] - FLIP_POINT - ret_vert.append([v[0],FLIP_POINT-Delta,v[2]]) - if AXIS == 'z': - for v in VERTS: - Delta = v[2] - FLIP_POINT - ret_vert.append([v[0],v[1],FLIP_POINT-Delta]) - - for f in FACES: - fsub = [] - for i in range(len(f)): - fsub.append(f[i]+ offset) - fsub.reverse() # flip the order to make norm point out - ret_face.append(fsub) - - return ret_vert,ret_face - - - -# Returns a list of faces that -# make up an array of 4 point polygon. -def Build_Face_List_Quads(OFFSET,COLUM,ROW,FLIP = 0): - Ret =[] - RowStart = 0; - for j in range(ROW): - for i in range(COLUM): - Res1 = RowStart + i; - Res2 = RowStart + i + (COLUM +1) - Res3 = RowStart + i + (COLUM +1) +1 - Res4 = RowStart+i+1 - if FLIP: - Ret.append([OFFSET+Res1,OFFSET+Res2,OFFSET+Res3,OFFSET+Res4]) - else: - Ret.append([OFFSET+Res4,OFFSET+Res3,OFFSET+Res2,OFFSET+Res1]) - RowStart += COLUM+1 - return Ret - - -# Returns a list of faces that makes up a fill pattern for a -# circle -def Fill_Ring_Face(OFFSET,NUM,FACE_DOWN = 0): - Ret =[] - Face = [1,2,0] - TempFace = [0,0,0] - A = 0 - B = 1 - C = 2 - if NUM < 3: - return None - for i in range(NUM-2): - if (i%2): - TempFace[0] = Face[C]; - TempFace[1] = Face[C] + 1; - TempFace[2] = Face[B]; - if FACE_DOWN: - Ret.append([OFFSET+Face[2],OFFSET+Face[1],OFFSET+Face[0]]) - else: - Ret.append([OFFSET+Face[0],OFFSET+Face[1],OFFSET+Face[2]]) - else: - TempFace[0] =Face[C]; - if Face[C] == 0: - TempFace[1] = NUM-1; - else: - TempFace[1] = Face[C] - 1; - TempFace[2] = Face[B]; - if FACE_DOWN: - Ret.append([OFFSET+Face[0],OFFSET+Face[1],OFFSET+Face[2]]) - else: - Ret.append([OFFSET+Face[2],OFFSET+Face[1],OFFSET+Face[0]]) - - Face[0] = TempFace[0] - Face[1] = TempFace[1] - Face[2] = TempFace[2] - return Ret - - -########################################################################################## -########################################################################################## -## Converter Functions For Bolt Factory -########################################################################################## -########################################################################################## - - -def Flat_To_Radius(FLAT): - h = (float(FLAT)/2)/cos(radians(30)) - return h - -def Get_Phillips_Bit_Height(Bit_Dia): - Flat_Width_half = (Bit_Dia*(0.5/1.82))/2.0 - Bit_Rad = Bit_Dia / 2.0 - x = Bit_Rad - Flat_Width_half - y = tan(radians(60))*x - return y - -########################################################################################## -########################################################################################## -## Error Checking -########################################################################################## -########################################################################################## - - -def Error_Check(): - - #global Phillips_Bit_Depth - #global Philips_Bit_Dia - - #global Allen_Bit_Depth - #global Allen_Bit_Flat_Distance - - #global Hex_Head_Height - #global Hex_Head_Flat_Distance - - #global Cap_Head_Dia - #global Cap_Head_Height - - - #global Dome_Head_Dia - - #global Pan_Head_Dia - - #global Shank_Dia - #global Shank_Length - - global Thread_Length - global Major_Dia - global Minor_Dia - global Pitch - global Hex_Nut_Flat_Distance - global Model_Type - #global Crest_Percent - #global Root_Percent - - Error_Result = 0 - - if Minor_Dia.val >= Major_Dia.val: - error_txt = "Error%t|Major Dia must be larger than Minor Dia" - Blender.Draw.PupMenu(error_txt) - print error_txt - Error_Result = TRUE - - elif (Model_Type['BOLT'][0].val) and ((Pitch.val*7.0) > Thread_Length.val): - error_txt = "Error%t|Thread length must be at least 7 times the Pitch" - Blender.Draw.PupMenu(error_txt) - print error_txt - Error_Result = TRUE - - elif (Model_Type['NUT'][0].val) and (Hex_Nut_Flat_Distance.val < Major_Dia.val): - error_txt = "Error%t|Nut Flat Distance must be greater than Major Dia" - Blender.Draw.PupMenu(error_txt) - print error_txt - Error_Result = TRUE - - elif (Model_Type['NUT'][0].val) and ((Pitch.val * 2.5 )> Hex_Nut_Height.val): - error_txt = "Error%t|Nut Height must be greater than 2.5 * Pitch" - Blender.Draw.PupMenu(error_txt) - print error_txt - Error_Result = TRUE - - elif (Model_Type['BOLT'][0].val): - Check_Head_Height = None - Check_Bit_Height = None - if (Bit_Type['ALLEN'][0].val): - Check_Bit_Height = Allen_Bit_Depth.val - if (Bit_Type['PHILLIPS'][0].val): - Check_Bit_Height = Phillips_Bit_Depth.val - if (Head_Type['HEX'][0].val): - Check_Head_Height = Hex_Head_Height.val - if (Head_Type['CAP'][0].val): - Check_Head_Height = Cap_Head_Height.val - - if Check_Head_Height != None and Check_Bit_Height != None : - if Check_Bit_Height > Check_Head_Height: - error_txt = "Error%t|Bit Depth must not be greater that Head Height" - Blender.Draw.PupMenu(error_txt) - print error_txt - Error_Result = TRUE - - - return Error_Result - - - -########################################################################################## -########################################################################################## -## Create Allen Bit -########################################################################################## -########################################################################################## - - -def Allen_Fill(OFFSET,FLIP= 0): - faces = [] - Lookup = [[19,1,0], - [19,2,1], - [19,3,2], - [19,20,3], - [20,4,3], - [20,5,4], - [20,6,5], - [20,7,6], - [20,8,7], - [20,9,8], - - [20,21,9], - - [21,10,9], - [21,11,10], - [21,12,11], - [21,13,12], - [21,14,13], - [21,15,14], - - [21,22,15], - [22,16,15], - [22,17,16], - [22,18,17] - ] - for i in Lookup: - if FLIP: - faces.append([OFFSET+i[2],OFFSET+i[1],OFFSET+i[0]]) - else: - faces.append([OFFSET+i[0],OFFSET+i[1],OFFSET+i[2]]) - - return faces - -def Allen_Bit_Dia(FLAT_DISTANCE): - Flat_Radius = (float(FLAT_DISTANCE)/2.0)/cos(radians(30)) - return (Flat_Radius * 1.05) * 2.0 - -def Allen_Bit_Dia_To_Flat(DIA): - Flat_Radius = (DIA/2.0)/1.05 - return (Flat_Radius * cos (radians(30)))* 2.0 - - - -def Create_Allen_Bit(FLAT_DISTANCE,HEIGHT): - Div = 36 - verts = [] - faces = [] - - Flat_Radius = (float(FLAT_DISTANCE)/2.0)/cos(radians(30)) - OUTTER_RADIUS = Flat_Radius * 1.05 - Outter_Radius_Height = Flat_Radius * (0.1/5.77) - FaceStart_Outside = len(verts) - Deg_Step = 360.0 /float(Div) - - for i in range((Div/2)+1): # only do half and mirror later - x = sin(radians(i*Deg_Step))*OUTTER_RADIUS - y = cos(radians(i*Deg_Step))*OUTTER_RADIUS - verts.append([x,y,0]) - - FaceStart_Inside = len(verts) - - Deg_Step = 360.0 /float(6) - for i in range((6/2)+1): - x = sin(radians(i*Deg_Step))* Flat_Radius - y = cos(radians(i*Deg_Step))* Flat_Radius - verts.append([x,y,0-Outter_Radius_Height]) - - faces.extend(Allen_Fill(FaceStart_Outside,0)) - - - FaceStart_Bottom = len(verts) - - Deg_Step = 360.0 /float(6) - for i in range((6/2)+1): - x = sin(radians(i*Deg_Step))* Flat_Radius - y = cos(radians(i*Deg_Step))* Flat_Radius - verts.append([x,y,0-HEIGHT]) - - faces.extend(Build_Face_List_Quads(FaceStart_Inside,3,1,TRUE)) - faces.extend(Fill_Ring_Face(FaceStart_Bottom,4)) - - - M_Verts,M_Faces = Mirror_Verts_Faces(verts,faces,'y') - verts.extend(M_Verts) - faces.extend(M_Faces) - - return verts,faces,OUTTER_RADIUS * 2.0 - - -########################################################################################## -########################################################################################## -## Create Phillips Bit -########################################################################################## -########################################################################################## - - -def Phillips_Fill(OFFSET,FLIP= 0): - faces = [] - Lookup = [[0,1,10], - [1,11,10], - [1,2,11], - [2,12,11], - - [2,3,12], - [3,4,12], - [4,5,12], - [5,6,12], - [6,7,12], - - [7,13,12], - [7,8,13], - [8,14,13], - [8,9,14], - - - [10,11,16,15], - [11,12,16], - [12,13,16], - [13,14,17,16], - [15,16,17,18] - - - ] - for i in Lookup: - if FLIP: - if len(i) == 3: - faces.append([OFFSET+i[2],OFFSET+i[1],OFFSET+i[0]]) - else: - faces.append([OFFSET+i[3],OFFSET+i[2],OFFSET+i[1],OFFSET+i[0]]) - else: - if len(i) == 3: - faces.append([OFFSET+i[0],OFFSET+i[1],OFFSET+i[2]]) - else: - faces.append([OFFSET+i[0],OFFSET+i[1],OFFSET+i[2],OFFSET+i[3]]) - return faces - - - -def Create_Phillips_Bit(FLAT_DIA,FLAT_WIDTH,HEIGHT): - Div = 36 - verts = [] - faces = [] - - FLAT_RADIUS = FLAT_DIA * 0.5 - OUTTER_RADIUS = FLAT_RADIUS * 1.05 - - Flat_Half = float(FLAT_WIDTH)/2.0 - - FaceStart_Outside = len(verts) - Deg_Step = 360.0 /float(Div) - for i in range((Div/4)+1): # only do half and mirror later - x = sin(radians(i*Deg_Step))*OUTTER_RADIUS - y = cos(radians(i*Deg_Step))*OUTTER_RADIUS - verts.append([x,y,0]) - - - FaceStart_Inside = len(verts) - verts.append([0,FLAT_RADIUS,0]) #10 - verts.append([Flat_Half,FLAT_RADIUS,0]) #11 - verts.append([Flat_Half,Flat_Half,0]) #12 - verts.append([FLAT_RADIUS,Flat_Half,0]) #13 - verts.append([FLAT_RADIUS,0,0]) #14 - - - verts.append([0,Flat_Half,0-HEIGHT]) #15 - verts.append([Flat_Half,Flat_Half,0-HEIGHT]) #16 - verts.append([Flat_Half,0,0-HEIGHT]) #17 - - verts.append([0,0,0-HEIGHT]) #18 - - faces.extend(Phillips_Fill(FaceStart_Outside,TRUE)) - - Spin_Verts,Spin_Face = SpinDup(verts,faces,360,4,'z') - - return Spin_Verts,Spin_Face,OUTTER_RADIUS * 2 - - -########################################################################################## -########################################################################################## -## Create Head Types -########################################################################################## -########################################################################################## - -def Max_Pan_Bit_Dia(HEAD_DIA): - HEAD_RADIUS = HEAD_DIA * 0.5 - XRad = HEAD_RADIUS * 1.976 - return (sin(radians(10))*XRad) * 2.0 - - -def Create_Pan_Head(HOLE_DIA,HEAD_DIA,SHANK_DIA,HEIGHT,RAD1,RAD2,FACE_OFFSET): - - DIV = 36 - HOLE_RADIUS = HOLE_DIA * 0.5 - HEAD_RADIUS = HEAD_DIA * 0.5 - SHANK_RADIUS = SHANK_DIA * 0.5 - - verts = [] - faces = [] - Row = 0 - BEVEL = HEIGHT * 0.01 - #Dome_Rad = HEAD_RADIUS * (1.0/1.75) - - Dome_Rad = HEAD_RADIUS * 1.12 - RAD_Offset = HEAD_RADIUS * 0.96 - OtherRad = HEAD_RADIUS * 0.16 - OtherRad_X_Offset = HEAD_RADIUS * 0.84 - OtherRad_Z_Offset = HEAD_RADIUS * 0.504 - XRad = HEAD_RADIUS * 1.976 - ZRad = HEAD_RADIUS * 1.768 - EndRad = HEAD_RADIUS * 0.284 - EndZOffset = HEAD_RADIUS * 0.432 - HEIGHT = HEAD_RADIUS * 0.59 - -# Dome_Rad = 5.6 -# RAD_Offset = 4.9 -# OtherRad = 0.8 -# OtherRad_X_Offset = 4.2 -# OtherRad_Z_Offset = 2.52 -# XRad = 9.88 -# ZRad = 8.84 -# EndRad = 1.42 -# EndZOffset = 2.16 -# HEIGHT = 2.95 - - FaceStart = FACE_OFFSET - - z = cos(radians(10))*ZRad - verts.append([HOLE_RADIUS,0.0,(0.0-ZRad)+z]) - Start_Height = 0 - ((0.0-ZRad)+z) - Row += 1 - - #for i in range(0,30,10): was 0 to 30 more work needed to make this look good. - for i in range(10,30,10): - x = sin(radians(i))*XRad - z = cos(radians(i))*ZRad - verts.append([x,0.0,(0.0-ZRad)+z]) - Row += 1 - - for i in range(20,140,10): - x = sin(radians(i))*EndRad - z = cos(radians(i))*EndRad - if ((0.0 - EndZOffset)+z) < (0.0-HEIGHT): - verts.append([(HEAD_RADIUS -EndRad)+x,0.0,0.0 - HEIGHT]) - else: - verts.append([(HEAD_RADIUS -EndRad)+x,0.0,(0.0 - EndZOffset)+z]) - Row += 1 - - - verts.append([SHANK_RADIUS,0.0,(0.0-HEIGHT)]) - Row += 1 - - verts.append([SHANK_RADIUS,0.0,(0.0-HEIGHT)-Start_Height]) - Row += 1 - - - sVerts,sFaces = SpinDup(verts,faces,360,DIV,'z') - sVerts.extend(verts) #add the start verts to the Spin verts to complete the loop - - faces.extend(Build_Face_List_Quads(FaceStart,Row-1,DIV)) - - Global_Head_Height = HEIGHT ; - - - return Move_Verts_Up_Z(sVerts,Start_Height),faces,HEIGHT - - - -def Create_Dome_Head(HOLE_DIA,HEAD_DIA,SHANK_DIA,HEIGHT,RAD1,RAD2,FACE_OFFSET): - DIV = 36 - HOLE_RADIUS = HOLE_DIA * 0.5 - HEAD_RADIUS = HEAD_DIA * 0.5 - SHANK_RADIUS = SHANK_DIA * 0.5 - - verts = [] - faces = [] - Row = 0 - BEVEL = HEIGHT * 0.01 - #Dome_Rad = HEAD_RADIUS * (1.0/1.75) - - Dome_Rad = HEAD_RADIUS * 1.12 - #Head_Height = HEAD_RADIUS * 0.78 - RAD_Offset = HEAD_RADIUS * 0.98 - Dome_Height = HEAD_RADIUS * 0.64 - OtherRad = HEAD_RADIUS * 0.16 - OtherRad_X_Offset = HEAD_RADIUS * 0.84 - OtherRad_Z_Offset = HEAD_RADIUS * 0.504 - - -# Dome_Rad = 5.6 -# RAD_Offset = 4.9 -# Dome_Height = 3.2 -# OtherRad = 0.8 -# OtherRad_X_Offset = 4.2 -# OtherRad_Z_Offset = 2.52 -# - - FaceStart = FACE_OFFSET - - verts.append([HOLE_RADIUS,0.0,0.0]) - Row += 1 - - - for i in range(0,60,10): - x = sin(radians(i))*Dome_Rad - z = cos(radians(i))*Dome_Rad - if ((0.0-RAD_Offset)+z) <= 0: - verts.append([x,0.0,(0.0-RAD_Offset)+z]) - Row += 1 - - - for i in range(60,160,10): - x = sin(radians(i))*OtherRad - z = cos(radians(i))*OtherRad - z = (0.0-OtherRad_Z_Offset)+z - if z < (0.0-Dome_Height): - z = (0.0-Dome_Height) - verts.append([OtherRad_X_Offset+x,0.0,z]) - Row += 1 - - verts.append([SHANK_RADIUS,0.0,(0.0-Dome_Height)]) - Row += 1 - - - sVerts,sFaces = SpinDup(verts,faces,360,DIV,'z') - sVerts.extend(verts) #add the start verts to the Spin verts to complete the loop - - faces.extend(Build_Face_List_Quads(FaceStart,Row-1,DIV)) - - return sVerts,faces,Dome_Height - - - -def Create_Cap_Head(HOLE_DIA,HEAD_DIA,SHANK_DIA,HEIGHT,RAD1,RAD2): - DIV = 36 - - HOLE_RADIUS = HOLE_DIA * 0.5 - HEAD_RADIUS = HEAD_DIA * 0.5 - SHANK_RADIUS = SHANK_DIA * 0.5 - - verts = [] - faces = [] - Row = 0 - BEVEL = HEIGHT * 0.01 - - - FaceStart = len(verts) - - verts.append([HOLE_RADIUS,0.0,0.0]) - Row += 1 - - #rad - - for i in range(0,100,10): - x = sin(radians(i))*RAD1 - z = cos(radians(i))*RAD1 - verts.append([(HEAD_RADIUS-RAD1)+x,0.0,(0.0-RAD1)+z]) - Row += 1 - - - verts.append([HEAD_RADIUS,0.0,0.0-HEIGHT+BEVEL]) - Row += 1 - - verts.append([HEAD_RADIUS-BEVEL,0.0,0.0-HEIGHT]) - Row += 1 - - #rad2 - - for i in range(0,100,10): - x = sin(radians(i))*RAD2 - z = cos(radians(i))*RAD2 - verts.append([(SHANK_RADIUS+RAD2)-x,0.0,(0.0-HEIGHT-RAD2)+z]) - Row += 1 - - - sVerts,sFaces = SpinDup(verts,faces,360,DIV,'z') - sVerts.extend(verts) #add the start verts to the Spin verts to complete the loop - - - faces.extend(Build_Face_List_Quads(FaceStart,Row-1,DIV)) - - return sVerts,faces,HEIGHT+RAD2 - - - -def Create_Hex_Head(FLAT,HOLE_DIA,SHANK_DIA,HEIGHT): - - verts = [] - faces = [] - HOLE_RADIUS = HOLE_DIA * 0.5 - Half_Flat = FLAT/2 - TopBevelRadius = Half_Flat - (Half_Flat* (0.05/8)) - Undercut_Height = (Half_Flat* (0.05/8)) - Shank_Bevel = (Half_Flat* (0.05/8)) - Flat_Height = HEIGHT - Undercut_Height - Shank_Bevel - #Undercut_Height = 5 - SHANK_RADIUS = SHANK_DIA/2 - Row = 0; - - verts.append([0.0,0.0,0.0]) - - - FaceStart = len(verts) - #inner hole - - x = sin(radians(0))*HOLE_RADIUS - y = cos(radians(0))*HOLE_RADIUS - verts.append([x,y,0.0]) - - - x = sin(radians(60/6))*HOLE_RADIUS - y = cos(radians(60/6))*HOLE_RADIUS - verts.append([x,y,0.0]) - - - x = sin(radians(60/3))*HOLE_RADIUS - y = cos(radians(60/3))*HOLE_RADIUS - verts.append([x,y,0.0]) - - - x = sin(radians(60/2))*HOLE_RADIUS - y = cos(radians(60/2))*HOLE_RADIUS - verts.append([x,y,0.0]) - Row += 1 - - #bevel - - x = sin(radians(0))*TopBevelRadius - y = cos(radians(0))*TopBevelRadius - vec1 = Mathutils.Vector([x,y,0.0]) - verts.append([x,y,0.0]) - - - x = sin(radians(60/6))*TopBevelRadius - y = cos(radians(60/6))*TopBevelRadius - vec2 = Mathutils.Vector([x,y,0.0]) - verts.append([x,y,0.0]) - - - x = sin(radians(60/3))*TopBevelRadius - y = cos(radians(60/3))*TopBevelRadius - vec3 = Mathutils.Vector([x,y,0.0]) - verts.append([x,y,0.0]) - - - x = sin(radians(60/2))*TopBevelRadius - y = cos(radians(60/2))*TopBevelRadius - vec4 = Mathutils.Vector([x,y,0.0]) - verts.append([x,y,0.0]) - Row += 1 - - #Flats - - x = tan(radians(0))*Half_Flat - dvec = vec1 - Mathutils.Vector([x,Half_Flat,0.0]) - verts.append([x,Half_Flat,-dvec.length]) - - - x = tan(radians(60/6))*Half_Flat - dvec = vec2 - Mathutils.Vector([x,Half_Flat,0.0]) - verts.append([x,Half_Flat,-dvec.length]) - - - x = tan(radians(60/3))*Half_Flat - dvec = vec3 - Mathutils.Vector([x,Half_Flat,0.0]) - Lowest_Point = -dvec.length - verts.append([x,Half_Flat,-dvec.length]) - - - x = tan(radians(60/2))*Half_Flat - dvec = vec4 - Mathutils.Vector([x,Half_Flat,0.0]) - Lowest_Point = -dvec.length - verts.append([x,Half_Flat,-dvec.length]) - Row += 1 - - #down Bits Tri - x = tan(radians(0))*Half_Flat - verts.append([x,Half_Flat,Lowest_Point]) - - x = tan(radians(60/6))*Half_Flat - verts.append([x,Half_Flat,Lowest_Point]) - - x = tan(radians(60/3))*Half_Flat - verts.append([x,Half_Flat,Lowest_Point]) - - x = tan(radians(60/2))*Half_Flat - verts.append([x,Half_Flat,Lowest_Point]) - Row += 1 - - #down Bits - - x = tan(radians(0))*Half_Flat - verts.append([x,Half_Flat,-Flat_Height]) - - x = tan(radians(60/6))*Half_Flat - verts.append([x,Half_Flat,-Flat_Height]) - - x = tan(radians(60/3))*Half_Flat - verts.append([x,Half_Flat,-Flat_Height]) - - x = tan(radians(60/2))*Half_Flat - verts.append([x,Half_Flat,-Flat_Height]) - Row += 1 - - - #under cut - - x = sin(radians(0))*Half_Flat - y = cos(radians(0))*Half_Flat - vec1 = Mathutils.Vector([x,y,0.0]) - verts.append([x,y,-Flat_Height]) - - x = sin(radians(60/6))*Half_Flat - y = cos(radians(60/6))*Half_Flat - vec2 = Mathutils.Vector([x,y,0.0]) - verts.append([x,y,-Flat_Height]) - - x = sin(radians(60/3))*Half_Flat - y = cos(radians(60/3))*Half_Flat - vec3 = Mathutils.Vector([x,y,0.0]) - verts.append([x,y,-Flat_Height]) - - x = sin(radians(60/2))*Half_Flat - y = cos(radians(60/2))*Half_Flat - vec3 = Mathutils.Vector([x,y,0.0]) - verts.append([x,y,-Flat_Height]) - Row += 1 - - #under cut down bit - x = sin(radians(0))*Half_Flat - y = cos(radians(0))*Half_Flat - vec1 = Mathutils.Vector([x,y,0.0]) - verts.append([x,y,-Flat_Height-Undercut_Height]) - - x = sin(radians(60/6))*Half_Flat - y = cos(radians(60/6))*Half_Flat - vec2 = Mathutils.Vector([x,y,0.0]) - verts.append([x,y,-Flat_Height-Undercut_Height]) - - x = sin(radians(60/3))*Half_Flat - y = cos(radians(60/3))*Half_Flat - vec3 = Mathutils.Vector([x,y,0.0]) - verts.append([x,y,-Flat_Height-Undercut_Height]) - - x = sin(radians(60/2))*Half_Flat - y = cos(radians(60/2))*Half_Flat - vec3 = Mathutils.Vector([x,y,0.0]) - verts.append([x,y,-Flat_Height-Undercut_Height]) - Row += 1 - - #under cut to Shank BEVEAL - x = sin(radians(0))*(SHANK_RADIUS+Shank_Bevel) - y = cos(radians(0))*(SHANK_RADIUS+Shank_Bevel) - vec1 = Mathutils.Vector([x,y,0.0]) - verts.append([x,y,-Flat_Height-Undercut_Height]) - - x = sin(radians(60/6))*(SHANK_RADIUS+Shank_Bevel) - y = cos(radians(60/6))*(SHANK_RADIUS+Shank_Bevel) - vec2 = Mathutils.Vector([x,y,0.0]) - verts.append([x,y,-Flat_Height-Undercut_Height]) - - x = sin(radians(60/3))*(SHANK_RADIUS+Shank_Bevel) - y = cos(radians(60/3))*(SHANK_RADIUS+Shank_Bevel) - vec3 = Mathutils.Vector([x,y,0.0]) - verts.append([x,y,-Flat_Height-Undercut_Height]) - - x = sin(radians(60/2))*(SHANK_RADIUS+Shank_Bevel) - y = cos(radians(60/2))*(SHANK_RADIUS+Shank_Bevel) - vec3 = Mathutils.Vector([x,y,0.0]) - verts.append([x,y,-Flat_Height-Undercut_Height]) - Row += 1 - - #under cut to Shank BEVEAL - x = sin(radians(0))*SHANK_RADIUS - y = cos(radians(0))*SHANK_RADIUS - vec1 = Mathutils.Vector([x,y,0.0]) - verts.append([x,y,-Flat_Height-Undercut_Height-Shank_Bevel]) - - x = sin(radians(60/6))*SHANK_RADIUS - y = cos(radians(60/6))*SHANK_RADIUS - vec2 = Mathutils.Vector([x,y,0.0]) - verts.append([x,y,-Flat_Height-Undercut_Height-Shank_Bevel]) - - x = sin(radians(60/3))*SHANK_RADIUS - y = cos(radians(60/3))*SHANK_RADIUS - vec3 = Mathutils.Vector([x,y,0.0]) - verts.append([x,y,-Flat_Height-Undercut_Height-Shank_Bevel]) - - x = sin(radians(60/2))*SHANK_RADIUS - y = cos(radians(60/2))*SHANK_RADIUS - vec3 = Mathutils.Vector([x,y,0.0]) - verts.append([x,y,-Flat_Height-Undercut_Height-Shank_Bevel]) - Row += 1 - - - #Global_Head_Height = 0 - (-HEIGHT-0.1) - faces.extend(Build_Face_List_Quads(FaceStart,3,Row - 1)) - - - Mirror_Verts,Mirror_Faces = Mirror_Verts_Faces(verts,faces,'y') - verts.extend(Mirror_Verts) - faces.extend(Mirror_Faces) - - Spin_Verts,Spin_Faces = SpinDup(verts,faces,360,6,'z') - - return Spin_Verts,Spin_Faces,0 - (-HEIGHT) - - -########################################################################################## -########################################################################################## -## Create Bolt -########################################################################################## -########################################################################################## - - - -def MakeBolt(): - global Phillips_Bit_Depth - global Philips_Bit_Dia - - global Allen_Bit_Depth - global Allen_Bit_Flat_Distance - - global Hex_Head_Height - global Hex_Head_Flat_Distance - - global Cap_Head_Dia - global Cap_Head_Height - - - global Dome_Head_Dia - - global Pan_Head_Dia - - global Shank_Dia - global Shank_Length - - global Thread_Length - global Major_Dia - global Minor_Dia - global Pitch - global Crest_Percent - global Root_Percent - - verts = [] - faces = [] - Bit_Verts = [] - Bit_Faces = [] - Bit_Dia = 0.001 - Head_Verts = [] - Head_Faces= [] - Head_Height = 0.0 - ReSized_Allen_Bit_Flat_Distance = Allen_Bit_Flat_Distance.val # set default - - - Head_Height = Hex_Head_Height.val # will be changed by the Head Functions - - if Bit_Type['ALLEN'][0].val and Head_Type['PAN'][0].val: - #need to size Allen bit if it is too big. - if Allen_Bit_Dia(Allen_Bit_Flat_Distance.val) > Max_Pan_Bit_Dia(Pan_Head_Dia.val): - ReSized_Allen_Bit_Flat_Distance = Allen_Bit_Dia_To_Flat(Max_Pan_Bit_Dia(Pan_Head_Dia.val)) * 1.05 - print "Resized Allen Bit Flat Distance to ",ReSized_Allen_Bit_Flat_Distance - - #bit Mesh - if Bit_Type['ALLEN'][0].val: - Bit_Verts,Bit_Faces,Bit_Dia = Create_Allen_Bit(ReSized_Allen_Bit_Flat_Distance,Allen_Bit_Depth.val) - - if Bit_Type['PHILLIPS'][0].val: - Bit_Verts,Bit_Faces,Bit_Dia = Create_Phillips_Bit(Philips_Bit_Dia.val,Philips_Bit_Dia.val*(0.5/1.82),Phillips_Bit_Depth.val) - - - #Head Mesh - if Head_Type['HEX'][0].val: - Head_Verts,Head_Faces,Head_Height = Create_Hex_Head(Hex_Head_Flat_Distance.val,Bit_Dia,Shank_Dia.val,Hex_Head_Height.val) - - elif Head_Type['CAP'][0].val: - Head_Verts,Head_Faces,Head_Height = Create_Cap_Head(Bit_Dia,Cap_Head_Dia.val,Shank_Dia.val,Cap_Head_Height.val,Cap_Head_Dia.val*(1.0/19.0),Cap_Head_Dia.val*(1.0/19.0)) - - elif Head_Type['DOME'][0].val: - Head_Verts,Head_Faces,Head_Height = Create_Dome_Head(Bit_Dia,Dome_Head_Dia.val,Shank_Dia.val,Hex_Head_Height.val,1,1,0) - - elif Head_Type['PAN'][0].val: - Head_Verts,Head_Faces,Head_Height = Create_Pan_Head(Bit_Dia,Pan_Head_Dia.val,Shank_Dia.val,Hex_Head_Height.val,1,1,0) - - - Face_Start = len(verts) - verts.extend(Move_Verts_Up_Z(Bit_Verts,Head_Height)) - faces.extend(Copy_Faces(Bit_Faces,Face_Start)) - - Face_Start = len(verts) - verts.extend(Move_Verts_Up_Z(Head_Verts,Head_Height)) - faces.extend(Copy_Faces(Head_Faces,Face_Start)) - - Face_Start = len(verts) - Thread_Verts,Thread_Faces,Thread_Height = Create_External_Thread(Shank_Dia.val,Shank_Length.val,Minor_Dia.val,Major_Dia.val,Pitch.val,Thread_Length.val,Crest_Percent.val,Root_Percent.val) - - verts.extend(Move_Verts_Up_Z(Thread_Verts,00)) - faces.extend(Copy_Faces(Thread_Faces,Face_Start)) - - return Move_Verts_Up_Z(verts,Thread_Height),faces - - - - - - - -########################################################################################## -########################################################################################## -## Create Internal Thread -########################################################################################## -########################################################################################## - - -def Create_Internal_Thread_Start_Verts(verts,INNER_RADIUS,OUTTER_RADIUS,PITCH,DIV,CREST_PERCENT,ROOT_PERCENT,Height_Offset): - - - Ret_Row = 0; - - Height_Offset = Height_Offset + PITCH #Move the offset up so that the verts start at - #at the correct place (Height_Start) - - Half_Pitch = float(PITCH)/2 - Height_Start = Height_Offset - PITCH - Height_Step = float(PITCH)/float(DIV) - Deg_Step = 360.0 /float(DIV) - - Crest_Height = float(PITCH) * float(CREST_PERCENT)/float(100) - Root_Height = float(PITCH) * float(ROOT_PERCENT)/float(100) - Root_to_Crest_Height = Crest_to_Root_Height = (float(PITCH) - (Crest_Height + Root_Height))/2.0 - - - Rank = float(OUTTER_RADIUS - INNER_RADIUS)/float(DIV) - for j in range(1): - - for i in range(DIV+1): - z = Height_Offset - (Height_Step*i) - if z > Height_Start: - z = Height_Start - x = sin(radians(i*Deg_Step))*OUTTER_RADIUS - y = cos(radians(i*Deg_Step))*OUTTER_RADIUS - verts.append([x,y,z]) - Height_Offset -= Crest_Height - Ret_Row += 1 - - for i in range(DIV+1): - z = Height_Offset - (Height_Step*i) - if z > Height_Start: - z = Height_Start - - x = sin(radians(i*Deg_Step))*OUTTER_RADIUS - y = cos(radians(i*Deg_Step))*OUTTER_RADIUS - verts.append([x,y,z ]) - Height_Offset -= Crest_to_Root_Height - Ret_Row += 1 - - - for i in range(DIV+1): - z = Height_Offset - (Height_Step*i) - if z > Height_Start: - z = Height_Start - - x = sin(radians(i*Deg_Step))*INNER_RADIUS - y = cos(radians(i*Deg_Step))*INNER_RADIUS - if j == 0: - x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank)) - y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank)) - verts.append([x,y,z ]) - Height_Offset -= Root_Height - Ret_Row += 1 - - for i in range(DIV+1): - z = Height_Offset - (Height_Step*i) - if z > Height_Start: - z = Height_Start - - x = sin(radians(i*Deg_Step))*INNER_RADIUS - y = cos(radians(i*Deg_Step))*INNER_RADIUS - - if j == 0: - x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank)) - y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank)) - verts.append([x,y,z ]) - Height_Offset -= Root_to_Crest_Height - Ret_Row += 1 - - return Ret_Row,Height_Offset - - -def Create_Internal_Thread_End_Verts(verts,INNER_RADIUS,OUTTER_RADIUS,PITCH,DIV,CREST_PERCENT,ROOT_PERCENT,Height_Offset): - - - Ret_Row = 0; - - Half_Pitch = float(PITCH)/2 - #Height_End = Height_Offset - PITCH - PITCH - PITCH- PITCH - PITCH- PITCH - Height_End = Height_Offset - PITCH - #Height_End = -2.1 - Height_Step = float(PITCH)/float(DIV) - Deg_Step = 360.0 /float(DIV) - - Crest_Height = float(PITCH) * float(CREST_PERCENT)/float(100) - Root_Height = float(PITCH) * float(ROOT_PERCENT)/float(100) - Root_to_Crest_Height = Crest_to_Root_Height = (float(PITCH) - (Crest_Height + Root_Height))/2.0 - - - - Rank = float(OUTTER_RADIUS - INNER_RADIUS)/float(DIV) - - Num = 0 - - for j in range(2): - - for i in range(DIV+1): - z = Height_Offset - (Height_Step*i) - if z < Height_End: - z = Height_End - x = sin(radians(i*Deg_Step))*OUTTER_RADIUS - y = cos(radians(i*Deg_Step))*OUTTER_RADIUS - verts.append([x,y,z]) - Height_Offset -= Crest_Height - Ret_Row += 1 - - - for i in range(DIV+1): - z = Height_Offset - (Height_Step*i) - if z < Height_End: - z = Height_End - - x = sin(radians(i*Deg_Step))*OUTTER_RADIUS - y = cos(radians(i*Deg_Step))*OUTTER_RADIUS - verts.append([x,y,z ]) - Height_Offset -= Crest_to_Root_Height - Ret_Row += 1 - - - for i in range(DIV+1): - z = Height_Offset - (Height_Step*i) - if z < Height_End: - z = Height_End - - x = sin(radians(i*Deg_Step))*INNER_RADIUS - y = cos(radians(i*Deg_Step))*INNER_RADIUS - if j == Num: - x = sin(radians(i*Deg_Step))*(INNER_RADIUS + (i*Rank)) - y = cos(radians(i*Deg_Step))*(INNER_RADIUS + (i*Rank)) - if j > Num: - x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS) - y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS ) - - verts.append([x,y,z ]) - Height_Offset -= Root_Height - Ret_Row += 1 - - - for i in range(DIV+1): - z = Height_Offset - (Height_Step*i) - if z < Height_End: - z = Height_End - - x = sin(radians(i*Deg_Step))*INNER_RADIUS - y = cos(radians(i*Deg_Step))*INNER_RADIUS - - if j == Num: - x = sin(radians(i*Deg_Step))*(INNER_RADIUS + (i*Rank)) - y = cos(radians(i*Deg_Step))*(INNER_RADIUS + (i*Rank)) - if j > Num: - x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS ) - y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS ) - - verts.append([x,y,z ]) - Height_Offset -= Root_to_Crest_Height - Ret_Row += 1 - - - return Ret_Row,Height_End # send back Height End as this is the lowest point - - -def Create_Internal_Thread(INNER_DIA,OUTTER_DIA,PITCH,HEIGHT,CREST_PERCENT,ROOT_PERCENT,INTERNAL = 1): - verts = [] - faces = [] - - DIV = 36 - - INNER_RADIUS = INNER_DIA/2 - OUTTER_RADIUS = OUTTER_DIA/2 - - Half_Pitch = float(PITCH)/2 - Deg_Step = 360.0 /float(DIV) - Height_Step = float(PITCH)/float(DIV) - - Num = int(round((HEIGHT- PITCH)/PITCH)) # less one pitch for the start and end that is 1/2 pitch high - - Col = 0 - Row = 0 - - - Crest_Height = float(PITCH) * float(CREST_PERCENT)/float(100) - Root_Height = float(PITCH) * float(ROOT_PERCENT)/float(100) - Root_to_Crest_Height = Crest_to_Root_Height = (float(PITCH) - (Crest_Height + Root_Height))/2.0 - - Height_Offset = 0 - FaceStart = len(verts) - - Row_Inc,Height_Offset = Create_Internal_Thread_Start_Verts(verts,INNER_RADIUS,OUTTER_RADIUS,PITCH,DIV,CREST_PERCENT,ROOT_PERCENT,Height_Offset) - Row += Row_Inc - - for j in range(Num): - - for i in range(DIV+1): - x = sin(radians(i*Deg_Step))*OUTTER_RADIUS - y = cos(radians(i*Deg_Step))*OUTTER_RADIUS - verts.append([x,y,Height_Offset - (Height_Step*i) ]) - Height_Offset -= Crest_Height - Row += 1 - - for i in range(DIV+1): - x = sin(radians(i*Deg_Step))*OUTTER_RADIUS - y = cos(radians(i*Deg_Step))*OUTTER_RADIUS - verts.append([x,y,Height_Offset - (Height_Step*i) ]) - Height_Offset -= Crest_to_Root_Height - Row += 1 - - - for i in range(DIV+1): - x = sin(radians(i*Deg_Step))*INNER_RADIUS - y = cos(radians(i*Deg_Step))*INNER_RADIUS - verts.append([x,y,Height_Offset - (Height_Step*i) ]) - Height_Offset -= Root_Height - Row += 1 - - for i in range(DIV+1): - x = sin(radians(i*Deg_Step))*INNER_RADIUS - y = cos(radians(i*Deg_Step))*INNER_RADIUS - verts.append([x,y,Height_Offset - (Height_Step*i) ]) - Height_Offset -= Root_to_Crest_Height - Row += 1 - - - Row_Inc,Height_Offset = Create_Internal_Thread_End_Verts(verts,INNER_RADIUS,OUTTER_RADIUS,PITCH,DIV,CREST_PERCENT,ROOT_PERCENT,Height_Offset) - Row += Row_Inc - - faces.extend(Build_Face_List_Quads(FaceStart,DIV,Row -1,INTERNAL)) - - return verts,faces,0 - Height_Offset - - - -########################################################################################## -########################################################################################## -## Create External Thread -########################################################################################## -########################################################################################## - - - -def Thread_Start3(verts,INNER_RADIUS,OUTTER_RADIUS,PITCH,DIV,CREST_PERCENT,ROOT_PERCENT,Height_Offset): - - - Ret_Row = 0; - - Half_Pitch = float(PITCH)/2 - Height_Start = Height_Offset - PITCH - Height_Step = float(PITCH)/float(DIV) - Deg_Step = 360.0 /float(DIV) - - Crest_Height = float(PITCH) * float(CREST_PERCENT)/float(100) - Root_Height = float(PITCH) * float(ROOT_PERCENT)/float(100) - Root_to_Crest_Height = Crest_to_Root_Height = (float(PITCH) - (Crest_Height + Root_Height))/2.0 - -#theard start - - Rank = float(OUTTER_RADIUS - INNER_RADIUS)/float(DIV) - for j in range(4): - - for i in range(DIV+1): - z = Height_Offset - (Height_Step*i) - if z > Height_Start: - z = Height_Start - x = sin(radians(i*Deg_Step))*OUTTER_RADIUS - y = cos(radians(i*Deg_Step))*OUTTER_RADIUS - verts.append([x,y,z]) - Height_Offset -= Crest_Height - Ret_Row += 1 - - for i in range(DIV+1): - z = Height_Offset - (Height_Step*i) - if z > Height_Start: - z = Height_Start - - x = sin(radians(i*Deg_Step))*OUTTER_RADIUS - y = cos(radians(i*Deg_Step))*OUTTER_RADIUS - verts.append([x,y,z ]) - Height_Offset -= Crest_to_Root_Height - Ret_Row += 1 - - - for i in range(DIV+1): - z = Height_Offset - (Height_Step*i) - if z > Height_Start: - z = Height_Start - - x = sin(radians(i*Deg_Step))*INNER_RADIUS - y = cos(radians(i*Deg_Step))*INNER_RADIUS - if j == 0: - x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank)) - y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank)) - verts.append([x,y,z ]) - Height_Offset -= Root_Height - Ret_Row += 1 - - for i in range(DIV+1): - z = Height_Offset - (Height_Step*i) - if z > Height_Start: - z = Height_Start - - x = sin(radians(i*Deg_Step))*INNER_RADIUS - y = cos(radians(i*Deg_Step))*INNER_RADIUS - - if j == 0: - x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank)) - y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank)) - verts.append([x,y,z ]) - Height_Offset -= Root_to_Crest_Height - Ret_Row += 1 - - return Ret_Row,Height_Offset - - -def Create_Shank_Verts(START_DIA,OUTTER_DIA,LENGTH,Z_LOCATION = 0): - - verts = [] - DIV = 36 - - START_RADIUS = START_DIA/2 - OUTTER_RADIUS = OUTTER_DIA/2 - - Opp = abs(START_RADIUS - OUTTER_RADIUS) - Taper_Lentgh = Opp/tan(radians(31)); - - if Taper_Lentgh > LENGTH: - Taper_Lentgh = 0 - - Stright_Length = LENGTH - Taper_Lentgh - - Deg_Step = 360.0 /float(DIV) - - Row = 0 - - Lowest_Z_Vert = 0; - - Height_Offset = Z_LOCATION - - - #ring - for i in range(DIV+1): - x = sin(radians(i*Deg_Step))*START_RADIUS - y = cos(radians(i*Deg_Step))*START_RADIUS - z = Height_Offset - 0 - verts.append([x,y,z]) - Lowest_Z_Vert = min(Lowest_Z_Vert,z) - Height_Offset -= Stright_Length - Row += 1 - - for i in range(DIV+1): - x = sin(radians(i*Deg_Step))*START_RADIUS - y = cos(radians(i*Deg_Step))*START_RADIUS - z = Height_Offset - 0 - verts.append([x,y,z]) - Lowest_Z_Vert = min(Lowest_Z_Vert,z) - Height_Offset -= Taper_Lentgh - Row += 1 - - - return verts,Row,Height_Offset - - -def Create_Thread_Start_Verts(INNER_DIA,OUTTER_DIA,PITCH,CREST_PERCENT,ROOT_PERCENT,Z_LOCATION = 0): - - verts = [] - DIV = 36 - - INNER_RADIUS = INNER_DIA/2 - OUTTER_RADIUS = OUTTER_DIA/2 - - Half_Pitch = float(PITCH)/2 - Deg_Step = 360.0 /float(DIV) - Height_Step = float(PITCH)/float(DIV) - - Row = 0 - - Lowest_Z_Vert = 0; - - Height_Offset = Z_LOCATION - - Height_Start = Height_Offset - - Crest_Height = float(PITCH) * float(CREST_PERCENT)/float(100) - Root_Height = float(PITCH) * float(ROOT_PERCENT)/float(100) - Root_to_Crest_Height = Crest_to_Root_Height = (float(PITCH) - (Crest_Height + Root_Height))/2.0 - - Rank = float(OUTTER_RADIUS - INNER_RADIUS)/float(DIV) - - Height_Offset = Z_LOCATION + PITCH - Cut_off = Z_LOCATION - - - for j in range(1): - - for i in range(DIV+1): - x = sin(radians(i*Deg_Step))*OUTTER_RADIUS - y = cos(radians(i*Deg_Step))*OUTTER_RADIUS - z = Height_Offset - (Height_Step*i) - if z > Cut_off : z = Cut_off - verts.append([x,y,z]) - Lowest_Z_Vert = min(Lowest_Z_Vert,z) - Height_Offset -= Crest_Height - Row += 1 - - for i in range(DIV+1): - x = sin(radians(i*Deg_Step))*OUTTER_RADIUS - y = cos(radians(i*Deg_Step))*OUTTER_RADIUS - z = Height_Offset - (Height_Step*i) - if z > Cut_off : z = Cut_off - verts.append([x,y,z]) - Lowest_Z_Vert = min(Lowest_Z_Vert,z) - Height_Offset -= Crest_to_Root_Height - Row += 1 - - for i in range(DIV+1): - x = sin(radians(i*Deg_Step))*OUTTER_RADIUS - y = cos(radians(i*Deg_Step))*OUTTER_RADIUS - z = Height_Offset - (Height_Step*i) - if z > Cut_off : z = Cut_off - verts.append([x,y,z]) - Lowest_Z_Vert = min(Lowest_Z_Vert,z) - Height_Offset -= Root_Height - Row += 1 - - for i in range(DIV+1): - x = sin(radians(i*Deg_Step))*OUTTER_RADIUS - y = cos(radians(i*Deg_Step))*OUTTER_RADIUS - z = Height_Offset - (Height_Step*i) - if z > Cut_off : z = Cut_off - verts.append([x,y,z]) - Lowest_Z_Vert = min(Lowest_Z_Vert,z) - Height_Offset -= Root_to_Crest_Height - Row += 1 - - - for j in range(2): - for i in range(DIV+1): - z = Height_Offset - (Height_Step*i) - if z > Height_Start: - z = Height_Start - x = sin(radians(i*Deg_Step))*OUTTER_RADIUS - y = cos(radians(i*Deg_Step))*OUTTER_RADIUS - verts.append([x,y,z]) - Lowest_Z_Vert = min(Lowest_Z_Vert,z) - Height_Offset -= Crest_Height - Row += 1 - - for i in range(DIV+1): - z = Height_Offset - (Height_Step*i) - if z > Height_Start: - z = Height_Start - - x = sin(radians(i*Deg_Step))*OUTTER_RADIUS - y = cos(radians(i*Deg_Step))*OUTTER_RADIUS - verts.append([x,y,z ]) - Lowest_Z_Vert = min(Lowest_Z_Vert,z) - Height_Offset -= Crest_to_Root_Height - Row += 1 - - - for i in range(DIV+1): - z = Height_Offset - (Height_Step*i) - if z > Height_Start: - z = Height_Start - - x = sin(radians(i*Deg_Step))*INNER_RADIUS - y = cos(radians(i*Deg_Step))*INNER_RADIUS - if j == 0: - x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank)) - y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank)) - verts.append([x,y,z ]) - Lowest_Z_Vert = min(Lowest_Z_Vert,z) - Height_Offset -= Root_Height - Row += 1 - - for i in range(DIV+1): - z = Height_Offset - (Height_Step*i) - if z > Height_Start: - z = Height_Start - - x = sin(radians(i*Deg_Step))*INNER_RADIUS - y = cos(radians(i*Deg_Step))*INNER_RADIUS - - if j == 0: - x = sin(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank)) - y = cos(radians(i*Deg_Step))*(OUTTER_RADIUS - (i*Rank)) - verts.append([x,y,z ]) - Lowest_Z_Vert = min(Lowest_Z_Vert,z) - Height_Offset -= Root_to_Crest_Height - Row += 1 - - - return verts,Row,Height_Offset - - - -def Create_Thread_Verts(INNER_DIA,OUTTER_DIA,PITCH,HEIGHT,CREST_PERCENT,ROOT_PERCENT,Z_LOCATION = 0): - verts = [] - - DIV = 36 - - INNER_RADIUS = INNER_DIA/2 - OUTTER_RADIUS = OUTTER_DIA/2 - - Half_Pitch = float(PITCH)/2 - Deg_Step = 360.0 /float(DIV) - Height_Step = float(PITCH)/float(DIV) - - NUM_OF_START_THREADS = 4.0 - NUM_OF_END_THREADS = 3.0 - Num = int((HEIGHT- ((NUM_OF_START_THREADS*PITCH) + (NUM_OF_END_THREADS*PITCH) ))/PITCH) - Row = 0 - - - Crest_Height = float(PITCH) * float(CREST_PERCENT)/float(100) - Root_Height = float(PITCH) * float(ROOT_PERCENT)/float(100) - Root_to_Crest_Height = Crest_to_Root_Height = (float(PITCH) - (Crest_Height + Root_Height))/2.0 - - - Height_Offset = Z_LOCATION - - Lowest_Z_Vert = 0; - FaceStart = len(verts) - - - for j in range(Num): - - for i in range(DIV+1): - x = sin(radians(i*Deg_Step))*OUTTER_RADIUS - y = cos(radians(i*Deg_Step))*OUTTER_RADIUS - z = Height_Offset - (Height_Step*i) - verts.append([x,y,z]) - Lowest_Z_Vert = min(Lowest_Z_Vert,z) - Height_Offset -= Crest_Height - Row += 1 - - for i in range(DIV+1): - x = sin(radians(i*Deg_Step))*OUTTER_RADIUS - y = cos(radians(i*Deg_Step))*OUTTER_RADIUS - z = Height_Offset - (Height_Step*i) - verts.append([x,y,z]) - Lowest_Z_Vert = min(Lowest_Z_Vert,z) - Height_Offset -= Crest_to_Root_Height - Row += 1 - - - for i in range(DIV+1): - x = sin(radians(i*Deg_Step))*INNER_RADIUS - y = cos(radians(i*Deg_Step))*INNER_RADIUS - z = Height_Offset - (Height_Step*i) - verts.append([x,y,z]) - Lowest_Z_Vert = min(Lowest_Z_Vert,z) - Height_Offset -= Root_Height - Row += 1 - - for i in range(DIV+1): - x = sin(radians(i*Deg_Step))*INNER_RADIUS - y = cos(radians(i*Deg_Step))*INNER_RADIUS - z = Height_Offset - (Height_Step*i) - verts.append([x,y,z]) - Lowest_Z_Vert = min(Lowest_Z_Vert,z) - Height_Offset -= Root_to_Crest_Height - Row += 1 - - return verts,Row,Height_Offset - - - -def Create_Thread_End_Verts(INNER_DIA,OUTTER_DIA,PITCH,CREST_PERCENT,ROOT_PERCENT,Z_LOCATION = 0): - verts = [] - - DIV = 36 - - INNER_RADIUS = INNER_DIA/2 - OUTTER_RADIUS = OUTTER_DIA/2 - - Half_Pitch = float(PITCH)/2 - Deg_Step = 360.0 /float(DIV) - Height_Step = float(PITCH)/float(DIV) - - Crest_Height = float(PITCH) * float(CREST_PERCENT)/float(100) - Root_Height = float(PITCH) * float(ROOT_PERCENT)/float(100) - Root_to_Crest_Height = Crest_to_Root_Height = (float(PITCH) - (Crest_Height + Root_Height))/2.0 - - Col = 0 - Row = 0 - - Height_Offset = Z_LOCATION - - Tapper_Height_Start = Height_Offset - PITCH - PITCH - - Max_Height = Tapper_Height_Start - PITCH - - Lowest_Z_Vert = 0; - - FaceStart = len(verts) - for j in range(4): - - for i in range(DIV+1): - z = Height_Offset - (Height_Step*i) - z = max(z,Max_Height) - Tapper_Radius = OUTTER_RADIUS - if z < Tapper_Height_Start: - Tapper_Radius = OUTTER_RADIUS - (Tapper_Height_Start - z) - - x = sin(radians(i*Deg_Step))*(Tapper_Radius) - y = cos(radians(i*Deg_Step))*(Tapper_Radius) - verts.append([x,y,z]) - Lowest_Z_Vert = min(Lowest_Z_Vert,z) - Height_Offset -= Crest_Height - Row += 1 - - for i in range(DIV+1): - z = Height_Offset - (Height_Step*i) - z = max(z,Max_Height) - Tapper_Radius = OUTTER_RADIUS - if z < Tapper_Height_Start: - Tapper_Radius = OUTTER_RADIUS - (Tapper_Height_Start - z) - - x = sin(radians(i*Deg_Step))*(Tapper_Radius) - y = cos(radians(i*Deg_Step))*(Tapper_Radius) - verts.append([x,y,z]) - Lowest_Z_Vert = min(Lowest_Z_Vert,z) - Height_Offset -= Crest_to_Root_Height - Row += 1 - - - for i in range(DIV+1): - z = Height_Offset - (Height_Step*i) - z = max(z,Max_Height) - Tapper_Radius = OUTTER_RADIUS - (Tapper_Height_Start - z) - if Tapper_Radius > INNER_RADIUS: - Tapper_Radius = INNER_RADIUS - - x = sin(radians(i*Deg_Step))*(Tapper_Radius) - y = cos(radians(i*Deg_Step))*(Tapper_Radius) - verts.append([x,y,z]) - Lowest_Z_Vert = min(Lowest_Z_Vert,z) - Height_Offset -= Root_Height - Row += 1 - - for i in range(DIV+1): - z = Height_Offset - (Height_Step*i) - z = max(z,Max_Height) - Tapper_Radius = OUTTER_RADIUS - (Tapper_Height_Start - z) - if Tapper_Radius > INNER_RADIUS: - Tapper_Radius = INNER_RADIUS - - x = sin(radians(i*Deg_Step))*(Tapper_Radius) - y = cos(radians(i*Deg_Step))*(Tapper_Radius) - verts.append([x,y,z]) - Lowest_Z_Vert = min(Lowest_Z_Vert,z) - Height_Offset -= Root_to_Crest_Height - Row += 1 - - return verts,Row,Height_Offset,Lowest_Z_Vert - - - - -def Create_External_Thread(SHANK_DIA,SHANK_LENGTH,INNER_DIA,OUTTER_DIA,PITCH,LENGTH,CREST_PERCENT,ROOT_PERCENT): - - verts = [] - faces = [] - - DIV = 36 - - Total_Row = 0 - Thread_Len = 0; - - Face_Start = len(verts) - Offset = 0.0; - - - Shank_Verts,Shank_Row,Offset = Create_Shank_Verts(SHANK_DIA,OUTTER_DIA,SHANK_LENGTH,Offset) - Total_Row += Shank_Row - - Thread_Start_Verts,Thread_Start_Row,Offset = Create_Thread_Start_Verts(INNER_DIA,OUTTER_DIA,PITCH,CREST_PERCENT,ROOT_PERCENT,Offset) - Total_Row += Thread_Start_Row - - - Thread_Verts,Thread_Row,Offset = Create_Thread_Verts(INNER_DIA,OUTTER_DIA,PITCH,LENGTH,CREST_PERCENT,ROOT_PERCENT,Offset) - Total_Row += Thread_Row - - - Thread_End_Verts,Thread_End_Row,Offset,Lowest_Z_Vert = Create_Thread_End_Verts(INNER_DIA,OUTTER_DIA,PITCH,CREST_PERCENT,ROOT_PERCENT,Offset ) - Total_Row += Thread_End_Row - - - verts.extend(Shank_Verts) - verts.extend(Thread_Start_Verts) - verts.extend(Thread_Verts) - verts.extend(Thread_End_Verts) - - faces.extend(Build_Face_List_Quads(Face_Start,DIV,Total_Row -1,0)) - faces.extend(Fill_Ring_Face(len(verts)-DIV,DIV,1)) - - return verts,faces,0.0 - Lowest_Z_Vert - - -########################################################################################## -########################################################################################## -## Create Nut -########################################################################################## -########################################################################################## - - -def add_Hex_Nut(FLAT,HOLE_DIA,HEIGHT): - global Global_Head_Height - global Global_NutRad - - verts = [] - faces = [] - HOLE_RADIUS = HOLE_DIA * 0.5 - Half_Flat = FLAT/2 - Half_Height = HEIGHT/2 - TopBevelRadius = Half_Flat - 0.05 - - Global_NutRad = TopBevelRadius - - Row = 0; - Lowest_Z_Vert = 0.0; - - verts.append([0.0,0.0,0.0]) - - - FaceStart = len(verts) - #inner hole - - x = sin(radians(0))*HOLE_RADIUS - y = cos(radians(0))*HOLE_RADIUS - verts.append([x,y,0.0]) - - - x = sin(radians(60/6))*HOLE_RADIUS - y = cos(radians(60/6))*HOLE_RADIUS - verts.append([x,y,0.0]) - - - x = sin(radians(60/3))*HOLE_RADIUS - y = cos(radians(60/3))*HOLE_RADIUS - verts.append([x,y,0.0]) - - - x = sin(radians(60/2))*HOLE_RADIUS - y = cos(radians(60/2))*HOLE_RADIUS - verts.append([x,y,0.0]) - Row += 1 - - #bevel - - x = sin(radians(0))*TopBevelRadius - y = cos(radians(0))*TopBevelRadius - vec1 = Mathutils.Vector([x,y,0.0]) - verts.append([x,y,0.0]) - - - x = sin(radians(60/6))*TopBevelRadius - y = cos(radians(60/6))*TopBevelRadius - vec2 = Mathutils.Vector([x,y,0.0]) - verts.append([x,y,0.0]) - - - x = sin(radians(60/3))*TopBevelRadius - y = cos(radians(60/3))*TopBevelRadius - vec3 = Mathutils.Vector([x,y,0.0]) - verts.append([x,y,0.0]) - - - x = sin(radians(60/2))*TopBevelRadius - y = cos(radians(60/2))*TopBevelRadius - vec4 = Mathutils.Vector([x,y,0.0]) - verts.append([x,y,0.0]) - Row += 1 - - #Flats - - x = tan(radians(0))*Half_Flat - dvec = vec1 - Mathutils.Vector([x,Half_Flat,0.0]) - verts.append([x,Half_Flat,-dvec.length]) - Lowest_Z_Vert = min(Lowest_Z_Vert,-dvec.length) - - - x = tan(radians(60/6))*Half_Flat - dvec = vec2 - Mathutils.Vector([x,Half_Flat,0.0]) - verts.append([x,Half_Flat,-dvec.length]) - Lowest_Z_Vert = min(Lowest_Z_Vert,-dvec.length) - - - x = tan(radians(60/3))*Half_Flat - dvec = vec3 - Mathutils.Vector([x,Half_Flat,0.0]) - Lowest_Point = -dvec.length - verts.append([x,Half_Flat,-dvec.length]) - Lowest_Z_Vert = min(Lowest_Z_Vert,-dvec.length) - - x = tan(radians(60/2))*Half_Flat - dvec = vec4 - Mathutils.Vector([x,Half_Flat,0.0]) - Lowest_Point = -dvec.length - verts.append([x,Half_Flat,-dvec.length]) - Lowest_Z_Vert = min(Lowest_Z_Vert,-dvec.length) - Row += 1 - - #down Bits Tri - x = tan(radians(0))*Half_Flat - verts.append([x,Half_Flat,Lowest_Point]) - - - x = tan(radians(60/6))*Half_Flat - verts.append([x,Half_Flat,Lowest_Point]) - - x = tan(radians(60/3))*Half_Flat - verts.append([x,Half_Flat,Lowest_Point]) - - x = tan(radians(60/2))*Half_Flat - verts.append([x,Half_Flat,Lowest_Point]) - Lowest_Z_Vert = min(Lowest_Z_Vert,Lowest_Point) - Row += 1 - - #down Bits - - x = tan(radians(0))*Half_Flat - verts.append([x,Half_Flat,-Half_Height]) - - x = tan(radians(60/6))*Half_Flat - verts.append([x,Half_Flat,-Half_Height]) - - x = tan(radians(60/3))*Half_Flat - verts.append([x,Half_Flat,-Half_Height]) - - x = tan(radians(60/2))*Half_Flat - verts.append([x,Half_Flat,-Half_Height]) - Lowest_Z_Vert = min(Lowest_Z_Vert,-Half_Height) - Row += 1 - - - - - faces.extend(Build_Face_List_Quads(FaceStart,3,Row - 1)) - - - Global_Head_Height = HEIGHT - - Tvert,tface = Mirror_Verts_Faces(verts,faces,'z',Lowest_Z_Vert) - verts.extend(Tvert) - faces.extend(tface) - - - Tvert,tface = Mirror_Verts_Faces(verts,faces,'y') - verts.extend(Tvert) - faces.extend(tface) - - S_verts,S_faces = SpinDup(verts,faces,360,6,'z') - return S_verts,S_faces,TopBevelRadius - - -def add_Nylon_Head(OUTSIDE_RADIUS,Z_LOCATION = 0): - DIV = 36 - verts = [] - faces = [] - Row = 0 - - INNER_HOLE = OUTSIDE_RADIUS - (OUTSIDE_RADIUS * (1.25/4.75)) - EDGE_THICKNESS = (OUTSIDE_RADIUS * (0.4/4.75)) - RAD1 = (OUTSIDE_RADIUS * (0.5/4.75)) - OVER_ALL_HEIGTH = (OUTSIDE_RADIUS * (2.0/4.75)) - - - FaceStart = len(verts) - - Start_Height = 0 - 3 - Height_Offset = Z_LOCATION - Lowest_Z_Vert = 0 - - x = INNER_HOLE - z = (Height_Offset - OVER_ALL_HEIGTH) + EDGE_THICKNESS - verts.append([x,0.0,z]) - Lowest_Z_Vert = min(Lowest_Z_Vert,z) - Row += 1 - - x = INNER_HOLE - z = (Height_Offset - OVER_ALL_HEIGTH) - verts.append([x,0.0,z]) - Lowest_Z_Vert = min(Lowest_Z_Vert,z) - Row += 1 - - - for i in range(180,80,-10): - x = sin(radians(i))*RAD1 - z = cos(radians(i))*RAD1 - verts.append([(OUTSIDE_RADIUS-RAD1)+x,0.0,((Height_Offset - OVER_ALL_HEIGTH)+RAD1)+z]) - Lowest_Z_Vert = min(Lowest_Z_Vert,z) - Row += 1 - - - x = OUTSIDE_RADIUS - 0 - z = Height_Offset - verts.append([x,0.0,z]) - Lowest_Z_Vert = min(Lowest_Z_Vert,z) - Row += 1 - - sVerts,sFaces = SpinDup(verts,faces,360,DIV,'z') - sVerts.extend(verts) #add the start verts to the Spin verts to complete the loop - - faces.extend(Build_Face_List_Quads(FaceStart,Row-1,DIV,1)) - - return Move_Verts_Up_Z(sVerts,0),faces,Lowest_Z_Vert - - - -def add_Nylon_Part(OUTSIDE_RADIUS,Z_LOCATION = 0): - DIV = 36 - verts = [] - faces = [] - Row = 0 - - INNER_HOLE = OUTSIDE_RADIUS - (OUTSIDE_RADIUS * (1.5/4.75)) - EDGE_THICKNESS = (OUTSIDE_RADIUS * (0.4/4.75)) - RAD1 = (OUTSIDE_RADIUS * (0.5/4.75)) - OVER_ALL_HEIGTH = (OUTSIDE_RADIUS * (2.0/4.75)) - PART_THICKNESS = OVER_ALL_HEIGTH - EDGE_THICKNESS - PART_INNER_HOLE = (OUTSIDE_RADIUS * (2.5/4.75)) - - FaceStart = len(verts) - - Start_Height = 0 - 3 - Height_Offset = Z_LOCATION - Lowest_Z_Vert = 0 - - - x = INNER_HOLE + EDGE_THICKNESS - z = Height_Offset - verts.append([x,0.0,z]) - Lowest_Z_Vert = min(Lowest_Z_Vert,z) - Row += 1 - - x = PART_INNER_HOLE - z = Height_Offset - verts.append([x,0.0,z]) - Lowest_Z_Vert = min(Lowest_Z_Vert,z) - Row += 1 - - x = PART_INNER_HOLE - z = Height_Offset - PART_THICKNESS - verts.append([x,0.0,z]) - Lowest_Z_Vert = min(Lowest_Z_Vert,z) - Row += 1 - - x = INNER_HOLE + EDGE_THICKNESS - z = Height_Offset - PART_THICKNESS - verts.append([x,0.0,z]) - Lowest_Z_Vert = min(Lowest_Z_Vert,z) - Row += 1 - - - sVerts,sFaces = SpinDup(verts,faces,360,DIV,'z') - sVerts.extend(verts) #add the start verts to the Spin verts to complete the loop - - faces.extend(Build_Face_List_Quads(FaceStart,Row-1,DIV,1)) - - return sVerts,faces,0 - Lowest_Z_Vert - - - -def Nut_Mesh(): - - verts = [] - faces = [] - Head_Verts = [] - Head_Faces= [] - - Face_Start = len(verts) - Thread_Verts,Thread_Faces,New_Nut_Height = Create_Internal_Thread(Minor_Dia.val,Major_Dia.val,Pitch.val,Hex_Nut_Height.val,Crest_Percent.val,Root_Percent.val,1) - verts.extend(Thread_Verts) - faces.extend(Copy_Faces(Thread_Faces,Face_Start)) - - Face_Start = len(verts) - Head_Verts,Head_Faces,Lock_Nut_Rad = add_Hex_Nut(Hex_Nut_Flat_Distance.val,Major_Dia.val,New_Nut_Height) - verts.extend((Head_Verts)) - faces.extend(Copy_Faces(Head_Faces,Face_Start)) - - LowZ = 0 - New_Nut_Height - - if Nut_Type['LOCK'][0].val: - Face_Start = len(verts) - Nylon_Head_Verts,Nylon_Head_faces,LowZ = add_Nylon_Head(Lock_Nut_Rad,0-New_Nut_Height) - verts.extend((Nylon_Head_Verts)) - faces.extend(Copy_Faces(Nylon_Head_faces,Face_Start)) - - Face_Start = len(verts) - Nylon_Verts,Nylon_faces,Temp_LowZ = add_Nylon_Part(Lock_Nut_Rad,0-New_Nut_Height) - verts.extend((Nylon_Verts)) - faces.extend(Copy_Faces(Nylon_faces,Face_Start)) - - - return Move_Verts_Up_Z(verts,0 - LowZ),faces - - - -################################################################################################## - - -def Create_Nut(): - - verts = [] - faces = [] - - - if Error_Check() : - return - - - verts, faces = Nut_Mesh() - Add_Mesh_To_Scene('Nut', verts, faces) - - -################################################################################################## - - -def Create_Bolt(): - verts = [] - faces = [] - - - if Error_Check() : - return - - verts, faces = MakeBolt() - Add_Mesh_To_Scene('Bolt', verts, faces) - - - -def Remove_Doubles_From_Mesh(verts,faces): - Ret_verts = [] - Ret_faces = [] - - is_editmode = Window.EditMode() # Store edit mode state - if is_editmode: Window.EditMode(0) # Python must get a mesh in object mode. - - Temp_mesh = Mesh.New('MeshTemp') # create a new mesh - - Temp_mesh.verts.extend(verts) # add vertices to mesh - Temp_mesh.faces.extend(faces) # add faces to the mesh (also adds edges) - - scn = Scene.GetCurrent() # link object to current scene - Temp_Object = scn.objects.new(Temp_mesh, 'ObjectTemp') - - Temp_mesh.remDoubles(0.010) - Temp_mesh.transform(Mathutils.Matrix([Global_Scale,0,0,0], [0,Global_Scale,0,0], [0,0,Global_Scale,0], [0,0,0, Global_Scale])) - Ret_verts[:] = [v.co for v in Temp_mesh.verts] - Ret_faces[:] = [ [v.index for v in f] for f in Temp_mesh.faces] - - #delete temp mesh - scn.objects.unlink(Temp_Object) - scn.update(0) - - if is_editmode: Window.EditMode(1) - return Ret_verts,Ret_faces - - - -def Add_Mesh_To_Scene(name, verts, faces): - - scn = Scene.GetCurrent() - if scn.lib: return - ob_act = scn.objects.active - - is_editmode = Window.EditMode() - - cursor = Window.GetCursorPos() - quat = None - - if is_editmode or Blender.Get('add_view_align'): # Aligning seems odd for editmode, but blender does it, oh well - try: quat = Blender.Mathutils.Quaternion(Window.GetViewQuat()) - except: pass - - - # Exist editmode for non mesh types - if ob_act and ob_act.type != 'Mesh' and is_editmode: - EditMode(0) - - # We are in mesh editmode - if Window.EditMode(): - me = ob_act.getData(mesh=1) - - if me.multires: - error_txt = 'Error%t|Unable to complete action with multires enabled' - Blender.Draw.PupMenu(error_txt) - print error_txt - return - - #Don't want to remove doubles and scale the existing - # mesh so we need to get the verts and the faces from - # a mesh that has been scaled. - verts,faces = Remove_Doubles_From_Mesh(verts, faces) - - # Add to existing mesh - # must exit editmode to modify mesh - Window.EditMode(0) - - me.sel = False - - vert_offset = len(me.verts) - face_offset = len(me.faces) - - - # transform the verts - txmat = Blender.Mathutils.TranslationMatrix(Blender.Mathutils.Vector(cursor)) - if quat: - mat = quat.toMatrix() - mat.invert() - mat.resize4x4() - txmat = mat * txmat - - txmat = txmat * ob_act.matrixWorld.copy().invert() - - - me.verts.extend(verts) - # Transform the verts by the cursor and view rotation - me.transform(txmat, selected_only=True) - - if vert_offset: - me.faces.extend([[i+vert_offset for i in f] for f in faces]) - else: - # Mesh with no data, unlikely - me.faces.extend(faces) - else: - - # Object mode add new - me = Mesh.New(name) - me.verts.extend(verts) - me.faces.extend(faces) - - - me.sel = True - - # Object creation and location - scn.objects.selected = [] - ob_act = scn.objects.new(me, name) - - me.remDoubles(0.010) - me.transform(Mathutils.Matrix([Global_Scale,0,0,0], [0,Global_Scale,0,0], [0,0,Global_Scale,0], [0,0,0, Global_Scale])) - - scn.objects.active = ob_act - - if quat: - mat = quat.toMatrix() - mat.invert() - mat.resize4x4() - ob_act.setMatrix(mat) - - ob_act.loc = cursor - - me.calcNormals() - - if is_editmode or Blender.Get('add_editmode'): - Window.EditMode(1) - - Blender.Redraw(-1)#Redraw all - -################################################################################################## - - - -def Load_Preset(): - - global Preset_Menu - global Shank_Dia - global Shank_Length - global Thread_Length - global Major_Dia - global Minor_Dia - global Pitch - global Crest_Percent - global Root_Percent - global Allen_Bit_Flat_Distance - global Allen_Bit_Depth - global Head_Height - global Hex_Head_Flat_Distance - global Head_Dia - global Dome_Head_Dia - global Pan_Head_Dia - global Philips_Bit_Dia - global Phillips_Bit_Depth - global Cap_Head_Height - - global Hex_Nut_Height - global Hex_Nut_Flat_Distance - - - if Preset_Menu.val == 1 : #M3 - Shank_Dia.val = 3.0 - #Pitch.val = 0.5 #Coarse - Pitch.val = 0.35 #Fine - Crest_Percent.val = 10 - Root_Percent.val = 10 - Major_Dia.val = 3.0 - Minor_Dia.val = Major_Dia.val - (1.082532 * Pitch.val) - Hex_Head_Flat_Distance.val = 5.5 - Hex_Head_Height.val = 2.0 - Cap_Head_Dia.val = 5.5 - Cap_Head_Height.val = 3.0 - Allen_Bit_Flat_Distance.val = 2.5 - Allen_Bit_Depth.val = 1.5 - Pan_Head_Dia.val = 5.6 - Dome_Head_Dia.val = 5.6 - Philips_Bit_Dia.val = Pan_Head_Dia.val*(1.82/5.6) - Phillips_Bit_Depth.val = Get_Phillips_Bit_Height(Philips_Bit_Dia.val) - Hex_Nut_Height.val = 2.4 - Hex_Nut_Flat_Distance.val = 5.5 - Thread_Length.val = 6 - Shank_Length.val = 0.0 - - - if Preset_Menu.val == 2 : #M4 - Shank_Dia.val = 4.0 - #Pitch.val = 0.7 #Coarse - Pitch.val = 0.5 #Fine - Crest_Percent.val = 10 - Root_Percent.val = 10 - Major_Dia.val = 4.0 - Minor_Dia.val = Major_Dia.val - (1.082532 * Pitch.val) - Hex_Head_Flat_Distance.val = 7.0 - Hex_Head_Height.val = 2.8 - Cap_Head_Dia.val = 7.0 - Cap_Head_Height.val = 4.0 - Allen_Bit_Flat_Distance.val = 3.0 - Allen_Bit_Depth.val = 2.0 - Pan_Head_Dia.val = 8.0 - Dome_Head_Dia.val = 8.0 - Philips_Bit_Dia.val = Pan_Head_Dia.val*(1.82/5.6) - Phillips_Bit_Depth.val = Get_Phillips_Bit_Height(Philips_Bit_Dia.val) - Hex_Nut_Height.val = 3.2 - Hex_Nut_Flat_Distance.val = 7.0 - Thread_Length.val = 8 - Shank_Length.val = 0.0 - - - if Preset_Menu.val == 3 : #M5 - Shank_Dia.val = 5.0 - #Pitch.val = 0.8 #Coarse - Pitch.val = 0.5 #Fine - Crest_Percent.val = 10 - Root_Percent.val = 10 - Major_Dia.val = 5.0 - Minor_Dia.val = Major_Dia.val - (1.082532 * Pitch.val) - Hex_Head_Flat_Distance.val = 8.0 - Hex_Head_Height.val = 3.5 - Cap_Head_Dia.val = 8.5 - Cap_Head_Height.val = 5.0 - Allen_Bit_Flat_Distance.val = 4.0 - Allen_Bit_Depth.val = 2.5 - Pan_Head_Dia.val = 9.5 - Dome_Head_Dia.val = 9.5 - Philips_Bit_Dia.val = Pan_Head_Dia.val*(1.82/5.6) - Phillips_Bit_Depth.val = Get_Phillips_Bit_Height(Philips_Bit_Dia.val) - Hex_Nut_Height.val = 4.0 - Hex_Nut_Flat_Distance.val = 8.0 - Thread_Length.val = 10 - Shank_Length.val = 0.0 - - - if Preset_Menu.val == 4 : #M6 - Shank_Dia.val = 6.0 - #Pitch.val = 1.0 #Coarse - Pitch.val = 0.75 #Fine - Crest_Percent.val = 10 - Root_Percent.val = 10 - Major_Dia.val = 6.0 - Minor_Dia.val = Major_Dia.val - (1.082532 * Pitch.val) - Hex_Head_Flat_Distance.val = 10.0 - Hex_Head_Height.val = 4.0 - Cap_Head_Dia.val = 10.0 - Cap_Head_Height.val = 6.0 - Allen_Bit_Flat_Distance.val = 5.0 - Allen_Bit_Depth.val = 3.0 - Pan_Head_Dia.val = 12.0 - Dome_Head_Dia.val = 12.0 - Philips_Bit_Dia.val = Pan_Head_Dia.val*(1.82/5.6) - Phillips_Bit_Depth.val = Get_Phillips_Bit_Height(Philips_Bit_Dia.val) - Hex_Nut_Height.val = 5.0 - Hex_Nut_Flat_Distance.val = 10.0 - Thread_Length.val = 12 - Shank_Length.val = 0.0 - - - if Preset_Menu.val == 5 : #M8 - Shank_Dia.val = 8.0 - #Pitch.val = 1.25 #Coarse - Pitch.val = 1.00 #Fine - Crest_Percent.val = 10 - Root_Percent.val = 10 - Major_Dia.val = 8.0 - Minor_Dia.val = Major_Dia.val - (1.082532 * Pitch.val) - Hex_Head_Flat_Distance.val = 13.0 - Hex_Head_Height.val = 5.3 - Cap_Head_Dia.val = 13.5 - Cap_Head_Height.val = 8.0 - Allen_Bit_Flat_Distance.val = 6.0 - Allen_Bit_Depth.val = 4.0 - Pan_Head_Dia.val = 16.0 - Dome_Head_Dia.val = 16.0 - Philips_Bit_Dia.val = Pan_Head_Dia.val*(1.82/5.6) - Phillips_Bit_Depth.val = Get_Phillips_Bit_Height(Philips_Bit_Dia.val) - Hex_Nut_Height.val = 6.5 - Hex_Nut_Flat_Distance.val = 13.0 - Thread_Length.val = 16 - Shank_Length.val = 0.0 - - if Preset_Menu.val == 6 : #M10 - Shank_Dia.val = 10.0 - #Pitch.val = 1.5 #Coarse - Pitch.val = 1.25 #Fine - Crest_Percent.val = 10 - Root_Percent.val = 10 - Major_Dia.val = 10.0 - Minor_Dia.val = Major_Dia.val - (1.082532 * Pitch.val) - Hex_Head_Flat_Distance.val = 17.0 - Hex_Head_Height.val = 6.4 - Cap_Head_Dia.val = 16.0 - Cap_Head_Height.val = 10.0 - Allen_Bit_Flat_Distance.val = 8.0 - Allen_Bit_Depth.val = 5.0 - Pan_Head_Dia.val = 20.0 - Dome_Head_Dia.val = 20.0 - Philips_Bit_Dia.val = Pan_Head_Dia.val*(1.82/5.6) - Phillips_Bit_Depth.val = Get_Phillips_Bit_Height(Philips_Bit_Dia.val) - Hex_Nut_Height.val = 8.0 - Hex_Nut_Flat_Distance.val = 17.0 - Thread_Length.val = 20 - Shank_Length.val = 0.0 - - - if Preset_Menu.val == 7 : #M12 - #Pitch.val = 1.75 #Coarse - Pitch.val = 1.50 #Fine - Crest_Percent.val = 10 - Root_Percent.val = 10 - Major_Dia.val = 12.0 - Minor_Dia.val = Major_Dia.val - (1.082532 * Pitch.val) - Hex_Head_Flat_Distance.val = 19.0 - Hex_Head_Height.val = 7.5 - Cap_Head_Dia.val = 18.5 - Cap_Head_Height.val = 12.0 - Allen_Bit_Flat_Distance.val = 10.0 - Allen_Bit_Depth.val = 6.0 - Pan_Head_Dia.val = 24.0 - Dome_Head_Dia.val = 24.0 - Philips_Bit_Dia.val = Pan_Head_Dia.val*(1.82/5.6) - Phillips_Bit_Depth.val = Get_Phillips_Bit_Height(Philips_Bit_Dia.val) - Hex_Nut_Height.val = 10.0 - Hex_Nut_Flat_Distance.val = 19.0 - Shank_Dia.val = 12.0 - Shank_Length.val = 33.0 - Thread_Length.val = 32.0 - -############################################################################################## - -def Test(): - verts = [] - faces = [] - - if Error_Check() : - return - - verts, faces = MakeBolt() - - Add_Mesh_To_Scene("TestBolt", verts,faces) - - Window.Redraw(-1) - - - - -def event(evt, val): # the function to handle input events - - if evt == Draw.ESCKEY: - Draw.Exit() # exit when user presses ESC - return - - -def button_event(evt): # the function to handle Draw Button events - - if evt == On_Exit_Click: - Draw.Exit() # exit when user presses ESC - return - - if evt == On_Test_Click: - Test() - Draw.Redraw(1) - - if evt == On_Preset_Click: - Load_Preset() - Draw.Redraw(1) - - if evt == On_Create_Click: - if Model_Type['BOLT'][0].val: - Create_Bolt() - if Model_Type['NUT'][0].val: - Create_Nut() - Draw.Redraw(1) - - elif (evt in [On_Hex_Click, On_Cap_Click,On_Dome_Click,On_Pan_Click]): - for k in Head_Type.iterkeys(): - if Head_Type[k][1]!=evt: - Head_Type[k][0].val=0 - else: - Head_Type[k][0].val=1 - Draw.Redraw(1) - - elif (evt in [On_Bit_None_Click,On_Bit_Allen_Click,On_Bit_Philips_Click]): - for k in Bit_Type.iterkeys(): - if Bit_Type[k][1]!=evt: - Bit_Type[k][0].val=0 - else: - Bit_Type[k][0].val=1 - Draw.Redraw(1) - - elif (evt in [On_Model_Bolt_Click,On_Model_Nut_Click]): - for k in Model_Type.iterkeys(): - if Model_Type[k][1]!=evt: - Model_Type[k][0].val=0 - else: - Model_Type[k][0].val=1 - Draw.Redraw(1) - - elif (evt in [On_Hex_Nut_Click,On_Lock_Nut_Click]): - for k in Nut_Type.iterkeys(): - if Nut_Type[k][1]!=evt: - Nut_Type[k][0].val=0 - else: - Nut_Type[k][0].val=1 - Draw.Redraw(1) - -##################################################################################### - - -def Draw_Border(X1,Y1,X2,Y2): # X1,Y1 = Top Left X2,Y2 = Bottom Right - INDENT = 3 - - BGL.glColor3f(1.0,1.0,1.0) - BGL.glBegin(BGL.GL_LINES) - BGL.glVertex2i(X1+INDENT,Y1-INDENT) #top line - BGL.glVertex2i(X2-INDENT,Y1-INDENT) - - BGL.glVertex2i(X1+INDENT,Y1-INDENT) #left line - BGL.glVertex2i(X1+INDENT,Y2+INDENT) - BGL.glEnd() - - BGL.glColor3f(0.5,0.5,0.5) - BGL.glBegin(BGL.GL_LINES) - BGL.glVertex2i(X2-INDENT,Y1-INDENT) #Right line - BGL.glVertex2i(X2-INDENT,Y2+INDENT) - - BGL.glVertex2i(X1+INDENT,Y2+INDENT) #bottom line - BGL.glVertex2i(X2-INDENT,Y2+INDENT) - BGL.glEnd() - - - - -def Create_Tab(X1,Y1,X2,Y2,Title,Buttons): # X1,Y1 = Top Left X2,Y2 = Bottom Right - - BIT_BUTTON_WIDTH = 55 - BIT_BUTTON_HEIGHT = 18 - TITLE_HEIGHT = 15 - INDENT = 6 - BUTTON_GAP = 4 - - BGL.glColor3f(0.75, 0.75, 0.75) - BGL.glRecti(X1,Y1,X2,Y2) - - Draw_Border(X1,Y1,X2,Y2); - - BGL.glColor3f(0.0,0.0,0.0) - BGL.glRasterPos2d(X1+INDENT,Y1 - TITLE_HEIGHT) - Draw.Text(Title) - - Button_X = X1 + INDENT - Button_Y = Y1 - TITLE_HEIGHT - BIT_BUTTON_HEIGHT - 8 - - #Nut_Number_X = Nut_Button_X - #Nut_Number_Y = Nut_Button_Y - 25 - if (Buttons != 0): - key= Buttons.keys() - for k in key: - Buttons[k][0]= Draw.Toggle(k,Buttons[k][1],Button_X,Button_Y, BIT_BUTTON_WIDTH,BIT_BUTTON_HEIGHT,Buttons[k][0].val,Buttons[k][2]) - Button_X += BIT_BUTTON_WIDTH + BUTTON_GAP - - - -def Dispaly_Title_Bar(Y_POS,CONTROL_HEIGHT): - CONTROL_WIDTH = 250 - Create_Tab(3,Y_POS,CONTROL_WIDTH,Y_POS -CONTROL_HEIGHT,"Bolt Factory V2.02",Model_Type) - - - -def Dispaly_Preset_Tab(Y_POS,CONTROL_HEIGHT): - CONTROL_WIDTH = 250 - BUTTON_Y_OFFSET = 40 - - Create_Tab(3,Y_POS,CONTROL_WIDTH,Y_POS-CONTROL_HEIGHT,"Preset",0) - - name = "M3%x1|M4%x2|M5%x3|M6%x4|M8%x5|M10%x6|M12%x7" - - global Preset_Menu - Preset_Menu = Draw.Menu(name,No_Event,9,Y_POS-BUTTON_Y_OFFSET,50,18, Preset_Menu.val, "Predefined metric screw sizes.") - Draw.Button("Apply",On_Preset_Click,150,Y_POS-BUTTON_Y_OFFSET,55,18,"Apply the preset screw sizes.") - - -def Dispaly_Bit_Tab(Y_POS,CONTROL_HEIGHT): - - CONTROL_WIDTH = 250 - NUMBER_HEIGHT = 18 - NUMBER_WIDTH = CONTROL_WIDTH -3-3-3-3-3 - - Bit_Number_X = 3+3+3 - Bit_Number_Y = Y_POS - 64 - - Create_Tab(3,Y_POS,CONTROL_WIDTH,Y_POS-CONTROL_HEIGHT,"Bit Type",Bit_Type) - - if Bit_Type['NONE'][0].val: - DoNothing = 1; - - elif Bit_Type['ALLEN'][0].val: - global Allen_Bit_Depth - Allen_Bit_Depth = Draw.Number('Bit Depth: ',No_Event,Bit_Number_X,Bit_Number_Y,NUMBER_WIDTH, NUMBER_HEIGHT,Allen_Bit_Depth.val, 0,100, '') - Bit_Number_Y -= NUMBER_HEIGHT - global Allen_Bit_Flat_Distance - Allen_Bit_Flat_Distance = Draw.Number('Flat Dist: ',No_Event,Bit_Number_X,Bit_Number_Y,NUMBER_WIDTH,NUMBER_HEIGHT,Allen_Bit_Flat_Distance.val, 0,100, '') - Bit_Number_Y -= NUMBER_HEIGHT - - elif Bit_Type['PHILLIPS'][0].val: - global Phillips_Bit_Depth - Phillips_Bit_Depth = Draw.Number('Bit Depth: ',No_Event,Bit_Number_X,Bit_Number_Y,NUMBER_WIDTH, NUMBER_HEIGHT,Phillips_Bit_Depth.val, 0,100, '') - Bit_Number_Y -= NUMBER_HEIGHT - global Philips_Bit_Dia - Philips_Bit_Dia = Draw.Number('Bit Dia: ',No_Event,Bit_Number_X,Bit_Number_Y, NUMBER_WIDTH, NUMBER_HEIGHT,Philips_Bit_Dia.val, 0,100, '') - Bit_Number_Y -= NUMBER_HEIGHT - - - -def Dispaly_Shank_Tab(Y_POS,CONTROL_HEIGHT): - - CONTROL_WIDTH = 250 - NUMBER_HEIGHT = 18 - NUMBER_WIDTH = CONTROL_WIDTH -3-3-3-3-3 - - Number_X = 3+3+3 - Number_Y_Pos = Y_POS - 40 - - Create_Tab(3,Y_POS,CONTROL_WIDTH,Y_POS-CONTROL_HEIGHT,"Shank",0) - - global Shank_Length - Shank_Length = Draw.Number('Shank Length: ',No_Event,Number_X,Number_Y_Pos,NUMBER_WIDTH,NUMBER_HEIGHT, Shank_Length.val, 0,MAX_INPUT_NUMBER, 'some text tip') - Number_Y_Pos -= NUMBER_HEIGHT - - global Shank_Dia - Shank_Dia = Draw.Number('Shank Dia: ',No_Event,Number_X,Number_Y_Pos,NUMBER_WIDTH,NUMBER_HEIGHT, Shank_Dia.val, 0,MAX_INPUT_NUMBER, 'some text tip') - Number_Y_Pos -= NUMBER_HEIGHT - - - -def Dispaly_Thread_Tab(Y_POS,CONTROL_HEIGHT): - - CONTROL_WIDTH = 250 - NUMBER_HEIGHT = 18 - NUMBER_WIDTH = CONTROL_WIDTH -3-3-3-3-3 - - - Number_X = 3+3+3 - Number_Y_Pos = Y_POS - 40 - - Create_Tab(3,Y_POS,CONTROL_WIDTH,Y_POS-CONTROL_HEIGHT,"Thread",0) - - global Thread_Length - if Model_Type['BOLT'][0].val: - Thread_Length = Draw.Number('Thread Length: ',No_Event, Number_X,Number_Y_Pos,NUMBER_WIDTH,NUMBER_HEIGHT, Thread_Length.val, 0,MAX_INPUT_NUMBER, '') - Number_Y_Pos -= NUMBER_HEIGHT - - global Major_Dia - Major_Dia = Draw.Number('Major Dia: ',No_Event,Number_X,Number_Y_Pos, NUMBER_WIDTH,NUMBER_HEIGHT, Major_Dia.val, 0,MAX_INPUT_NUMBER, '') - Number_Y_Pos -= NUMBER_HEIGHT - - global Minor_Dia - Minor_Dia = Draw.Number('Minor Dia: ',No_Event,Number_X,Number_Y_Pos, NUMBER_WIDTH,NUMBER_HEIGHT, Minor_Dia.val, 0,MAX_INPUT_NUMBER, '') - Number_Y_Pos -= NUMBER_HEIGHT - - global Pitch - Pitch = Draw.Number('Pitch: ',No_Event,Number_X,Number_Y_Pos,NUMBER_WIDTH,NUMBER_HEIGHT, Pitch.val, 0.1,7.0, '') - Number_Y_Pos -= NUMBER_HEIGHT - - global Crest_Percent - Crest_Percent = Draw.Number('Crest %: ',No_Event,Number_X,Number_Y_Pos,NUMBER_WIDTH,NUMBER_HEIGHT,Crest_Percent.val, 1,90, '') - Number_Y_Pos -= NUMBER_HEIGHT - - global Root_Percent - Root_Percent = Draw.Number('Root %: ',No_Event,Number_X,Number_Y_Pos,NUMBER_WIDTH,NUMBER_HEIGHT,Root_Percent.val, 1,90, '') - Number_Y_Pos -= NUMBER_HEIGHT - - - - -def Dispaly_Head_Tab(Y_POS,CONTROL_HEIGHT): - - CONTROL_WIDTH = 250 - NUMBER_HEIGHT = 18 - NUMBER_WIDTH = CONTROL_WIDTH -3-3-3-3-3 - - Head_Number_X = 3+3+3 - Head_Number_Y = Y_POS - 64 - - Create_Tab(3,Y_POS,CONTROL_WIDTH,Y_POS-CONTROL_HEIGHT,"Head Type",Head_Type) - - if Head_Type['HEX'][0].val: - global Hex_Head_Height - Hex_Head_Height = Draw.Number('Head Height: ',No_Event,Head_Number_X ,Head_Number_Y, NUMBER_WIDTH, NUMBER_HEIGHT,Hex_Head_Height.val, 0,100, '') - Head_Number_Y -= NUMBER_HEIGHT - global Hex_Head_Flat_Distance - Hex_Head_Flat_Distance = Draw.Number('Head Hex Flat Distance ',No_Event,Head_Number_X,Head_Number_Y,NUMBER_WIDTH, NUMBER_HEIGHT,Hex_Head_Flat_Distance.val, 0,MAX_INPUT_NUMBER, '') - Head_Number_Y -= NUMBER_HEIGHT - - elif Head_Type['CAP'][0].val: - global Cap_Head_Height - Cap_Head_Height = Draw.Number('Head Height: ',No_Event, Head_Number_X,Head_Number_Y, NUMBER_WIDTH, NUMBER_HEIGHT,Cap_Head_Height.val, 0,100, '') - Head_Number_Y -= NUMBER_HEIGHT - global Cap_Head_Dia - Cap_Head_Dia = Draw.Number('Head Dia ',No_Event,Head_Number_X,Head_Number_Y,NUMBER_WIDTH, NUMBER_HEIGHT,Cap_Head_Dia.val, 0,MAX_INPUT_NUMBER, '') - Head_Number_Y -= NUMBER_HEIGHT - - elif Head_Type['DOME'][0].val: - global Dome_Head_Dia - Dome_Head_Dia = Draw.Number(' Dome Head Dia ',No_Event,Head_Number_X,Head_Number_Y, NUMBER_WIDTH, NUMBER_HEIGHT,Dome_Head_Dia.val, 0,MAX_INPUT_NUMBER, '') - Head_Number_Y -= NUMBER_HEIGHT - - elif Head_Type['PAN'][0].val: - global Pan_Head_Dia - Pan_Head_Dia = Draw.Number('Pan Head Dia ',No_Event,Head_Number_X,Head_Number_Y, NUMBER_WIDTH, NUMBER_HEIGHT,Pan_Head_Dia.val, 0,MAX_INPUT_NUMBER, '') - Head_Number_Y -= NUMBER_HEIGHT - - - - -def Dispaly_Nut_Tab(Y_POS,CONTROL_HEIGHT): - - CONTROL_WIDTH = 250 - NUMBER_HEIGHT = 18 - NUMBER_WIDTH = CONTROL_WIDTH -3-3-3-3-3 - - Nut_Number_X = 3+3+3 - Nut_Number_Y = Y_POS - 64 - - Create_Tab(3,Y_POS,CONTROL_WIDTH,Y_POS-CONTROL_HEIGHT,"Nut Type",Nut_Type) - - #if Nut_Type['HEX'][0].val: - global Hex_Nut_Height - Hex_Nut_Height = Draw.Number('Nut Height: ',No_Event,Nut_Number_X ,Nut_Number_Y, NUMBER_WIDTH, NUMBER_HEIGHT,Hex_Nut_Height.val, 0,MAX_INPUT_NUMBER, '') - Nut_Number_Y -= NUMBER_HEIGHT - global Hex_Nut_Flat_Distance - Hex_Nut_Flat_Distance = Draw.Number('Nut Flat Distance ',No_Event,Nut_Number_X,Nut_Number_Y, NUMBER_WIDTH, NUMBER_HEIGHT,Hex_Nut_Flat_Distance.val, 0,MAX_INPUT_NUMBER, '') - Nut_Number_Y -= NUMBER_HEIGHT - - -def Dispaly_Bolt_Tab(): - - Dispaly_Shank_Tab(284,66) - Dispaly_Head_Tab(374,90) - Dispaly_Bit_Tab(464,90) - - -########################################################################################## - -def gui(): # the function to draw the screen - - CONTROL_WIDTH = 250 - - BGL.glClearColor(0.6, 0.6, 0.6, 1.0) - BGL.glClear(BGL.GL_COLOR_BUFFER_BIT) - - BGL.glColor3f(0.75, 0.75, 0.75) - BGL.glRecti(3,30,CONTROL_WIDTH,3) - - Dispaly_Title_Bar(514,50); - - if Model_Type['BOLT'][0].val: - Dispaly_Bolt_Tab(); - - if Model_Type['NUT'][0].val: - Dispaly_Nut_Tab(464,246); - - Dispaly_Thread_Tab(218,138) - - Dispaly_Preset_Tab(80,50) - - Draw.PushButton("Create",On_Create_Click,6,8,55,18,"Create Bolt") - Draw.Button("Exit",On_Exit_Click,6+55+4,8,55,18) - -# Draw.Button("Test",On_Test_Click,150,10,55,20) - -Load_Preset() -Draw.Register(gui, event, button_event) # registering the 3 callbacks diff --git a/release/scripts/wizard_curve2tree.py b/release/scripts/wizard_curve2tree.py deleted file mode 100644 index 07b45c1986f..00000000000 --- a/release/scripts/wizard_curve2tree.py +++ /dev/null @@ -1,4048 +0,0 @@ -#!BPY -""" -Name: 'Tree from Curves' -Blender: 245 -Group: 'Wizards' -Tip: 'Generate trees from curve shapes' -""" - -__author__ = "Campbell Barton" -__url__ = ['www.blender.org', 'blenderartists.org'] -__version__ = "0.1" - -__bpydoc__ = """\ - -""" - -# -------------------------------------------------------------------------- -# Tree from Curves v0.1 by Campbell Barton (AKA Ideasman42) -# -------------------------------------------------------------------------- -# ***** 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 ***** -# -------------------------------------------------------------------------- - -import bpy -import Blender -import BPyMesh -from Blender.Mathutils import Vector, Matrix, AngleBetweenVecs, LineIntersect, TranslationMatrix, ScaleMatrix, RotationMatrix, Rand -from Blender.Geometry import ClosestPointOnLine -from Blender.Noise import randuvec - -GLOBALS = {} -GLOBALS['non_bez_error'] = 0 - -''' -def debugVec(v1,v2): - sce = bpy.data.scenes.active - me = bpy.data.meshes.new() - me.verts.extend( [v1,v2] ) - me.edges.extend( [(0,1)] ) - sce.objects.new(me) -''' - -def AngleBetweenVecsSafe(a1, a2): - try: - return AngleBetweenVecs(a1,a2) - except: - return 180.0 - -# Python 2.3 has no reversed. -try: - reversed -except: - def reversed(l): return l[::-1] - -# Copied from blender, we could wrap this! - BKE_curve.c -# But probably not toooo bad in python -def forward_diff_bezier(q0, q1, q2, q3, pointlist, steps, axis): - f= float(steps) - rt0= q0 - rt1= 3.0*(q1-q0)/f - f*= f - rt2= 3.0*(q0-2.0*q1+q2)/f - f*= steps - rt3= (q3-q0+3.0*(q1-q2))/f - - q0= rt0 - q1= rt1+rt2+rt3 - q2= 2*rt2+6*rt3 - q3= 6*rt3 - if axis == None: - for a in xrange(steps+1): - pointlist[a] = q0 - q0+= q1 - q1+= q2 - q2+= q3; - - else: - for a in xrange(steps+1): - pointlist[a][axis] = q0 - q0+= q1 - q1+= q2 - q2+= q3; - -def points_from_bezier_seg(steps, pointlist, radlist, bez1_vec, bez2_vec, radius1, radius2): - - # x,y,z,axis - for ii in (0,1,2): - forward_diff_bezier(bez1_vec[1][ii], bez1_vec[2][ii], bez2_vec[0][ii], bez2_vec[1][ii], pointlist, steps, ii) - - # radius - no axis, Copied from blenders BBone roll interpolation. - forward_diff_bezier(radius1, radius1 + 0.390464*(radius2-radius1), radius2 - 0.390464*(radius2-radius1), radius2, radlist, steps, None) - - -def debug_pt(co): - Blender.Window.SetCursorPos(tuple(co)) - Blender.Window.RedrawAll() - print 'debugging', co - -def freshMesh(mesh): - ''' - Utility function to get a new mesh or clear the existing one, but dont clear everything. - ''' - if mesh: - materials = mesh.materials - mesh.verts = None - for group in mesh.getVertGroupNames(): - mesh.removeVertGroup(group) - - # Add materials back - mesh.materials = materials - else: - mesh = bpy.data.meshes.new() - - return mesh - -def getObFromName(name): - if name: - try: return bpy.data.objects[name] - except: return None - else: - return None - -def getGroupFromName(name): - if name: - try: return bpy.data.groups[name] - except: return None - else: - return None - -def closestVecIndex(vec, vecls): - best= -1 - best_dist = 100000000 - for i, vec_test in enumerate(vecls): - # Dont use yet, we may want to tho - if vec_test: # Seems odd, but use this so we can disable some verts in the list. - dist = (vec-vec_test).length - if dist < best_dist: - best = i - best_dist = dist - - return best - -IRATIONAL_NUM = 22.0/7.0 -def next_random_num(rnd): - ''' - return a random number between 0.0 and 1.0 - ''' - rnd[0] += (rnd[0] * IRATIONAL_NUM) % 1 - # prevent - if rnd[0] > 1000000: - rnd[0]-=1000000 - return rnd[0] % 1 - -eul = 0.00001 - -BRANCH_TYPE_CURVE = 0 -BRANCH_TYPE_GROWN = 1 -BRANCH_TYPE_FILL = 2 - -class tree: - def __init__(self): - self.branches_all = [] - self.branches_root = [] - self.branches_twigs = [] - self.mesh = None - self.armature = None - self.objectCurve = None - self.objectCurveMat = None - self.objectCurveIMat = None - - self.objectTwigBounds = None # use for twigs only at the moment. - self.objectTwigBoundsIMat = None - self.objectTwigBoundsMat = None - self.objectTwigBoundsMesh = None - - self.objectLeafBounds = None - self.objectLeafBoundsIMat = None - self.objectLeafBoundsMesh = None - - self.limbScale = 1.0 - - self.debug_objects = [] - self.steps = 6 # defalt, curve overwrites - - def __repr__(self): - s = '' - s += '[Tree]' - s += ' limbScale: %.6f' % self.limbScale - s += ' object: %s' % self.objectCurve - - for brch in self.branches_root: - s += str(brch) - return s - - def fromCurve(self, objectCurve): - # Now calculate the normals - self.objectCurve = objectCurve - self.objectCurveMat = objectCurve.matrixWorld - self.objectCurveIMat = self.objectCurveMat.copy().invert() - curve = objectCurve.data - self.steps = curve.resolu # curve resolution - - # Set the curve object scale - if curve.bevob: - # A bit of a hack to guess the size of the curve object if you have one. - bb = curve.bevob.boundingBox - # self.limbScale = (bb[0] - bb[7]).length / 2.825 # THIS IS GOOD WHEN NON SUBSURRFED - self.limbScale = (bb[0] - bb[7]).length / 1.8 - elif curve.ext2 != 0.0: - self.limbScale = curve.ext2 * 1.5 - - # forward_diff_bezier will fill in the blanks - # nice we can reuse these for every curve segment :) - pointlist = [[None, None, None] for i in xrange(self.steps+1)] - radlist = [ None for i in xrange(self.steps+1) ] - - for spline in curve: - - if len(spline) < 2: # Ignore single point splines - continue - - if spline.type != 1: # 0 poly, 1 bez, 4 nurbs - GLOBALS['non_bez_error'] = 1 - continue - - - brch = branch() - brch.type = BRANCH_TYPE_CURVE - - - - bez_list = list(spline) - for i in xrange(1, len(bez_list)): - bez1 = bez_list[i-1] - bez2 = bez_list[i] - vec1 = bez1.vec - vec2 = bez2.vec - if abs(vec1[1][0]-vec2[1][0]) > 0.000001 or\ - abs(vec1[1][1]-vec2[1][1]) > 0.000001 or\ - abs(vec1[1][2]-vec2[1][2]) > 0.000001: - - points_from_bezier_seg(self.steps, pointlist, radlist, vec1, vec2, bez1.radius, bez2.radius) - - # remove endpoint for all but the last - len_pointlist = len(pointlist) - if i != len(bez_list)-1: - len_pointlist -= 1 - - brch.bpoints.extend([ bpoint(brch, Vector(pointlist[ii]), Vector(), radlist[ii] * self.limbScale) for ii in xrange(len_pointlist) ]) - - # Finalize once point data is there - if brch.bpoints: - # if all points are in the same location, this is possible - self.branches_all.append(brch) - if brch.bpoints[0].radius < brch.bpoints[-1].radius: # This means we dont have to worry about curve direction. - brch.bpoints.reverse() - brch.calcData() - - # Sort from big to small, so big branches get priority - # Py 2.3 dosnt have keywords in sort - try: self.branches_all.sort( key = lambda brch: -brch.bpoints[0].radius ) - except: self.branches_all.sort( lambda brch_a, brch_b: cmp(brch_b.bpoints[0].radius, brch_a.bpoints[0].radius) ) # py2.3 - - - def closestBranchPt(self, co): - best_brch = None - best_pt = None - best_dist = 10000000000 - for brch in self.branches_all: - for pt in brch.bpoints: - # if pt.inTwigBounds: # only find twigs, give different results for leaves - l = (pt.co-co).length - if l < best_dist: - best_dist = l - best_brch = brch - best_pt = pt - return best_brch, best_pt - - def setTwigBounds(self, objectMesh): - self.objectTwigBounds = objectMesh - self.objectTwigBoundsMesh = objectMesh.getData(mesh=1) - self.objectTwigBoundsMat = objectMesh.matrixWorld.copy() - self.objectTwigBoundsIMat = self.objectTwigBoundsMat.copy().invert() - - for brch in self.branches_all: - brch.calcTwigBounds(self) - - def setLeafBounds(self, objectMesh): - self.objectLeafBounds = objectMesh - self.objectLeafBoundsMesh = objectMesh.getData(mesh=1) - self.objectLeafBoundsIMat = objectMesh.matrixWorld.copy().invert() - - def isPointInTwigBounds(self, co, selected_only=False): - return self.objectTwigBoundsMesh.pointInside(co * self.objectCurveMat * self.objectTwigBoundsIMat, selected_only) - - def isPointInLeafBounds(self, co, selected_only=False): - return self.objectLeafBoundsMesh.pointInside(co * self.objectCurveMat * self.objectLeafBoundsIMat, selected_only) - - def resetTags(self, value): - for brch in self.branches_all: - brch.tag = value - - def buildConnections( self,\ - sloppy = 1.0,\ - connect_base_trim = 1.0,\ - do_twigs = False,\ - twig_ratio = 2.0,\ - twig_select_mode = 0,\ - twig_select_factor = 0.5,\ - twig_scale = 0.8,\ - twig_scale_width = 1.0,\ - twig_random_orientation = 180,\ - twig_random_angle = 33,\ - twig_recursive=True,\ - twig_recursive_limit=3,\ - twig_ob_bounds=None,\ - twig_ob_bounds_prune=True,\ - twig_ob_bounds_prune_taper=1.0,\ - twig_placement_maxradius=10.0,\ - twig_placement_maxtwig=0,\ - twig_follow_parent=0.0,\ - twig_follow_x=0.0,\ - twig_follow_y=0.0,\ - twig_follow_z=0.0,\ - do_variation = 0,\ - variation_seed = 1,\ - variation_orientation = 0.0,\ - variation_scale = 0.0,\ - do_twigs_fill = 0,\ - twig_fill_levels=4,\ - twig_fill_rand_scale=0.0,\ - twig_fill_fork_angle_max=180.0,\ - twig_fill_radius_min=0.1,\ - twig_fill_radius_factor=0.75,\ - twig_fill_shape_type=0,\ - twig_fill_shape_rand=0.0,\ - twig_fill_shape_power=0.3,\ - ): - ''' - build tree data - fromCurve must run first - ''' - - - # Sort the branchs by the first radius, so big branchs get joins first - ### self.branches_all.sort( key = lambda brch: brch.bpoints[0].radius ) - - #self.branches_all.reverse() - - # Connect branches - for i in xrange(len(self.branches_all)): - brch_i = self.branches_all[i] - - for j in xrange(len(self.branches_all)): - if i != j: - # See if any of the points match this branch - # see if Branch 'i' is the child of branch 'j' - - brch_j = self.branches_all[j] - - if not brch_j.inParentChain(brch_i): # So we dont make cyclic tree! - - pt_best_j, dist = brch_j.findClosest(brch_i.bpoints[0].co) - - # Check its in range, allow for a bit out - hense the sloppy - # The second check in the following IF was added incase the point is close enough to the line but the midpoint is further away - # ...in this case the the resulting mesh will be adjusted to fit the join so its best to make it. - if (dist < pt_best_j.radius * sloppy) or \ - ((brch_i.bpoints[0].co - pt_best_j.co).length < pt_best_j.radius * sloppy): - - - brch_i.parent_pt = pt_best_j - pt_best_j.childCount += 1 # dont remove me - - brch_i.baseTrim(connect_base_trim) - - ''' - if pt_best_j.childCount>4: - raise "ERROR" - ''' - - # addas a member of best_j.children later when we have the geometry info available. - - #### print "Found Connection!!!", i, j - break # go onto the next branch - - """ - children = [brch_child for brch_child in pt.children] - if children: - # This pt is one side of the segment, pt.next joins this segment. - # calculate the median point the 2 segments would spanal - # Once this is done we need to adjust 2 things - # 1) move both segments up/down so they match the branches best. - # 2) set the spacing of the segments around the point. - - - # First try to get the ideal some space around each joint - # the spacing shoule be an average of - for brch.bpoints: - """ - - ''' - for brch in self.branches_all: - brch.checkPointList() - ''' - - # Variations - use for making multiple versions of the same tree. - if do_variation: - irational_num = 22.0/7.0 # use to make the random number more odd - rnd = [variation_seed] - - # Add children temporarily - for brch in self.branches_all: - if brch.parent_pt: - rnd_rot = ((next_random_num(rnd) * variation_orientation) - 0.5) * 720 - mat_orientation = RotationMatrix(rnd_rot, 3, 'r', brch.parent_pt.no) - rnd_sca = 1 + ((next_random_num(rnd)-0.5)* variation_scale ) - mat_scale = Matrix([rnd_sca,0,0],[0,rnd_sca,0],[0,0,rnd_sca]) - # mat_orientation = RotationMatrix(0, 3, 'r', brch.parent_pt.no) - brch.transformRecursive(self, mat_scale * mat_orientation, brch.parent_pt.co) - - if (do_twigs or do_twigs_fill) and twig_ob_bounds: # Only spawn twigs inside this mesh - self.setTwigBounds(twig_ob_bounds) - - # Important we so this with existing parent/child but before connecting and calculating verts. - if do_twigs: - - # scale values down - twig_random_orientation= twig_random_orientation/360.0 - twig_random_angle= twig_random_angle/360.0 - - irational_num = 22.0/7.0 # use to make the random number more odd - - if not twig_recursive: - twig_recursive_limit = 0 - - self.buildTwigs(twig_ratio, twig_select_mode, twig_select_factor) - - branches_twig_attached = [] - - # This wont add all! :/ - brch_twig_index = 0 - brch_twig_index_LAST = -1 # use this to prevent in inf loop, since its possible we cant place every branch - while brch_twig_index < len(self.branches_twigs) and brch_twig_index_LAST != brch_twig_index: - ###print "While" - ### print brch_twig_index, len(self.branches_twigs) # if this dosnt change, quit the while - - brch_twig_index_LAST = brch_twig_index - - # new twigs have been added, recalculate - branches_twig_sort = [brch.bestTwigSegment() for brch in self.branches_all] - branches_twig_sort.sort() # this will sort the branches with best braches for adding twigs to at the start of the list - - for tmp_sortval, twig_pt_index, brch_parent in branches_twig_sort: # tmp_sortval is not used. - if twig_pt_index != -1 and \ - (twig_recursive_limit == 0 or brch_parent.generation < twig_recursive_limit) and \ - (twig_placement_maxtwig == 0 or brch_parent.twig_count < twig_placement_maxtwig) and \ - brch_parent.bpoints[twig_pt_index].radius < twig_placement_maxradius: - - if brch_twig_index >= len(self.branches_twigs): - break - - brch_twig = self.branches_twigs[brch_twig_index] - parent_pt = brch_parent.bpoints[twig_pt_index] - - brch_twig.parent_pt = parent_pt - parent_pt.childCount += 1 - - # Scale this twig using this way... - # The size of the parent, scaled by the parent point's radius, - # ...compared to the parent branch;s root point radius. - # Also take into account the length of the parent branch - # Use this for pretend random numbers too. - scale = twig_scale * (parent_pt.branch.bpoints[0].radius / brch_twig.bpoints[0].radius) * (parent_pt.radius / parent_pt.branch.bpoints[0].radius) - - # Random orientation - # THIS IS NOT RANDOM - Dont be real random so we can always get re-produceale results. - if twig_random_orientation: rnd1 = (((irational_num * scale * 10000000) % 360) - 180) * twig_random_orientation - else: rnd1 = 0.0 - if twig_random_angle: rnd2 = (((irational_num * scale * 66666666) % 360) - 180) * twig_random_angle - else: rnd2 = 0.0 - - # Align this with the existing branch - angle = AngleBetweenVecsSafe(zup, parent_pt.no) - cross = zup.cross(parent_pt.no) - mat_align = RotationMatrix(angle, 3, 'r', cross) - - # Use the bend on the point to work out which way to make the branch point! - if parent_pt.prev: cross = parent_pt.no.cross(parent_pt.prev.no - parent_pt.no) - else: cross = parent_pt.no.cross(parent_pt.next.no - parent_pt.no) - - if parent_pt.branch.parent_pt: - angle = AngleBetweenVecsSafe(parent_pt.branch.parent_pt.no, parent_pt.no) - else: - # Should add a UI for this... only happens when twigs come off a root branch - angle = 66 - - mat_branch_angle = RotationMatrix(angle+rnd1, 3, 'r', cross) - mat_scale = Matrix([scale,0,0],[0,scale,0],[0,0,scale]) - - mat_orientation = RotationMatrix(rnd2, 3, 'r', parent_pt.no) - - if twig_scale_width != 1.0: - # adjust length - no radius adjusting - for pt in brch_twig.bpoints: - pt.radius *= twig_scale_width - - brch_twig.transform(mat_scale * mat_branch_angle * mat_align * mat_orientation, parent_pt.co) - - # Follow the parent normal - if twig_follow_parent or twig_follow_x or twig_follow_y or twig_follow_z: - - vecs = [] - brch_twig_len = float(len(brch_twig.bpoints)) - - if twig_follow_parent: - no = parent_pt.no.copy() * twig_follow_parent - else: - no = Vector() - - no.x += twig_follow_x - no.y += twig_follow_y - no.z += twig_follow_z - - for i, pt in enumerate(brch_twig.bpoints): - if pt.prev: - fac = i / brch_twig_len - - # Scale this value - fac_inv = 1-fac - - no_orig = pt.co - pt.prev.co - len_orig = no_orig.length - - no_new = (fac_inv * no_orig) + (fac * no) - no_new.length = len_orig - - # Mix the 2 normals - vecs.append(no_new) - - # Apply the coords - for i, pt in enumerate(brch_twig.bpoints): - if pt.prev: - pt.co = pt.prev.co + vecs[i-1] - - brch_twig.calcPointExtras() - - - # When using a bounding mesh, clip and calculate points in bounds. - #print "Attempting to trim base" - brch_twig.baseTrim(connect_base_trim) - - if twig_ob_bounds and (twig_ob_bounds_prune or twig_recursive): - brch_twig.calcTwigBounds(self) - - # we would not have been but here if the bounds were outside - if twig_ob_bounds_prune: - brch_twig.boundsTrim() - if twig_ob_bounds_prune_taper != 1.0: - # taper to a point. we could use some nice taper algo here - just linear atm. - - brch_twig.taper(twig_ob_bounds_prune_taper) - - # Make sure this dosnt mess up anything else - - brch_twig_index += 1 - - # Add to the branches - #self.branches_all.append(brch_twig) - if len(brch_twig.bpoints) > 2: - branches_twig_attached.append(brch_twig) - brch_twig.generation = brch_parent.generation + 1 - brch_parent.twig_count += 1 - else: - # Dont add the branch - parent_pt.childCount -= 1 - - # Watch This! - move 1 tab down for no recursive twigs - if twig_recursive: - self.branches_all.extend(branches_twig_attached) - branches_twig_attached = [] - - if not twig_recursive: - self.branches_all.extend(branches_twig_attached) - branches_twig_attached = [] - - - if do_twigs_fill and twig_ob_bounds: - self.twigFill(\ - twig_fill_levels,\ - twig_fill_rand_scale,\ - twig_fill_fork_angle_max,\ - twig_fill_radius_min,\ - twig_fill_radius_factor,\ - twig_fill_shape_type,\ - twig_fill_shape_rand,\ - twig_fill_shape_power,\ - ) - - ### self.branches_all.sort( key = lambda brch: brch.parent_pt != None ) - - # Calc points with dependancies - # detect circular loops!!! - TODO - #### self.resetTags(False) # NOT NEEDED NOW - done_nothing = False - while done_nothing == False: - done_nothing = True - - for brch in self.branches_all: - - if brch.tag == False and (brch.parent_pt == None or brch.parent_pt.branch.tag == True): - # Assign this to a spesific side of the parents point - # we know this is a child but not which side it should be attached to. - if brch.parent_pt: - - child_locs = [\ - brch.parent_pt.childPointUnused(0),\ - brch.parent_pt.childPointUnused(1),\ - brch.parent_pt.childPointUnused(2),\ - brch.parent_pt.childPointUnused(3)] - - best_idx = closestVecIndex(brch.bpoints[0].co, child_locs) - - # best_idx could be -1 if all childPoint's are used however we check for this and dont allow it to happen. - #if best_idx==-1: - # raise "Error"z - brch.parent_pt.children[best_idx] = brch - - for pt in brch.bpoints: - pt.calcVerts() - - done_nothing = False - brch.tag = True - - ''' - for i in xrange(len(self.branches_all)): - brch_i = self.branches_all[i] - print brch_i.myindex, - print 'tag', brch_i.tag, - print 'parent is', - if brch_i.parent_pt: - print brch_i.parent_pt.branch.myindex - else: - print None - ''' - - def optimizeSpacing(self, seg_density=0.5, seg_density_angle=20.0, seg_density_radius=0.3, joint_compression=1.0, joint_smooth=1.0): - ''' - Optimize spacing, taking branch hierarchy children into account, - can add or subdivide segments so branch joins dont look horrible. - ''' - for brch in self.branches_all: - brch.evenJointDistrobution(joint_compression) - - # Correct points that were messed up from sliding - # This happens when one point is pushed past another and the branch gets an overlaping line - - for brch in self.branches_all: - brch.fixOverlapError(joint_smooth) - - - # Collapsing - for brch in self.branches_all: - brch.collapsePoints(seg_density, seg_density_angle, seg_density_radius, joint_smooth) - - ''' - for brch in self.branches_all: - brch.branchReJoin() - ''' - - def twigFill(self_tree,\ - twig_fill_levels,\ - twig_fill_rand_scale,\ - twig_fill_fork_angle_max,\ - twig_fill_radius_min,\ - twig_fill_radius_factor,\ - twig_fill_shape_type,\ - twig_fill_shape_rand,\ - twig_fill_shape_power,\ - ): - ''' - Fill with twigs, this function uses its own class 'segment' - - twig_fill_shape_type; - 0 - no child smoothing - 1 - smooth one child - 2 - smooth both children - - ''' - - rnd = [1] - - segments_all = [] - segments_level = [] - - # Only for testing - def preview_curve(): - TWIG_WIDTH_MAX = 1.0 - TWIG_WIDTH_MIN = 0.1 - cu = bpy.data.curves["cu"] - # remove all curves - while len(cu): - del cu[0] - # return - - cu.setFlag(1) - cu.ext2 = 0.01 - - WIDTH_STEP = (TWIG_WIDTH_MAX-TWIG_WIDTH_MIN) / twig_fill_levels - - for i, seg in enumerate(segments_all): - - # 1 is the base and 2 is the tail - - p1_h2 = seg.getHeadHandle() # isnt used - p1_co = seg.headCo - p1_h1 = seg.getHeadHandle() - - p2_h1 = seg.getTailHandle() - - p2_co = seg.tailCo - p2_h2 = seg.tailCo # isnt used - - bez1 = Blender.BezTriple.New([ p1_h1[0], p1_h1[1], p1_h1[2], p1_co[0], p1_co[1], p1_co[2], p1_h2[0], p1_h2[1], p1_h2[2] ]) - bez2 = Blender.BezTriple.New([ p2_h1[0], p2_h1[1], p2_h1[2], p2_co[0], p2_co[1], p2_co[2], p2_h2[0], p2_h2[1], p2_h2[2] ]) - bez1.handleTypes = bez2.handleTypes = [Blender.BezTriple.HandleTypes.FREE, Blender.BezTriple.HandleTypes.FREE] - - bez1.radius = TWIG_WIDTH_MIN + (WIDTH_STEP * (seg.levelFromLeaf+1)) - bez2.radius = TWIG_WIDTH_MIN + (WIDTH_STEP * seg.levelFromLeaf) - - cunurb = cu.appendNurb(bez1) - cunurb.append(bez2) - - # This sucks - for bez in cunurb: - bez.handleTypes = [Blender.BezTriple.HandleTypes.FREE, Blender.BezTriple.HandleTypes.FREE] - - ### cc = sce.objects.new( cu ) - cu.update() - - - def mergeCo(parentCo, ch1Co, ch2Co, twig_fill_shape_rand): - if twig_fill_shape_rand==0.0: - return (parentCo + ch1Co + ch2Co) / 3.0 - else: - - w1 = (next_random_num(rnd)*twig_fill_shape_rand) + (1-twig_fill_shape_rand) - w2 = (next_random_num(rnd)*twig_fill_shape_rand) + (1-twig_fill_shape_rand) - w3 = (next_random_num(rnd)*twig_fill_shape_rand) + (1-twig_fill_shape_rand) - wtot = w1+w2+w3 - w1=w1/wtot - w2=w2/wtot - w3=w3/wtot - - # return (parentCo*w1 + ch1Co*w2 + ch2Co*w2) - co1 = (parentCo * w1) + (ch1Co * (1.0-w1)) - co2 = (ch1Co * w2) + (ch2Co * (1.0-w2)) - co3 = (ch2Co * w3) + (parentCo * (1.0-w3)) - - return (co1 + co2 + co3) / 3.0 - - - - class segment: - def __init__(self, level): - self.headCo = Vector() - self.tailCo = Vector() - self.parent = None - self.mergeCount = 0 - self.levelFromLeaf = level # how far we are from the leaf in levels - self.levelFromRoot = -1 # set later, assume root bone - self.children = [] - segments_all.append(self) - - if level >= len(segments_level): segments_level.append([self]) - else: segments_level[level].append(self) - - self.brothers = [] - self.no = Vector() # only endpoints have these - # self.id = len(segments_all) - - # First value is the bpoint, - # Second value is what to do - - # 0 - dont join - # 1 - Join to parent (tree point) - # 2 - join to parent, point from another fill-twig branch we just created. - - self.bpt = (None, False) # branch point for root segs only - self.new_bpt = None - - self.used = False # use this to tell if we are apart of a branch - - def sibling(self): - i = self.parent.children.index(self) - - if i == 0: - return self.parent.children[ 1 ] - elif i == 1: - return self.parent.children[ 0 ] - else: - raise "error" - - - def getHeadHandle(self): - """ - For Bezier only - """ - - if not self.parent: - return self.headCo - - if twig_fill_shape_type == 0: # no smoothing - return self.headCo - elif twig_fill_shape_type == 1: - if self.parent.children[1] == self: - return self.headCo - # 2 - always do both - - - # Y shape with curve? optional - - # we have a parent but it has no handle direction, easier - if not self.parent.parent: no = self.parent.headCo - self.parent.tailCo - else: no = self.parent.parent.headCo-self.parent.tailCo - - no.length = self.getLength() * twig_fill_shape_power - # Ok we have to account for the parents handle - return self.headCo - no - # return self.headCo - Vector(1, 0,0) - - def getTailHandle(self): - """ - For Bezier only - """ - if self.parent: - no = self.parent.headCo-self.tailCo - no.length = self.getLength() * twig_fill_shape_power - return self.tailCo + no - else: - return self.tailCo # isnt used - - def getRootSeg(self): - seg = self - while seg.parent: - seg = seg.parent - - return seg - - def calcBrothers(self): - # Run on children first - self.brothers.extend( \ - [seg_child_sibling.parent \ - for seg_child in self.children \ - for seg_child_sibling in seg_child.brothers \ - if seg_child_sibling.parent not in (self, None)]\ - ) - #print self.brothers - - def calcLevelFromRoot(self): - if self.parent: - self.levelFromRoot = self.parent.levelFromRoot + 1 - - for seg_child in self.children: - seg_child.calcLevelFromRoot() - - # Dont use for now, but scale worked, transform was never tested. - """ - def transform(self, matrix): - self.headCo = self.headCo * matrix - self.tailCo = self.tailCo * matrix - - if self.children: - ch1 = self.children[0] - ch2 = self.children[1] - - ch1.transform(matrix) - ch2.transform(matrix) - - def scale(self, scale, cent=None): - # scale = 0.9 - #matrix = Matrix([scale,0,0],[0,scale,0],[0,0,scale]).resize4x4() - #self.transform(matrix) - if cent == None: # first iter - cent = self.headCo - self.tailCo = ((self.tailCo-cent) * scale) + cent - else: - self.headCo = ((self.headCo-cent) * scale) + cent - self.tailCo = ((self.tailCo-cent) * scale) + cent - - if self.children: - self.children[0].scale(scale, cent) - self.children[1].scale(scale, cent) - """ - def recalcChildLoc(self): - if not self.children: - return - ch1 = self.children[0] - ch2 = self.children[1] - new_mid = mergeCo(self.headCo, ch1.tailCo, ch2.tailCo, twig_fill_shape_rand) - - self.tailCo[:] = ch1.headCo[:] = ch2.headCo[:] = new_mid - - ch1.recalcChildLoc() - ch2.recalcChildLoc() - - def merge(self, other): - """ - Merge other into self and make a new segment - """ - """ - seg_child = segment(self.levelFromLeaf) - self.levelFromLeaf += 1 - - seg_child.parent = other.parent = self - - # No need, recalcChildLoc sets the other coords - #self.parent.tailCo = (self.headCo + self.tailCo + other.tailCo) / 3.0 - #self.parent.headCo[:] = self.headCo - - seg_child.headCo[:] = self.headCo - - # isect = LineIntersect(self.headCo, self.tailCo, other.headCo, other.tailCo) - # new_head = (isect[0]+isect[1]) * 0.5 - - seg_child.mergeCount += 1 - other.mergeCount += 1 - - self.children.extend([ seg_child, other ]) - - self.recalcChildLoc() - - # print 'merging', self.id, other.id - """ - - #new_head = (self.headCo + self.tailCo + other.headCo + other.tailCo) * 0.25 - - self.parent = other.parent = segment(self.levelFromLeaf + 1) - - # No need, recalcChildLoc sets the self.parent.tailCo - # self.parent.tailCo = (self.headCo + self.tailCo + other.tailCo) / 3.0 - - self.parent.headCo[:] = self.headCo - self.parent.bpt = self.bpt - self.bpt = (None, False) - - # isect = LineIntersect(self.headCo, self.tailCo, other.headCo, other.tailCo) - # new_head = (isect[0]+isect[1]) * 0.5 - - self.mergeCount += 1 - other.mergeCount += 1 - - self.parent.children.extend([ self, other ]) - - self.parent.recalcChildLoc() - # print 'merging', self.id, other.id - - - def findBestMerge(self, twig_fill_fork_angle_max): - # print "findBestMerge" - if self.parent != None: - return - - best_dist = 1000000 - best_seg = None - for seg_list in (self.brothers, segments_level[self.levelFromLeaf]): - #for seg_list in (segments_level[self.levelFromLeaf],): - - # only use all other segments if we cant find any from our brothers - if seg_list == segments_level[self.levelFromLeaf] and best_seg != None: - break - - for seg in seg_list: - # 2 ppoint join - if seg != self and seg.mergeCount == 0 and seg.parent == None: - - # find the point they would join - test_dist = (self.tailCo - seg.tailCo).length - if test_dist < best_dist: - if twig_fill_fork_angle_max > 179: - best_dist = test_dist - best_seg = seg - else: - # Work out if the desired angle range is ok. - mco = mergeCo( self.headCo, self.tailCo, seg.tailCo, 0.0 ) # we dont want the random value for this test - ang = AngleBetweenVecsSafe(self.tailCo-mco, seg.tailCo-mco) - if ang < twig_fill_fork_angle_max: - best_dist = test_dist - best_seg = seg - return best_seg - - def getNormal(self): - return (self.headCo - self.tailCo).normalize() - - def getLength(self): - return (self.headCo - self.tailCo).length - """ - def toMatrix(self, LEAF_SCALE, LEAF_RANDSCALE, LEAF_RANDVEC): - if LEAF_RANDSCALE: scale = LEAF_SCALE * Rand(1.0-LEAF_RANDSCALE, 1.0+LEAF_RANDSCALE) - else: scale = LEAF_SCALE * 1.0 - - if LEAF_RANDVEC: rand_vec = Vector( Rand(-1, 1), Rand(-1, 1), Rand(-1, 1) ).normalize() * LEAF_RANDVEC - else: rand_vec = Vector( ) - - return Matrix([scale,0,0],[0,scale,0],[0,0,scale]).resize4x4() * (self.no + rand_vec).toTrackQuat('x', 'z').toMatrix().resize4x4() * TranslationMatrix(self.tailCo) - """ - def distripute_seg_on_mesh(me__, face_group): - """ - add segment endpoints - """ - - vert_segment_mapping = {} - for f in face_group: - for v in f: - i = v.index - if i not in vert_segment_mapping: - vert_segment_mapping[i] = len(segments_all) - v.sel = True - seg = segment(0) - # seg.tailCo = v.co.copy() # headCo undefined atm. - seg.tailCo = v.co.copy() * self_tree.objectTwigBoundsMat * self_tree.objectCurveIMat - - # self_tree.objectCurveMat - - seg.no = v.no - - # Build connectivity - for ed in me__.edges: - if ed.v1.sel and ed.v2.sel: - i1,i2 = ed.key - i1 = vert_segment_mapping[i1] - i2 = vert_segment_mapping[i2] - - segments_all[i1].brothers.append( segments_all[i2] ) - segments_all[i2].brothers.append( segments_all[i1] ) - - # Dont need to return anything, added when created. - - def set_seg_attach_point(seg, interior_points, twig_fill_rand_scale): - """ - Can only run on end nodes that have normals set - """ - best_dist = 1000000000.0 - best_point = None - - co = seg.tailCo - - for pt in interior_points: - # line from the point to the seg endpoint - - line_normal = seg.tailCo - pt.nextMidCo - l = line_normal.length - - - cross1 = seg.no.cross(line_normal) - cross2 = pt.no.cross(line_normal) - - angle_line = min(AngleBetweenVecsSafe(cross1, cross2), AngleBetweenVecsSafe(cross1, -cross2)) - angle_leaf_no_diff = min(AngleBetweenVecsSafe(line_normal, seg.no), AngleBetweenVecsSafe(line_normal, -seg.no)) - - # BEST_ANG=66.0 - # angle = 66.0 # min(AngleBetweenVecs(v2_co-v1_co, leaf.co-cc), AngleBetweenVecs(v1_co-v2_co, leaf.co-cc)) - # print angle, angle2 - # l = (l * ((1+abs(angle-BEST_ANG))**2 )) / (1+angle_line) - l = (1+(angle_leaf_no_diff/180)) * (1+(angle_line/180)) * l - - if l < best_dist: - best_pt = pt - best_co = pt.nextMidCo - - best_dist = l - - # twig_fill_rand_scale - seg.headCo = best_co.copy() - - if twig_fill_rand_scale: - seg_dir = seg.tailCo - seg.headCo - - seg_dir.length = seg_dir.length * ( 1.0 - (next_random_num(rnd)*twig_fill_rand_scale) ) - seg.tailCo = seg.headCo + seg_dir - - - if best_pt.childCount < 4: - # Watch this!!! adding a user before its attached and the branch is created! - # make sure if its not added later on, this isnt left added - best_pt.childCount += 1 - - # True/False denotes weather we try to connect to our parent branch - seg.bpt = (best_pt, True) - else: - seg.bpt = (best_pt, False) - - return True - - - # END Twig code, next add them - - - """ - Uses a reversed approch, fill in twigs from a bounding mesh - """ - # print "twig_fill_fork_angle_max" - # twig_fill_fork_angle_max = 60.0 # - # forward_diff_bezier will fill in the blanks - # nice we can reuse these for every curve segment :) - pointlist = [[None, None, None] for i in xrange(self_tree.steps+1)] - radlist = [ None for i in xrange(self_tree.steps+1) ] - - orig_branch_count = len(self_tree.branches_all) - - for face_group in BPyMesh.mesh2linkedFaces(self_tree.objectTwigBoundsMesh): - # Set the selection to do point inside. - self_tree.objectTwigBoundsMesh.sel = False - for f in face_group: f.sel = True - - interior_points = [] - interior_normal = Vector() - for i, brch in enumerate(self_tree.branches_all): - - if i == orig_branch_count: - break # no need to check new branches are inside us - - for pt in brch.bpoints: - if pt.next and pt.childCount < 4: # cannot attach to the last points - if self_tree.isPointInTwigBounds(pt.co, True): # selected_only - interior_points.append(pt) - interior_normal += pt.no * pt.radius - - segments_all[:] = [] - segments_level[:] = [] - - if interior_points: - # Ok, we can add twigs now - distripute_seg_on_mesh( self_tree.objectTwigBoundsMesh, face_group ) - - for seg in segments_level[0]: # only be zero segments - # Warning, increments the child count for bpoints we attach to!! - set_seg_attach_point(seg, interior_points, twig_fill_rand_scale) - - # Try sorting by other properties! this is ok for now - for segments_level_current in segments_level: - try: segments_level_current.sort( key = lambda seg: -(seg.headCo-seg.tailCo).length ) - except: segments_level_current.sort( lambda a,b: cmp((b.headCo-b.tailCo).length, (a.headCo-a.tailCo).length) ) # py2.3 - - for level in xrange(twig_fill_levels): - if len(segments_level) > level: - for seg in segments_level[level]: - # print level, seg.brothers - if seg.mergeCount == 0: - seg_merge = seg.findBestMerge(twig_fill_fork_angle_max) - if seg_merge: - seg.merge( seg_merge ) - - if len(segments_level) > level+1: - for seg in segments_level[level+1]: - seg.calcBrothers() - - for seg in segments_all: - if seg.parent == None: - seg.levelFromRoot = 0 - seg.calcLevelFromRoot() - - ''' - for i, seg in enumerate(segments_all): - # Make a branch from this data! - - brch = branch() - brch.type = BRANCH_TYPE_FILL - self_tree.branches_all.append(brch) - - # ============================= do this per bez pair - # 1 is the base and 2 is the tail - - #p1_h1 = seg.getHeadHandle() - p1_co = seg.headCo.copy() - p1_h2 = seg.getHeadHandle() # isnt used - - p2_h1 = seg.getTailHandle() - p2_co = seg.tailCo.copy() - #p2_h2 = seg.getTailHandle() # isnt used - - - bez1_vec = (None, p1_co, p1_h2) - bez2_vec = (p2_h1, p2_co, None) - - seg_root = seg.getRootSeg() - - radius_root = seg_root.bpt.radius * twig_fill_radius_factor - # Clamp so the head is never smaller then the tail - if radius_root < twig_fill_radius_min: radius_root = twig_fill_radius_min - - if seg_root.levelFromLeaf: - # print seg_root.levelFromLeaf, seg.levelFromRoot - WIDTH_STEP = (radius_root - twig_fill_radius_min) / (seg_root.levelFromLeaf+1) - - radius1 = twig_fill_radius_min + (WIDTH_STEP * (seg.levelFromLeaf+1)) - if seg.levelFromLeaf: radius2 = twig_fill_radius_min + (WIDTH_STEP * seg.levelFromLeaf) - else: radius2 = twig_fill_radius_min - else: - radius1 = radius_root - radius2 = twig_fill_radius_min - - - points_from_bezier_seg(self_tree.steps, pointlist, radlist, bez1_vec, bez2_vec, radius1, radius2) - - # dont apply self_tree.limbScale here! - its alredy done - bpoints = [ bpoint(brch, Vector(pointlist[ii]), Vector(), radlist[ii]) for ii in xrange(len(pointlist)) ] - - # remove endpoint for all but the last - #if i != len(bez_list)-1: - # bpoints.pop() - - brch.bpoints.extend(bpoints) - # ============================= - - # Finalize once point data is there - brch.calcData() - # - #preview_curve() - ''' - - for segments_level_current in reversed(segments_level): - for seg in segments_level_current: - if seg.used == False and (seg.parent == None or seg.parent.used == True): - - # The root segment for this set of links. - # seg_root_linked = seg - - brch = branch() - brch.type = BRANCH_TYPE_FILL - self_tree.branches_all.append(brch) - - # Can we attach to a real branch? - if seg.parent == None: - if seg.bpt[1]: # we can do a real join into the attach point - brch.parent_pt = seg.bpt[0] - # brch.parent_pt.childCount # this has alredy changed from - - ''' - if seg.parent: - if seg.bpt[1] == 2: - #if seg.bpt[1]: - # print "Making Connection" - if seg.bpt[0] == None: - raise "Error" - if seg.bpt[1] != 2: - print seg.bpt[1] - raise "Error" - - brch.parent_pt = seg.bpt[1] - brch.parent_pt.childCount += 1 - if brch.parent_pt.childCount > 4: - raise "Aeeae" - print "\n\nM<aking Joint!!" - ''' - - if seg.parent: - sibling = seg.sibling() - if sibling.new_bpt: - if sibling.new_bpt.childCount < 4: - brch.parent_pt = sibling.new_bpt - brch.parent_pt.childCount +=1 - - # Go down the hierarhy - is_first = True - while seg != None: - seg.used = True - - # ============================================== - - #p1_h1 = seg.getHeadHandle() - p1_co = seg.headCo.copy() - p1_h2 = seg.getHeadHandle() # isnt used - - p2_h1 = seg.getTailHandle() - p2_co = seg.tailCo.copy() - #p2_h2 = seg.getTailHandle() # isnt used - - - bez1_vec = (None, p1_co, p1_h2) - bez2_vec = (p2_h1, p2_co, None) - - seg_root = seg.getRootSeg() - - radius_root = seg_root.bpt[0].radius * twig_fill_radius_factor - # Clamp so the head is never smaller then the tail - if radius_root < twig_fill_radius_min: radius_root = twig_fill_radius_min - - if seg_root.levelFromLeaf: - # print seg_root.levelFromLeaf, seg.levelFromRoot - widthStep = (radius_root - twig_fill_radius_min) / (seg_root.levelFromLeaf+1) - - radius1 = twig_fill_radius_min + (widthStep * (seg.levelFromLeaf+1)) - if seg.levelFromLeaf: radius2 = twig_fill_radius_min + (widthStep * seg.levelFromLeaf) - else: radius2 = twig_fill_radius_min - else: - radius1 = radius_root - radius2 = twig_fill_radius_min - - points_from_bezier_seg(self_tree.steps, pointlist, radlist, bez1_vec, bez2_vec, radius1, radius2) - - - start_pointlist = 0 - - # This is like baseTrim, (remove the base points to make nice joins, accounting for radius of parent point) - # except we do it before the branch is made - - if brch.parent_pt: - while len(pointlist) - start_pointlist > 2 and (Vector(pointlist[start_pointlist]) - brch.parent_pt.co).length < (brch.parent_pt.radius*2): - start_pointlist +=1 - - if is_first and brch.parent_pt: - # We need to move the base point to a place where it looks good on the parent branch - # to do this. move the first point, then remove the following points that look horrible (double back on themself) - - no = Vector(pointlist[0]) - Vector(pointlist[-1]) - no.length = brch.parent_pt.radius*2 - pointlist[0] = list(Vector(pointlist[0]) - no) - - """ - pointlist[1][0] = (pointlist[0][0] + pointlist[2][0])/2.0 - pointlist[1][1] = (pointlist[0][1] + pointlist[2][1])/2.0 - pointlist[1][2] = (pointlist[0][2] + pointlist[2][2])/2.0 - - pointlist[2][0] = (pointlist[1][0] + pointlist[3][0])/2.0 - pointlist[2][1] = (pointlist[1][1] + pointlist[3][1])/2.0 - pointlist[2][2] = (pointlist[1][2] + pointlist[3][2])/2.0 - """ - - - # Done setting the start point - - - len_pointlist = len(pointlist) - if seg.children: - len_pointlist -= 1 - - # dont apply self_tree.limbScale here! - its alredy done - bpoints = [ bpoint(brch, Vector(pointlist[ii]), Vector(), radlist[ii]) for ii in xrange(start_pointlist, len_pointlist) ] - brch.bpoints.extend( bpoints ) - # ============================================== - - seg.new_bpt = bpoints[0] - - if seg.children: - seg = seg.children[0] - else: - seg = None - - is_first = False - - # done adding points - brch.calcData() - - - - - def buildTwigs(self, twig_ratio, twig_select_mode, twig_select_factor): - - ratio_int = int(len(self.branches_all) * twig_ratio) - if ratio_int == 0: - return - - # So we only mix branches of similar lengths - branches_sorted = self.branches_all[:] - - # Get the branches based on our selection method! - if twig_select_mode==0: - try: branches_sorted.sort( key = lambda brch: brch.getLength()) - except: branches_sorted.sort( lambda a,b: cmp(a.getLength(),a.getLength()) ) # py2.3 - elif twig_select_mode==1: - try: branches_sorted.sort( key = lambda brch:-brch.getLength()) - except: branches_sorted.sort( lambda a,b: cmp(b.getLength(), a.getLength()) ) # py2.3 - elif twig_select_mode==2: - try: branches_sorted.sort( key = lambda brch:brch.getStraightness()) - except: branches_sorted.sort( lambda a,b: cmp(a.getStraightness(), b.getStraightness())) # py2.3 - elif twig_select_mode==3: - try: branches_sorted.sort( key = lambda brch:-brch.getStraightness()) - except: branches_sorted.sort( lambda a,b: cmp(b.getStraightness(), a.getStraightness())) # py2.3 - - factor_int = int(len(self.branches_all) * twig_select_factor) - branches_sorted[factor_int:] = [] # remove the last part of the list - - try: branches_sorted.sort( key = lambda brch: len(brch.bpoints)) - except: branches_sorted.sort( lambda a,b: cmp(len(a.bpoints), len(b.bpoints)) ) # py2.3 - - branches_new = [] - #for i in xrange(ratio_int): - tot_twigs = 0 - - step = 1 - while tot_twigs < ratio_int and step < len(branches_sorted): - # Make branches from the existing - for j in xrange(step, len(branches_sorted)): - brch = branches_sorted[j-step].mixToNew(branches_sorted[j], None) - branches_new.append( brch ) - tot_twigs +=1 - - if tot_twigs > ratio_int: - break - - ### print "TwigCount", len(branches_new), ratio_int - - self.branches_twigs = branches_new - - def toDebugDisplay(self): - ''' - Should be able to call this at any time to see whats going on, dosnt work so nice ATM. - ''' - sce = bpy.data.scenes.active - - for ob in self.debug_objects: - for ob in sce.objects: - sce.objects.unlink(ob) - - for branch_index, brch in enumerate(self.branches_all): - pt_index = 0 - for pt_index, pt in enumerate(brch.bpoints): - name = '%.3d_%.3d' % (branch_index, pt_index) - if pt.next==None: - name += '_end' - if pt.prev==None: - name += '_start' - - ob = sce.objects.new('Empty', name) - self.debug_objects.append(ob) - mat = ScaleMatrix(pt.radius, 4) * TranslationMatrix(pt.co) - ob.setMatrix(mat) - ob.setDrawMode(8) # drawname - Blender.Window.RedrawAll() - - - - def toMesh(self, mesh=None,\ - do_uv=True,\ - do_uv_keep_vproportion=True,\ - do_uv_vnormalize=False,\ - do_uv_uscale=False,\ - uv_image = None,\ - uv_x_scale=1.0,\ - uv_y_scale=4.0,\ - do_uv_blend_layer= False,\ - do_cap_ends=False,\ - ): - - self.mesh = freshMesh(mesh) - totverts = 0 - - for brch in self.branches_all: - totverts += len(brch.bpoints) - - self.mesh.verts.extend( [ (0.0,0.0,0.0) ] * ((totverts * 4)+1) ) # +1 is a dummy vert - verts = self.mesh.verts - - # Assign verts to points, 4 verts for each point. - i = 1 # dummy vert, should be 0 - for brch in self.branches_all: - for pt in brch.bpoints: - pt.verts[0] = verts[i] - pt.verts[1] = verts[i+1] - pt.verts[2] = verts[i+2] - pt.verts[3] = verts[i+3] - i+=4 - - # Do this again because of collapsing - # pt.calcVerts(brch) - - # roll the tube so quads best meet up to their branches. - for brch in self.branches_all: - #for pt in brch.bpoints: - if brch.parent_pt: - - # Use temp lists for gathering an average - if brch.parent_pt.roll_angle == None: - brch.parent_pt.roll_angle = [brch.getParentQuadAngle()] - # More then 2 branches use this point, add to the list - else: - brch.parent_pt.roll_angle.append( brch.getParentQuadAngle() ) - - # average the temp lists into floats - for brch in self.branches_all: - #for pt in brch.bpoints: - if brch.parent_pt and type(brch.parent_pt.roll_angle) == list: - # print brch.parent_pt.roll_angle - f = 0.0 - for val in brch.parent_pt.roll_angle: - f += val - brch.parent_pt.roll_angle = f/len(brch.parent_pt.roll_angle) - - # set the roll of all the first segments that have parents, - # this is because their roll is set from their parent quad and we dont want them to roll away from that. - for brch in self.branches_all: - if brch.parent_pt: - # if the first joint has a child then apply half the roll - # theres no correct solition here, but this seems ok - if brch.bpoints[0].roll_angle != None: - #brch.bpoints[0].roll_angle *= 0.5 - #brch.bpoints[0].roll_angle = 0.0 - #brch.bpoints[1].roll_angle = 0.0 - brch.bpoints[0].roll_angle = 0.0 - pass - else: - # our roll was set from the branches parent and needs no changing - # set it to zero so the following functions know to interpolate. - brch.bpoints[0].roll_angle = 0.0 - #brch.bpoints[1].roll_angle = 0.0 - - ''' - Now interpolate the roll! - The method used here is a little odd. - - * first loop up the branch and set each points value to the "last defined" value and record the steps - since the last defined value - * Do the same again but backwards - - now for each undefined value we have 1 or 2 values, if its 1 its simple we just use that value - ( no interpolation ), if there are 2 then we use the offsets from each end to work out the interpolation. - - one up, one back, and another to set the values, so 3 loops all up. - ''' - #### print "scan up the branch..." - for brch in self.branches_all: - last_value = None - last_index = -1 - for i in xrange(len(brch.bpoints)): - pt = brch.bpoints[i] - if type(pt.roll_angle) in (float, int): - last_value = pt.roll_angle - last_index = i - else: - if type(last_value) in (float, int): - # Assign a list, because there may be a connecting roll value from another joint - pt.roll_angle = [(last_value, i-last_index)] - - #### print "scan down the branch..." - last_value = None - last_index = -1 - for i in xrange(len(brch.bpoints)-1, -1, -1): # same as above but reverse - pt = brch.bpoints[i] - if type(pt.roll_angle) in (float, int): - last_value = pt.roll_angle - last_index = i - else: - if last_value != None: - if type(pt.roll_angle) == list: - pt.roll_angle.append((last_value, last_index-i)) - else: - #pt.roll_angle = [(last_value, last_index-i)] - - # Dont bother assigning a list because we wont need to add to it later - pt.roll_angle = last_value - - # print "looping ,...." - ### print "assigning/interpolating roll values" - for pt in brch.bpoints: - - # print "this roll IS", pt.roll_angle - - if pt.roll_angle == None: - continue - elif type(pt.roll_angle) in (float, int): - pass - elif len(pt.roll_angle) == 1: - pt.roll_angle = pt.roll_angle[0][0] - else: - # interpolate - tot = pt.roll_angle[0][1] + pt.roll_angle[1][1] - pt.roll_angle = \ - (pt.roll_angle[0][0] * (tot - pt.roll_angle[0][1]) +\ - pt.roll_angle[1][0] * (tot - pt.roll_angle[1][1])) / tot - - #### print pt.roll_angle, 'interpolated roll' - - pt.roll(pt.roll_angle) - - # Done with temp average list. now we know the best roll for each branch. - - # mesh the data - for brch in self.branches_all: - for pt in brch.bpoints: - pt.toMesh(self.mesh) - - #faces_extend = [ face for brch in self.branches_all for pt in brch.bpoints for face in pt.faces if face ] - - - - faces_extend = [] - for brch in self.branches_all: - if brch.parent_pt: - faces_extend.extend(brch.faces) - for pt in brch.bpoints: - for face in pt.faces: - if face: - faces_extend.append(face) - - if do_cap_ends: - # TODO - UV map and image? - faces_extend.extend([ brch.bpoints[-1].verts for brch in self.branches_all ]) - - faces = self.mesh.faces - - faces.extend(faces_extend, smooth=True) - - if do_uv: - # Assign the faces back - face_index = 0 - for brch in self.branches_all: - if brch.parent_pt: - for i in (0,1,2,3): - face = brch.faces[i] = faces[face_index+i] - face_index +=4 - - for pt in brch.bpoints: - for i in (0,1,2,3): - if pt.faces[i]: - pt.faces[i] = faces[face_index] - face_index +=1 - - #if self.mesh.faces: - # self.mesh.faceUV = True - mesh.addUVLayer( 'base' ) - - # rename the uv layer - #mesh.renameUVLayer(mesh.getUVLayerNames()[0], 'base') - - for brch in self.branches_all: - - uv_x_scale_branch = 1.0 - if do_uv_uscale: - uv_x_scale_branch = 0.0 - for pt in brch.bpoints: - uv_x_scale_branch += pt.radius - - uv_x_scale_branch = uv_x_scale_branch / len(brch.bpoints) - # uv_x_scale_branch = brch.bpoints[0].radius - - if do_uv_vnormalize: - uv_normalize = [] - - def uvmap_faces(my_faces, y_val, y_size): - ''' - Accept a branch or pt faces - ''' - uv_ls = [None, None, None, None] - for i in (0,1,2,3): - if my_faces[i]: - if uv_image: - my_faces[i].image = uv_image - uvs = my_faces[i].uv - else: - # Use these for calculating blending values - uvs = [Vector(0,0), Vector(0,0), Vector(0,0), Vector(0,0)] - - uv_ls[i] = uvs - - x1 = i*0.25 * uv_x_scale * uv_x_scale_branch - x2 = (i+1)*0.25 * uv_x_scale * uv_x_scale_branch - - uvs[3].x = x1; - uvs[3].y = y_val+y_size - - uvs[0].x = x1 - uvs[0].y = y_val - - uvs[1].x = x2 - uvs[1].y = y_val - - uvs[2].x = x2 - uvs[2].y = y_val+y_size - - if do_uv_vnormalize: - uv_normalize.extend(uvs) - - return uv_ls - - # Done uvmap_faces - - y_val = 0.0 - - if brch.parent_pt: - y_size = (brch.getParentFaceCent() - brch.bpoints[0].co).length - - if do_uv_keep_vproportion: - y_size = y_size / ((brch.bpoints[0].radius + brch.parent_pt.radius)/2) * uv_y_scale - - brch.uv = uvmap_faces(brch.faces, 0.0, y_size) - - y_val += y_size - - for pt in brch.bpoints: - if pt.next: - y_size = (pt.co-pt.next.co).length - # scale the uvs by the radius, avoids stritching. - if do_uv_keep_vproportion: - y_size = y_size / pt.radius * uv_y_scale - pt.uv = uvmap_faces(pt.faces, y_val, y_size) - y_val += y_size - - - if do_uv_vnormalize and uv_normalize: - # Use yscale here so you can choose to have half the normalized value say. - vscale = (1/uv_normalize[-1].y) * uv_y_scale - for uv in uv_normalize: - uv.y *= vscale - - - # Done with UV mapping the first layer! now map the blend layers - if do_uv_blend_layer: - # Set up the blend UV layer - this is simply the blending for branch joints - mesh.addUVLayer( 'blend' ) - mesh.activeUVLayer = 'blend' - - # Set all faces to be on full blend - for f in mesh.faces: - for uv in f.uv: - uv.y = uv.x = 0.0 - - for brch in self.branches_all: - if brch.parent_pt: - for f in brch.faces: - if f: - uvs = f.uv - uvs[0].x = uvs[1].x = uvs[2].x = uvs[3].x = 0.0 - uvs[0].y = uvs[1].y = 1.0 # swap these? - same as inverting the blend - uvs[2].y = uvs[3].y = 0.0 - - # Set up the join UV layer, this overlays nice blended - mesh.addUVLayer( 'join' ) - mesh.activeUVLayer = 'join' - - # Set all faces to be on full blend - for f in mesh.faces: - for uv in f.uv: - uv.y = uv.x = 0.0 - - for brch in self.branches_all: - if brch.parent_pt: - # The UV's that this branch would cover if it was a face, - uvs_base = brch.parent_pt.uv[brch.getParentQuadIndex()] - - uvs_base_mid = Vector(0,0) - for uv in uvs_base: - uvs_base_mid += uv - - uvs_base_mid *= 0.25 - - # TODO - Factor scale and distance in here - ## uvs_base_small = [(uv+uvs_base_mid)*0.5 for uv in uvs_base] - uvs_base_small = [uvs_base_mid, uvs_base_mid, uvs_base_mid, uvs_base_mid] - - if brch.faces[0]: - f = brch.faces[0] - uvs = f.uv - uvs[0][:] = uvs_base[0] - uvs[1][:] = uvs_base[1] - - uvs[2][:] = uvs_base_small[1] - uvs[3][:] = uvs_base_small[0] - - if brch.faces[1]: - f = brch.faces[1] - uvs = f.uv - uvs[0][:] = uvs_base[1] - uvs[1][:] = uvs_base[2] - - uvs[2][:] = uvs_base_small[2] - uvs[3][:] = uvs_base_small[1] - - if brch.faces[2]: - f = brch.faces[2] - uvs = f.uv - uvs[0][:] = uvs_base[2] - uvs[1][:] = uvs_base[3] - - uvs[2][:] = uvs_base_small[3] - uvs[3][:] = uvs_base_small[2] - - if brch.faces[3]: - f = brch.faces[3] - uvs = f.uv - uvs[0][:] = uvs_base[3] - uvs[1][:] = uvs_base[0] - - uvs[2][:] = uvs_base_small[0] - uvs[3][:] = uvs_base_small[3] - - mesh.activeUVLayer = 'base' # just so people dont get worried the texture is not there - dosnt effect rendering. - else: - # no UV's - pass - - if do_cap_ends: - # de-select end points for - i = len(faces)-1 - - cap_end_face_start = len(faces) - len(self.branches_all) - - j = 0 - for i in xrange(cap_end_face_start, len(faces)): - self.branches_all[j].face_cap = faces[i] - faces[i].sel = 0 - - # default UV's are ok for now :/ - if do_uv and uv_image: - faces[i].image = uv_image - - j +=1 - - # set edge crease for capped ends. - for ed in self.mesh.edges: - if ed.v1.sel==False and ed.v2.sel==False: - ed.crease = 255 - ed.sel = True # so its all selected still - - del faces_extend - - return self.mesh - - def toLeafMesh(self, mesh_leaf,\ - leaf_branch_limit = 0.5,\ - leaf_branch_limit_rand = 0.8,\ - leaf_branch_limit_type_curve = False,\ - leaf_branch_limit_type_grow = False,\ - leaf_branch_limit_type_fill = False,\ - leaf_size = 0.5,\ - leaf_size_rand = 0.5,\ - leaf_branch_density = 0.2,\ - leaf_branch_pitch_angle = 0.0,\ - leaf_branch_pitch_rand = 0.2,\ - leaf_branch_roll_rand = 0.2,\ - leaf_branch_angle = 75.0,\ - leaf_rand_seed = 1.0,\ - leaf_object=None,\ - ): - - ''' - return a mesh with leaves seperate from the tree - - Add to the existing mesh. - ''' - - #radius = [(pt.radius for pt in self.branches_all for pt in brch.bpoints for pt in brch.bpoints] - mesh_leaf = freshMesh(mesh_leaf) - self.mesh_leaf = mesh_leaf - - # if not leaf_object: return # make the dupli anyway :/ - they can do it later or the script could complain - - if leaf_branch_limit == 1.0: - max_radius = 1000000.0 - else: - # We wont place leaves on all branches so... - # first collect stats, we want to know the average radius and total segments - totpoints = 0 - radius = 0.0 - max_radius = 0.0 - for brch in self.branches_all: - for pt in brch.bpoints: - radius += pt.radius - if pt.radius > max_radius: - max_radius = pt.radius - - #totpoints += len(brch.bpoints) - - radius_max = max_radius * leaf_branch_limit - - verts_extend = [] - faces_extend = [] - - co1 = Vector(0.0, -0.5, -0.5) - co2 = Vector(0.0, -0.5, 0.5) - co3 = Vector(0.0, 0.5, 0.5) - co4 = Vector(0.0, 0.5, -0.5) - - rnd_seed = [leaf_rand_seed] # could have seed as an input setting - - for brch in self.branches_all: - - # quick test, do we need leaves on this branch? - if leaf_branch_limit != 1.0 and brch.bpoints[-1].radius > radius_max: - continue - - - for pt in brch.bpoints: - - # For each point we can add 2 leaves - for odd_even in (0,1): - - - if (pt == brch.bpoints[-1] and odd_even==1) or \ - (leaf_branch_density != 1.0 and leaf_branch_density < next_random_num(rnd_seed)): - pass - else: - if leaf_branch_limit_rand: - # (-1 : +1) * leaf_branch_limit_rand - rnd = 1 + (((next_random_num(rnd_seed) - 0.5) * 2 ) * leaf_branch_limit_rand) - else: - rnd = 1.0 - - if pt.childCount == 0 and (leaf_branch_limit == 1.0 or (pt.radius * rnd) < radius_max): - leaf_size_tmp = leaf_size * (1.0-(next_random_num(rnd_seed)*leaf_size_rand)) - - # endpoints dont rotate - if pt.next != None: - cross1 = zup.cross(pt.no) # use this to offset the leaf later - cross2 = cross1.cross(pt.no) - if odd_even ==0: - mat_yaw = RotationMatrix(leaf_branch_angle, 3, 'r', cross2) - else: - mat_yaw = RotationMatrix(-leaf_branch_angle, 3, 'r', cross2) - - leaf_no = (pt.no * mat_yaw) - - # Correct upwards pointing from changing the yaw - #my_up = zup * mat - - # correct leaf location for branch width - cross1.length = pt.radius/2 - leaf_co = pt.co + cross1 - else: - # no correction needed, we are at the end of the branch - leaf_no = pt.no - leaf_co = pt.co - - mat = Matrix([leaf_size_tmp,0,0],[0,leaf_size_tmp,0],[0,0,leaf_size_tmp]) * leaf_no.toTrackQuat('x', 'z').toMatrix() - - # Randomize pitch and roll for the leaf - - # work out the axis to pitch and roll - cross1 = zup.cross(leaf_no) # use this to offset the leaf later - if leaf_branch_pitch_rand or leaf_branch_pitch_angle: - - angle = -leaf_branch_pitch_angle - if leaf_branch_pitch_rand: - angle += leaf_branch_pitch_rand * ((next_random_num(rnd_seed)-0.5)*360) - - mat_pitch = RotationMatrix( angle, 3, 'r', cross1) - mat = mat * mat_pitch - if leaf_branch_roll_rand: - mat_roll = RotationMatrix( leaf_branch_roll_rand * ((next_random_num(rnd_seed)-0.5)*360), 3, 'r', leaf_no) - mat = mat * mat_roll - - mat = mat.resize4x4() * TranslationMatrix(leaf_co) - - i = len(verts_extend) - faces_extend.append( (i,i+1,i+2,i+3) ) - verts_extend.extend([tuple(co4*mat), tuple(co3*mat), tuple(co2*mat), tuple(co1*mat)]) - #count += 1 - - - # setup dupli's - - self.mesh_leaf.verts.extend(verts_extend) - self.mesh_leaf.faces.extend(faces_extend) - - return self.mesh_leaf - - - def toArmature(self, ob_arm, armature): - - armature.drawType = Blender.Armature.STICK - armature.makeEditable() # enter editmode - - # Assume toMesh has run - self.armature = armature - for bonename in armature.bones.keys(): - del armature.bones[bonename] - - - group_names = [] - - for i, brch in enumerate(self.branches_all): - - # get a list of parent points to make into bones. use parents and endpoints - bpoints_parent = [pt for pt in brch.bpoints if pt.childCount or pt.prev == None or pt.next == None] - bpbone_last = None - for j in xrange(len(bpoints_parent)-1): - - # bone container class - bpoints_parent[j].bpbone = bpbone = bpoint_bone() - bpbone.name = '%i_%i' % (i,j) # must be unique - group_names.append(bpbone.name) - - bpbone.editbone = Blender.Armature.Editbone() # automatically added to the armature - self.armature.bones[bpbone.name] = bpbone.editbone - - bpbone.editbone.head = bpoints_parent[j].co - bpbone.editbone.head = bpoints_parent[j].co - bpbone.editbone.tail = bpoints_parent[j+1].co - - # parent the chain. - if bpbone_last: - bpbone.editbone.parent = bpbone_last.editbone - bpbone.editbone.options = [Blender.Armature.CONNECTED] - - bpbone_last = bpbone - - for brch in self.branches_all: - if brch.parent_pt: # We must have a parent - - # find the bone in the parent chain to use for the parent of this - parent_pt = brch.parent_pt - bpbone_parent = None - while parent_pt: - bpbone_parent = parent_pt.bpbone - if bpbone_parent: - break - - parent_pt = parent_pt.prev - - - if bpbone_parent: - brch.bpoints[0].bpbone.editbone.parent = bpbone_parent.editbone - else: # in rare cases this may not work. should be verry rare but check anyway. - print 'this is really odd... look into the bug.' - - self.armature.update() # exit editmode - - # Skin the mesh - if self.mesh: - for group in group_names: - self.mesh.addVertGroup(group) - - for brch in self.branches_all: - vertList = [] - group = '' # dummy - - for pt in brch.bpoints: - if pt.bpbone: - if vertList: - self.mesh.assignVertsToGroup(group, vertList, 1.0, Blender.Mesh.AssignModes.ADD) - - vertList = [] - group = pt.bpbone.name - - vertList.extend( [v.index for v in pt.verts] ) - - if vertList: - self.mesh.assignVertsToGroup(group, vertList, 1.0, Blender.Mesh.AssignModes.ADD) - - return self.armature - - def toAction(self, ob_arm, texture, anim_speed=1.0, anim_magnitude=1.0, anim_speed_size_scale=True, anim_offset_scale=1.0): - # Assume armature - action = ob_arm.action - if not action: - action = bpy.data.actions.new() - action.fakeUser = False # so we dont get masses of bad data - ob_arm.action = action - - # Blender.Armature.NLA.ob_arm. - pose = ob_arm.getPose() - - for pose_bone in pose.bones.values(): - pose_bone.insertKey(ob_arm, 0, [Blender.Object.Pose.ROT], True) - - # Now get all the IPO's - - ipo_dict = action.getAllChannelIpos() - # print ipo_dict - - # Sicne its per frame, it increases very fast. scale it down a bit - anim_speed = anim_speed/100 - - # When we have the same trees next to eachother, they will animate the same way unless we give each its own texture or offset settings. - # We can use the object's location as a factor - this also will have the advantage? of seeing the animation move across the tree's - # allow a scale so the difference between tree textures can be adjusted. - anim_offset = self.objectCurve.matrixWorld.translationPart() * anim_offset_scale - - anim_speed_final = anim_speed - # Assign drivers to them all - for name, ipo in ipo_dict.iteritems(): - tex_str = 'b.Texture.Get("%s")' % texture.name - - if anim_speed_size_scale: - # Adjust the speed by the bone size. - # get the point from the name. a bit ugly but works fine ;) - Just dont mess the index up! - lookup = [int(val) for val in name.split('_')] - pt = self.branches_all[ lookup[0] ].bpoints[ lookup[1] ] - anim_speed_final = anim_speed / (1+pt.radius) - - cu = ipo[Blender.Ipo.PO_QUATX] - try: cu.delBezier(0) - except: pass - cu.driver = 2 # Python expression - cu.driverExpression = '%.3f*(%s.evaluate(((b.Get("curframe")*%.3f)+%.3f,%.3f,%.3f)).w-0.5)' % (anim_magnitude, tex_str, anim_speed_final, anim_offset.x, anim_offset.y, anim_offset.z) - - cu = ipo[Blender.Ipo.PO_QUATY] - try: cu.delBezier(0) - except: pass - cu.driver = 2 # Python expression - cu.driverExpression = '%.3f*(%s.evaluate((%.3f,(b.Get("curframe")*%.3f)+%.3f,%.3f)).w-0.5)' % (anim_magnitude, tex_str, anim_offset.x, anim_speed_final, anim_offset.y, anim_offset.z) - - cu = ipo[Blender.Ipo.PO_QUATZ] - try: cu.delBezier(0) - except: pass - cu.driver = 2 # Python expression - cu.driverExpression = '%.3f*(%s.evaluate((%.3f,%.3f,(b.Get("curframe")*%.3f)+%.3f)).w-0.5)' % (anim_magnitude, tex_str, anim_offset.x, anim_offset.y, anim_speed_final, anim_offset.z) - -xyzup = Vector(1,1,1).normalize() -xup = Vector(1,0,0) -yup = Vector(0,1,0) -zup = Vector(0,0,1) - -class bpoint_bone: - def __init__(self): - self.name = None - self.editbone = None - self.blenbone = None - self.posebone = None - -class bpoint(object): - ''' The point in the middle of the branch, not the mesh points - ''' - __slots__ = 'branch', 'co', 'no', 'radius', 'vecs', 'verts', 'children', 'faces', 'uv', 'next', 'prev', 'childCount', 'bpbone', 'roll_angle', 'nextMidCo', 'childrenMidCo', 'childrenMidRadius', 'targetCos', 'inTwigBounds' - def __init__(self, brch, co, no, radius): - self.branch = brch - self.co = co - self.no = no - self.radius = radius - self.vecs = [None, None, None, None] # 4 for now - self.verts = [None, None, None, None] - self.children = [None, None, None, None] # child branches, dont fill in faces here - self.faces = [None, None, None, None] - self.uv = None # matching faces, except - UV's are calculated even if there is no face, this is so we can calculate the blending UV's - self.next = None - self.prev = None - self.childCount = 0 - self.bpbone = None # bpoint_bone instance - - # when set, This is the angle we need to roll to best face our branches - # the roll that is set may be interpolated if we are between 2 branches that need to roll. - # Set to None means that the roll will be left default (from parent) - self.roll_angle = None - - - # The location between this and the next point, - # if we want to be tricky we can try make this not just a simple - # inbetween and use the normals to have some curvature - self.nextMidCo = None - - # Similar to above, median point of all children - self.childrenMidCo = None - - # Similar as above, but for radius - self.childrenMidRadius = None - - # Target locations are used when you want to move the point to a new location but there are - # more then 1 influence, build up a list and then apply - self.targetCos = [] - - # When we use twig bounding mesh, store if this point is in the bounding mesh. Assume true unless we set to false and do the test - self.inTwigBounds = True - - def __repr__(self): - s = '' - s += '\t\tco:', self.co - s += '\t\tno:', self.no - s += '\t\tradius:', self.radius - s += '\t\tchildren:', [(child != False) for child in self.children] - return s - - def makeLast(self): - self.next = None - self.nextMidCo = None - self.childrenMidCo = None - - def setCo(self, co): - self.co[:] = co - self.calcNextMidCo() - self.calcNormal() - - if self.prev: - self.prev.calcNextMidCo() - self.prev.calcNormal() - self.prev.calcChildrenMidData() - - if self.next: - self.prev.calcNormal() - - self.calcChildrenMidData() - - - def nextLength(self): - return (self.co-self.next.co).length - def prevLength(self): - return (self.co-self.prev.co).length - - def hasOverlapError(self): - if self.prev == None: - return False - if self.next == None: - return False - ''' - # see if this point sits on the line between its siblings. - co, fac = ClosestPointOnLine(self.co, self.prev.co, self.next.co) - - if fac >= 0.0 and fac <= 1.0: - return False # no overlap, we are good - else: - return True # error, some overlap - ''' - - - # Alternate method, maybe better - ln = self.nextLength() - lp = self.prevLength() - ls = (self.prev.co-self.next.co).length - - # Are we overlapping? the length from our next or prev is longer then the next-TO-previous? - if ln>ls or lp>ls: - return True - else: - return False - - - def applyTargetLocation(self): - if not self.targetCos: - return False - elif len(self.targetCos) == 1: - co_all = self.targetCos[0] - else: - co_all = Vector() - for co in self.targetCos: - co_all += co - co_all = co_all / len(self.targetCos) - - self.targetCos[:] = [] - - length = (self.co-co_all).length - # work out if we are moving up or down - if AngleBetweenVecsSafe(self.no, self.co - co_all) < 90: - - # Up - while length > (self.co-self.prev.co).length: - if not self.collapseUp(): - break - - else: - # Down - while length*2 > (self.co-self.next.co).length: - if not self.collapseDown(): - break - - self.setCo(co_all) - - return True - - def calcNextMidCo(self): - if not self.next: - return None - - # be tricky later. - self.nextMidCo = (self.co + self.next.co) * 0.5 - - def calcNormal(self): - if self.prev == None: - self.no = (self.next.co - self.co).normalize() - elif self.next == None: - self.no = (self.co - self.prev.co).normalize() - else: - self.no = (self.next.co - self.prev.co).normalize() - - def calcChildrenMidData(self): - ''' - Calculate childrenMidCo & childrenMidRadius - This is a bit tricky, we need to find a point between this and the next, - the medium of all children, this point will be on the line between this and the next. - ''' - if not self.next: - return None - - # factor between this and the next point - radius = factor = factor_i = 0.0 - - count = 0 - for brch in self.children: - if brch: # we dont need the co at teh moment. - co, fac = ClosestPointOnLine(brch.bpoints[0].co, self.co, self.next.co) - factor_i += fac - count += 1 - - radius += brch.bpoints[0].radius - - if not count: - return - - # interpolate points - factor_i = factor_i/count - factor = 1-factor_i - - self.childrenMidCo = (self.co * factor) + (self.next.co * factor_i) - self.childrenMidRadius = radius - - #debug_pt(self.childrenMidCo) - - def getAbsVec(self, index): - # print self.vecs, index - return self.co + self.vecs[index] - - def slide(self, factor): - ''' - Slides the segment up and down using the prev and next points - ''' - self.setCo(self.slideCo(factor)) - - def slideCo(self, factor): - if self.prev == None or self.next == None or factor==0.0: - return - - if factor < 0.0: - prev_co = self.prev.co - co = self.co - - ofs = co-prev_co - ofs.length = abs(factor) - self.co - ofs - - return self.co - ofs - else: - next_co = self.next.co - co = self.co - - ofs = co-next_co - ofs.length = abs(factor) - - return self.co - ofs - - - def collapseDown(self): - ''' - Collapse the next point into this one - ''' - - # self.next.next == None check is so we dont shorten the final length of branches. - if self.next == None or self.next.next == None or self.childCount or self.next.childCount: - return False - - self.branch.bpoints.remove(self.next) - self.next = self.next.next # skip - self.next.prev = self - - # Watch this place - must update all data thats needed. roll is not calculaetd yet. - self.calcNextMidCo() - return True - - def collapseUp(self): - ''' - Collapse the previous point into this one - ''' - - # self.next.next == None check is so we dont shorten the final length of branches. - if self.prev == None or self.prev.prev == None or self.prev.childCount or self.prev.prev.childCount: - return False - - self.branch.bpoints.remove(self.prev) - self.prev = self.prev.prev # skip - self.prev.next = self - - # Watch this place - must update all data thats needed. roll is not calculaetd yet. - self.prev.calcNextMidCo() - return True - - - def smooth(self, factor, factor_joint): - ''' - Blend this point into the other 2 points - ''' - if self.next == None or self.prev == None: - return False - - if self.childCount or self.prev.childCount: - factor = factor_joint; - - if factor==0.0: - return False; - - radius = (self.next.radius + self.prev.radius)/2.0 - no = (self.next.no + self.prev.no).normalize() - - # do a line intersect to work out the best location - ''' - cos = LineIntersect( self.next.co, self.next.co+self.next.no,\ - self.prev.co, self.prev.co+self.prev.no) - if cos == None: - co = (self.prev.co + self.next.co)/2.0 - else: - co = (cos[0]+cos[1])/2.0 - ''' - # Above can give odd results every now and then - co = (self.prev.co + self.next.co)/2.0 - - # Now apply - factor_i = 1.0-factor - self.setCo(self.co*factor_i + co*factor) - self.radius = self.radius*factor_i + radius*factor - - return True - - def childPoint(self, index): - ''' - Returns the middle point for any children between this and the next edge - ''' - if self.next == None: - raise 'Error' - - if index == 0: return (self.getAbsVec(0) + self.next.getAbsVec(1)) / 2 - if index == 1: return (self.getAbsVec(1) + self.next.getAbsVec(2)) / 2 - if index == 2: return (self.getAbsVec(2) + self.next.getAbsVec(3)) / 2 - if index == 3: return (self.getAbsVec(3) + self.next.getAbsVec(0)) / 2 - - def childPointUnused(self, index): - ''' - Same as above but return None when the point is alredy used. - ''' - if self.children[index]: - return None - return self.childPoint(index) - - - def roll(self, angle): - ''' - Roll the quad about its normal - use for aurienting the sides of a quad to meet a branch that stems from here... - ''' - # debugVec(self.co, self.co + self.no) - - mat = RotationMatrix(angle, 3, 'r', self.no) - for i in xrange(4): - self.vecs[i] = self.vecs[i] * mat - - - def toMesh(self, mesh): - self.verts[0].co = self.getAbsVec(0) - self.verts[1].co = self.getAbsVec(1) - self.verts[2].co = self.getAbsVec(2) - self.verts[3].co = self.getAbsVec(3) - - if not self.next: - return - - if self.prev == None and self.branch.parent_pt: - # join from parent branch - - # which side are we of the parents quad - index = self.branch.parent_pt.children.index(self.branch) - - # collect the points we are to merge into between the parent its next point - if index==0: verts = [self.branch.parent_pt.verts[0], self.branch.parent_pt.verts[1], self.branch.parent_pt.next.verts[1], self.branch.parent_pt.next.verts[0]] - if index==1: verts = [self.branch.parent_pt.verts[1], self.branch.parent_pt.verts[2], self.branch.parent_pt.next.verts[2], self.branch.parent_pt.next.verts[1]] - if index==2: verts = [self.branch.parent_pt.verts[2], self.branch.parent_pt.verts[3], self.branch.parent_pt.next.verts[3], self.branch.parent_pt.next.verts[2]] - if index==3: verts = [self.branch.parent_pt.verts[3], self.branch.parent_pt.verts[0], self.branch.parent_pt.next.verts[0], self.branch.parent_pt.next.verts[3]] - - - # Watchout for overlapping faces! - self.branch.faces[:] =\ - [verts[0], verts[1], self.verts[1], self.verts[0]],\ - [verts[1], verts[2], self.verts[2], self.verts[1]],\ - [verts[2], verts[3], self.verts[3], self.verts[2]],\ - [verts[3], verts[0], self.verts[0], self.verts[3]] - - # normal join, parents or no parents - if not self.children[0]: self.faces[0] = [self.verts[0], self.verts[1], self.next.verts[1], self.next.verts[0]] - if not self.children[1]: self.faces[1] = [self.verts[1], self.verts[2], self.next.verts[2], self.next.verts[1]] - if not self.children[2]: self.faces[2] = [self.verts[2], self.verts[3], self.next.verts[3], self.next.verts[2]] - if not self.children[3]: self.faces[3] = [self.verts[3], self.verts[0], self.next.verts[0], self.next.verts[3]] - - def calcVerts(self): - if self.prev == None: - if self.branch.parent_pt: - cross = self.no.cross(self.branch.parent_pt.no) * RotationMatrix(-45, 3, 'r', self.no) - else: - # parentless branch - for best results get a cross thats not the same as the normal, in rare cases this happens. - - # Was just doing - # cross = zup - # which works most of the time, but no verticle lines - - if AngleBetweenVecsSafe(self.no, zup) > 1.0: cross = zup - elif AngleBetweenVecsSafe(self.no, yup) > 1.0: cross = yup - else: cross = xup - - else: - cross = self.prev.vecs[0].cross(self.no) - - self.vecs[0] = self.no.cross(cross) - self.vecs[0].length = abs(self.radius) - mat = RotationMatrix(90, 3, 'r', self.no) - self.vecs[1] = self.vecs[0] * mat - self.vecs[2] = self.vecs[1] * mat - self.vecs[3] = self.vecs[2] * mat - - def hasChildren(self): - ''' - Use .childCount where possible, this does the real check - ''' - if self.children.count(None) == 4: - return False - else: - return True - -class branch: - def __init__(self): - self.bpoints = [] - self.parent_pt = None - self.tag = False # have we calculated our points - self.face_cap = None - self.length = -1 - # self.totchildren = 0 - # Bones per branch - self.faces = [None, None, None, None] - self.uv = None # face uvs can be fake, always 4 - self.bones = [] - self.generation = 0 # use to limit twig reproduction - self.twig_count = 0 # count the number of twigs - so as to limit how many twigs a branch gets - # self.myindex = -1 - ### self.segment_spacing_scale = 1.0 # use this to scale up the spacing - so small twigs dont get WAY too many polys - self.type = None - - def __repr__(self): - s = '' - s += '\tbranch' - s += '\tbpoints:', len(self.bpoints) - for pt in brch.bpoints: - s += str(self.pt) - - def getNormal(self): - return (self.bpoints[-1].co - self.bpoints[0].co).normalize() - - def getParentAngle(self): - if self.parent_pt: - return AngleBetweenVecsSafe(self.parent_pt.no, self.bpoints[0].no ) - else: - return 45.0 - - def getParentRadiusRatio(self): - if self.parent_pt: - return self.bpoints[0].radius / self.parent_pt.radius - else: - return 0.8 - - def getLength(self): - return (self.bpoints[0].co - self.bpoints[-1].co).length - - def getStraightness(self): - straight = 0.0 - pt = self.bpoints[0] - while pt.next: - straight += AngleBetweenVecsSafe(pt.no, pt.next.no) - pt = pt.next - return straight - - - ''' - def calcTotChildren(self): - for pt in self.bpoints: - self.totchildren += pt.childCount - ''' - def calcData(self): - ''' - Finalize once point data is there - ''' - self.calcPointLinkedList() - self.calcPointExtras() - - def calcPointLinkedList(self): - for i in xrange(1, len(self.bpoints)-1): - self.bpoints[i].next = self.bpoints[i+1] - self.bpoints[i].prev = self.bpoints[i-1] - - self.bpoints[0].next = self.bpoints[1] - self.bpoints[-1].prev = self.bpoints[-2] - - def calcPointExtras(self): - ''' - Run on a new branch or after transforming an existing one. - ''' - for pt in self.bpoints: - pt.calcNormal() - pt.calcNextMidCo() - - def calcTwigBounds(self, tree): - ''' - Check if out points are - ''' - for pt in self.bpoints: - pt.inTwigBounds = tree.isPointInTwigBounds(pt.co) - #if pt.inTwigBounds: - # debug_pt(pt.co) - - def baseTrim(self, connect_base_trim): - # if 1) dont remove the whole branch, maybe an option but later - # if 2) we are alredy a parent, cant remove me now.... darn :/ not nice... - # could do this properly but it would be slower and its a corner case. - # - # if 3) this point is within the branch, remove it. - # Scale this value by the difference in radius, a low trim looks better when the parent is a lot bigger.. - # - - while len(self.bpoints)>2 and\ - self.bpoints[0].childCount == 0 and\ - (self.parent_pt.nextMidCo - self.bpoints[0].co).length < ((self.parent_pt.radius + self.parent_pt.next.radius)/4) + (self.bpoints[0].radius * connect_base_trim): - # Note /4 - is a bit odd, since /2 is correct, but /4 lets us have more tight joints by default - - - del self.bpoints[0] - self.bpoints[0].prev = None - - def boundsTrim(self): - ''' - depends on calcTwigBounds running first. - also assumes no children assigned yet! make sure this is always the case. - ''' - trim = False - for i, pt in enumerate(self.bpoints): - if not pt.inTwigBounds: - trim = True - break - - # We must have at least 2 points to be a valid branch. this will be a stump :/ - if not trim or i < 3: - self.bpoints = [] # - return - - # Shorten the point list - self.bpoints = self.bpoints[:i] - self.bpoints[-1].makeLast() - - def taper(self, twig_ob_bounds_prune_taper = 0.0): - l = float(len( self.bpoints )) - for i, pt in enumerate(self.bpoints): - pt.radius *= (((l-i)/l) + (twig_ob_bounds_prune_taper*(i/l)) ) - - def getParentBranch(self): - if not self.parent_pt: - return None - return self.parent_pt.branch - - def getParentQuadAngle(self): - ''' - The angle off we are from our parent quad, - ''' - # used to roll the parent so its faces us better - - # Warning this can be zero sometimes, see the try below for the error - parent_normal = self.getParentFaceCent() - self.parent_pt.nextMidCo - - - self_normal = self.bpoints[1].co - self.parent_pt.co - # We only want the angle in relation to the parent points normal - # modify self_normal to make this so - cross = self_normal.cross(self.parent_pt.no) - self_normal = self.parent_pt.no.cross(cross) # CHECK - - #try: angle = AngleBetweenVecs(parent_normal, self_normal) - #except: return 0.0 - angle = AngleBetweenVecsSafe(parent_normal, self_normal) - - - # see if we need to rotate positive or negative - # USE DOT PRODUCT! - cross = parent_normal.cross(self_normal) - if AngleBetweenVecsSafe(cross, self.parent_pt.no) > 90: - angle = -angle - - return angle - - def getParentQuadIndex(self): - return self.parent_pt.children.index(self) - def getParentFaceCent(self): - return self.parent_pt.childPoint( self.getParentQuadIndex() ) - - def findClosest(self, co): - ''' - Find the closest point that can bare a child - ''' - - - ''' # this dosnt work, but could. - best = None - best_dist = 100000000 - for pt in self.bpoints: - if pt.next: - co_on_line, fac = ClosestPointOnLine(co, pt.co, pt.next.co) - print fac - if fac >= 0.0 and fac <= 1.0: - - return pt, (co-co_on_line).length - - return best, best_dist - ''' - best = None - best_dist = 100000000 - for pt in self.bpoints: - if pt.nextMidCo and pt.childCount < 4: - dist = (pt.nextMidCo-co).length - if dist < best_dist: - best = pt - best_dist = dist - - return best, best_dist - - def inParentChain(self, brch): - ''' - See if this branch is a parent of self or in the chain - ''' - - self_parent_lookup = self.getParentBranch() - while self_parent_lookup: - if self_parent_lookup == brch: - return True - self_parent_lookup = self_parent_lookup.getParentBranch() - - return False - - def transform(self, mat, loc=None, scale=None): - if scale==None: - scale = (xyzup * mat).length - - for pt in self.bpoints: - if loc: - pt.co = (pt.co * mat) + loc - else: - pt.co = pt.co * mat - pt.radius *= scale - - for pt in self.bpoints: - self.calcPointExtras() - - def translate(self, co): - ''' - Simply move the twig on the branch - ''' - ofs = self.bpoints[0].co-co - for pt in self.bpoints: - pt.co -= ofs - - def transformRecursive(self, tree, mat3x3, cent, scale=None): - - if scale==None: - # incase this is a translation matrix - scale = ((xyzup * mat3x3) - (Vector(0,0,0) * mat3x3)).length - - for pt in self.bpoints: pt.co = ((pt.co-cent) * mat3x3) + cent - #for pt in self.bpoints: pt.co = (pt.co * mat3x3) - for pt in self.bpoints: self.calcPointExtras() - - - for brch in tree.branches_all: - if brch.parent_pt: - if brch.parent_pt.branch == self: - - brch.transformRecursive(tree, mat3x3, cent, scale) - - ''' - for pt in self.bpoints: - for brch in pt.children: - if brch: - brch.transformRecursive(mat3x3, cent, scale) - ''' - def bestTwigSegment(self): - ''' - Return the most free part on the branch to place a new twig - return (sort_value, best_index, self) - ''' - - # loop up and down the branch - counding how far from the last parent segment we are - spacing1 = [0] * (len(self.bpoints)-1) - spacing2 = spacing1[:] - - step_from_parent = 0 - for i in xrange(len(spacing1)): # -1 because the last pt cant have kits - - if self.bpoints[i].childCount or self.bpoints[i].inTwigBounds==False: - step_from_parent = 0 - else: - step_from_parent += 1 - - spacing1[i] += step_from_parent # -1 because the last pt cant have kits - - best_index = -1 - best_val = -1 - step_from_parent = 0 - for i in xrange(len(spacing1)-1, -1, -1): - - if self.bpoints[i].childCount or self.bpoints[i].inTwigBounds==False: - step_from_parent = 0 - else: - step_from_parent += 1 - - spacing2[i] += step_from_parent - - # inTwigBounds is true by default, when twigBounds are used it can be false - if self.bpoints[i].childCount < 4 and self.bpoints[i].inTwigBounds: - # Dont allow to assign more verts then 4 - val = spacing1[i] * spacing2[i] - if val > best_val: - best_val = val - best_index = i - - #if best_index == -1: - # raise "Error" - - # This value is only used for sorting, so the lower the value - the sooner it gets a twig. - #sort_val = -best_val + (1/self.getLength()) - sort_val=self.getLength() - - return sort_val, best_index, self - - def evenPointDistrobution(self, factor=1.0, factor_joint=1.0): - ''' - Redistribute points that are not evenly distributed - factor is between 0.0 and 1.0 - ''' - - for pt in self.bpoints: - if pt.next and pt.prev and pt.childCount == 0 and pt.prev.childCount == 0: - w1 = pt.nextLength() - w2 = pt.prevLength() - wtot = w1+w2 - if wtot > 0.0: - w1=w1/wtot - #w2=w2/wtot - w1 = abs(w1-0.5)*2 # make this from 0.0 to 1.0, where 0 is the middle and 1.0 is as far out of the middle as possible. - # print "%.6f" % w1 - pt.smooth(w1*factor, w1*factor_joint) - - def fixOverlapError(self, joint_smooth=1.0): - # Keep fixing until no hasOverlapError left to fix. - - error = True - while error: - error = False - for pt in self.bpoints: - if pt.prev and pt.next: - if pt.hasOverlapError(): - if pt.smooth(1.0, joint_smooth): # if we cant fix then dont bother trying again. - error = True - - def evenJointDistrobution(self, joint_compression = 1.0): - # See if we need to evaluate this branch at all - if len(self.bpoints) <= 2: # Rare but in this case we cant do anything - return - has_children = False - for pt in self.bpoints: - if pt.childCount: - has_children = True - break - - if not has_children: - return - - # OK, we have children, so we have some work to do... - # center each segment - - # work out the median location of all points children. - for pt in self.bpoints: - pt.calcChildrenMidData() - pt.targetCos[:] = [] - - for pt in self.bpoints: - - if pt.childrenMidCo: - # Move this and the next segment to be around the child point. - # TODO - factor in the branch angle, be careful with this - close angles can have extreme values. - slide_dist = (pt.childrenMidCo - pt.co).length - (pt.childrenMidRadius * joint_compression) - co = pt.slideCo( slide_dist ) - if co: - pt.targetCos.append( co ) - - slide_dist = (pt.childrenMidRadius * joint_compression) - (pt.childrenMidCo - pt.next.co).length - co = pt.next.slideCo( slide_dist ) - if co: - pt.next.targetCos.append( co ) - - for pt in reversed(self.bpoints): - pt.applyTargetLocation() - - def collapsePoints(self, seg_density=0.5, seg_density_angle=20.0, seg_density_radius=0.3, smooth_joint=1.0): - - collapse = True - while collapse: - collapse = False - pt = self.bpoints[0] - while pt: - # Collapse angles greater then 90. they are useually artifacts - - if pt.prev and pt.next and pt.prev.childCount == 0: - if (pt.radius + pt.prev.radius) != 0.0 and abs(pt.radius - pt.prev.radius) / (pt.radius + pt.prev.radius) < seg_density_radius: - ang = AngleBetweenVecsSafe(pt.no, pt.prev.no) - if seg_density_angle == 180 or ang > 90 or ang < seg_density_angle: - ## if (pt.prev.nextMidCo-pt.co).length < ((pt.radius + pt.prev.radius)/2) * seg_density: - if (pt.prev.nextMidCo-pt.co).length < seg_density or ang > 90: - pt_save = pt.prev - if pt.next.collapseUp(): # collapse this point - collapse = True - pt = pt_save # so we never reference a removed point - - if pt.childCount == 0 and pt.next: #if pt.childrenMidCo == None: - if (pt.radius + pt.next.radius) != 0.0 and abs(pt.radius - pt.next.radius) / (pt.radius + pt.next.radius) < seg_density_radius: - ang = AngleBetweenVecsSafe(pt.no, pt.next.no) - if seg_density_angle == 180 or ang > 90 or ang < seg_density_angle: - # do here because we only want to run this on points with no children, - # Are we closer theto eachother then the radius? - ## if (pt.nextMidCo-pt.co).length < ((pt.radius + pt.next.radius)/2) * seg_density: - if (pt.nextMidCo-pt.co).length < seg_density or ang > 90: - if pt.collapseDown(): - collapse = True - - pt = pt.next - ## self.checkPointList() - self.evenPointDistrobution(1.0, smooth_joint) - - for pt in self.bpoints: - pt.calcNormal() - pt.calcNextMidCo() - - # This is a bit dodgy - moving the branches around after placing can cause problems - """ - def branchReJoin(self): - ''' - Not needed but nice to run after collapsing incase segments moved a lot - ''' - if not self.parent_pt: - return # nothing to do - - # see if the next segment is closer now (after collapsing) - parent_pt = self.parent_pt - root_pt = self.bpoints[0] - - #try: - index = parent_pt.children.index(self) - #except: - #print "This is bad!, but not being able to re-join isnt that big a deal" - - current_dist = (parent_pt.nextMidCo - root_pt.co).length - - # TODO - Check size of new area is ok to move into - - if parent_pt.next and parent_pt.next.next and parent_pt.next.children[index] == None: - # We can go here if we want, see if its better - if current_dist > (parent_pt.next.nextMidCo - root_pt.co).length: - self.parent_pt.children[index] = None - self.parent_pt.childCount -= 1 - - self.parent_pt = parent_pt.next - self.parent_pt.children[index] = self - self.parent_pt.childCount += 1 - return - - if parent_pt.prev and parent_pt.prev.children[index] == None: - # We can go here if we want, see if its better - if current_dist > (parent_pt.prev.nextMidCo - root_pt.co).length: - self.parent_pt.children[index] = None - self.parent_pt.childCount -= 1 - - self.parent_pt = parent_pt.prev - self.parent_pt.children[index] = self - self.parent_pt.childCount += 1 - return - """ - - def checkPointList(self): - ''' - Error checking. use to check if collapsing worked. - ''' - p_link = self.bpoints[0] - i = 0 - while p_link: - if self.bpoints[i] != p_link: - raise "Error" - - if p_link.prev and p_link.prev != self.bpoints[i-1]: - raise "Error Prev" - - if p_link.next and p_link.next != self.bpoints[i+1]: - raise "Error Next" - - p_link = p_link.next - i+=1 - - def mixToNew(self, other, BLEND_MODE): - ''' - Generate a new branch based on 2 existing ones - These branches will point 'zup' - aurient 'xup' and have a tip length of 1.0 - ''' - - # Lets be lazy! - if the branches are different sizes- use the shortest. - # brch1 is always smaller - - brch1 = self - brch2 = other - if len(brch1.bpoints) > len(brch2.bpoints): - brch1, brch2 = brch2, brch1 - - if len(brch1.bpoints) == 1: - return None - - co_start = brch1.bpoints[0].co - cos1 = [ pt.co - co_start for pt in brch1.bpoints ] - - co_start = brch2.bpoints[0].co - if len(brch1.bpoints) == len(brch2.bpoints): - cos2 = [ pt.co - co_start for pt in brch2.bpoints ] - else: # truncate the points - cos2 = [ brch2.bpoints[i].co - co_start for i in xrange(len(brch1.bpoints)) ] - - scales = [] - for cos_ls in (cos1, cos2): - cross = cos_ls[-1].cross(zup) - mat = RotationMatrix(AngleBetweenVecsSafe(cos_ls[-1], zup), 3, 'r', cross) - cos_ls[:] = [co*mat for co in cos_ls] - - # point z-up - - # Now they are both pointing the same way aurient the curves to be rotated the same way - xy_nor = Vector(0,0,0) - for co in cos_ls: - xy_nor.x += co.x - xy_nor.y += co.y - cross = xy_nor.cross(xup) - - # Also scale them here so they are 1.0 tall always - scale = 1.0/(cos_ls[0]-cos_ls[-1]).length - mat = RotationMatrix(AngleBetweenVecsSafe(xy_nor, xup), 3, 'r', cross) * Matrix([scale,0,0],[0,scale,0],[0,0,scale]) - cos_ls[:] = [co*mat for co in cos_ls] - - scales.append(scale) - - # Make the new branch - new_brch = branch() - new_brch.type = BRANCH_TYPE_GROWN - for i in xrange(len(cos1)): - new_brch.bpoints.append( bpoint(new_brch, (cos1[i]+cos2[i])*0.5, Vector(), (brch1.bpoints[i].radius*scales[0] + brch2.bpoints[i].radius*scales[1])/2) ) - - new_brch.calcData() - return new_brch - - ''' - def toMesh(self): - pass - ''' - - - - -# No GUI code above this! ------------------------------------------------------ - -# PREFS - These can be saved on the object's id property. use 'tree2curve' slot -from Blender import Draw -import BPyWindow -ID_SLOT_NAME = 'Curve2Tree' - -EVENT_NONE = 0 -EVENT_EXIT = 1 -EVENT_UPDATE = 2 -EVENT_UPDATE_AND_UI = 2 -EVENT_REDRAW = 3 - - -# Prefs for each tree -PREFS = {} -PREFS['connect_sloppy'] = Draw.Create(1.5) -PREFS['connect_base_trim'] = Draw.Create(1.0) -PREFS['seg_density'] = Draw.Create(0.5) -PREFS['seg_density_angle'] = Draw.Create(20.0) -PREFS['seg_density_radius'] = Draw.Create(0.3) -PREFS['seg_joint_compression'] = Draw.Create(1.0) -PREFS['seg_joint_smooth'] = Draw.Create(2.0) -PREFS['image_main'] = Draw.Create('') -PREFS['do_uv'] = Draw.Create(0) -PREFS['uv_x_scale'] = Draw.Create(4.0) -PREFS['uv_y_scale'] = Draw.Create(1.0) -PREFS['do_material'] = Draw.Create(0) -PREFS['material_use_existing'] = Draw.Create(1) -PREFS['material_texture'] = Draw.Create(1) -PREFS['material_stencil'] = Draw.Create(1) -PREFS['do_subsurf'] = Draw.Create(1) -PREFS['do_cap_ends'] = Draw.Create(0) -PREFS['do_uv_keep_vproportion'] = Draw.Create(1) -PREFS['do_uv_vnormalize'] = Draw.Create(0) -PREFS['do_uv_uscale'] = Draw.Create(0) -PREFS['do_armature'] = Draw.Create(0) -PREFS['do_anim'] = Draw.Create(1) -try: PREFS['anim_tex'] = Draw.Create([tex for tex in bpy.data.textures][0].name) -except: PREFS['anim_tex'] = Draw.Create('') - -PREFS['anim_speed'] = Draw.Create(0.2) -PREFS['anim_magnitude'] = Draw.Create(0.2) -PREFS['anim_speed_size_scale'] = Draw.Create(1) -PREFS['anim_offset_scale'] = Draw.Create(1.0) - -PREFS['do_twigs_fill'] = Draw.Create(0) -PREFS['twig_fill_levels'] = Draw.Create(4) - -PREFS['twig_fill_rand_scale'] = Draw.Create(0.1) -PREFS['twig_fill_fork_angle_max'] = Draw.Create(180.0) -PREFS['twig_fill_radius_min'] = Draw.Create(0.001) -PREFS['twig_fill_radius_factor'] = Draw.Create(0.75) -PREFS['twig_fill_shape_type'] = Draw.Create(1) -PREFS['twig_fill_shape_rand'] = Draw.Create(0.5) -PREFS['twig_fill_shape_power'] = Draw.Create(0.5) - -PREFS['do_twigs'] = Draw.Create(0) -PREFS['twig_ratio'] = Draw.Create(2.0) -PREFS['twig_select_mode'] = Draw.Create(0) -PREFS['twig_select_factor'] = Draw.Create(0.5) -PREFS['twig_scale'] = Draw.Create(0.8) -PREFS['twig_scale_width'] = Draw.Create(1.0) -PREFS['twig_random_orientation'] = Draw.Create(180) -PREFS['twig_random_angle'] = Draw.Create(33) -PREFS['twig_recursive'] = Draw.Create(1) -PREFS['twig_recursive_limit'] = Draw.Create(3) -PREFS['twig_ob_bounds'] = Draw.Create('') # WATCH out, used for do_twigs_fill AND do_twigs -PREFS['twig_ob_bounds_prune'] = Draw.Create(1) -PREFS['twig_ob_bounds_prune_taper'] = Draw.Create(1.0) -PREFS['twig_placement_maxradius'] = Draw.Create(10.0) -PREFS['twig_placement_maxtwig'] = Draw.Create(4) -PREFS['twig_follow_parent'] = Draw.Create(0.0) -PREFS['twig_follow_x'] = Draw.Create(0.0) -PREFS['twig_follow_y'] = Draw.Create(0.0) -PREFS['twig_follow_z'] = Draw.Create(0.0) - -PREFS['do_leaf'] = Draw.Create(0) - -PREFS['leaf_branch_limit'] = Draw.Create(0.25) -PREFS['leaf_branch_limit_rand'] = Draw.Create(0.1) -PREFS['leaf_branch_density'] = Draw.Create(0.1) -PREFS['leaf_branch_pitch_angle'] = Draw.Create(0.0) -PREFS['leaf_branch_pitch_rand'] = Draw.Create(0.2) -PREFS['leaf_branch_roll_rand'] = Draw.Create(0.2) -PREFS['leaf_branch_angle'] = Draw.Create(75.0) -PREFS['leaf_rand_seed'] = Draw.Create(1.0) -PREFS['leaf_size'] = Draw.Create(0.5) -PREFS['leaf_size_rand'] = Draw.Create(0.5) - -PREFS['leaf_object'] = Draw.Create('') - -PREFS['do_variation'] = Draw.Create(0) -PREFS['variation_seed'] = Draw.Create(1) -PREFS['variation_orientation'] = Draw.Create(0.0) -PREFS['variation_scale'] = Draw.Create(0.0) - -GLOBAL_PREFS = {} -GLOBAL_PREFS['realtime_update'] = Draw.Create(0) - - -def getContextCurveObjects(): - sce = bpy.data.scenes.active - objects = [] - ob_act = sce.objects.active - for ob in sce.objects.context: - if ob == ob_act: ob_act = None - - if ob.type != 'Curve': - ob = ob.parent - if not ob or ob.type != 'Curve': - continue - objects.append(ob) - - # Alredy delt with - - - # Add the active, important when using localview or local layers - if ob_act: - ob = ob_act - if ob.type != 'Curve': - ob = ob.parent - if not ob or ob.type != 'Curve': - pass - else: - objects.append(ob) - - return objects - - -def Prefs2Dict(prefs, new_prefs): - ''' - Make a copy with no button settings - ''' - new_prefs.clear() - for key, val in prefs.items(): - try: new_prefs[key] = val.val - except: new_prefs[key] = val - return new_prefs - -def Dict2Prefs(prefs, new_prefs): - ''' - Make a copy with button settings - ''' - for key in prefs: # items would be nice for id groups - val = prefs[key] - ok = True - - try: - # If we have this setting allredy but its a different type, use the old setting (converting int's to floats for instance) - new_val = new_prefs[key] # this may fail, thats ok - if (type(new_val)==Blender.Types.ButtonType) and (type(new_val.val) != type(val)): - ok = False - except: - pass - - if ok: - try: - new_prefs[key] = Blender.Draw.Create( val ) - except: - new_prefs[key] = val - - return new_prefs - -def Prefs2IDProp(idprop, prefs): - new_prefs = {} - Prefs2Dict(prefs, new_prefs) - try: del idprop[ID_SLOT_NAME] - except: pass - - idprop[ID_SLOT_NAME] = new_prefs - -def IDProp2Prefs(idprop, prefs): - try: - prefs = idprop[ID_SLOT_NAME] - except: - return False - Dict2Prefs(prefs, PREFS) - return True - -def buildTree(ob_curve, single=False): - ''' - Must be a curve object, write to a child mesh - Must check this is a curve object! - ''' - print 'Curve2Tree, starting...' - # if were only doing 1 object, just use the current prefs - prefs = {} - - if single or not (IDProp2Prefs(ob_curve.properties, prefs)): - prefs = PREFS - - - # Check prefs are ok. - - - sce = bpy.data.scenes.active - - def getObChild(parent, obtype): - try: - return [ _ob for _ob in sce.objects if _ob.type == obtype if _ob.parent == parent ][0] - except: - return None - - def newObChild(parent, obdata): - - ob_new = bpy.data.scenes.active.objects.new(obdata) - # ob_new.Layers = parent.Layers - - # new object settings - parent.makeParent([ob_new]) - ob_new.setMatrix(Matrix()) - ob_new.sel = 0 - return ob_new - - def hasModifier(modtype): - return len([mod for mod in ob_mesh.modifiers if mod.type == modtype]) > 0 - - - sce = bpy.data.scenes.active - - if PREFS['image_main'].val: - try: image = bpy.data.images[PREFS['image_main'].val] - except: image = None - else: image = None - - # Get the mesh child - - print '\treading blenders curves...', - time1 = Blender.sys.time() - - t = tree() - t.fromCurve(ob_curve) - if not t.branches_all: - return # Empty curve? - may as well not throw an error - - time2 = Blender.sys.time() # time print - """ - print '%.4f sec' % (time2-time1) - if PREFS['do_twigs'].val: - print '\tbuilding twigs...', - t.buildTwigs(ratio=PREFS['twig_ratio'].val) - time3 = Blender.sys.time() # time print - print '%.4f sec' % (time3 - time2) - """ - if 0: pass - else: - time3 = Blender.sys.time() # time print - - print '\tconnecting branches...', - - twig_ob_bounds = getObFromName(PREFS['twig_ob_bounds'].val) - - t.buildConnections(\ - sloppy = PREFS['connect_sloppy'].val,\ - connect_base_trim = PREFS['connect_base_trim'].val,\ - do_twigs = PREFS['do_twigs'].val,\ - twig_ratio = PREFS['twig_ratio'].val,\ - twig_select_mode = PREFS['twig_select_mode'].val,\ - twig_select_factor = PREFS['twig_select_factor'].val,\ - twig_scale = PREFS['twig_scale'].val,\ - twig_scale_width = PREFS['twig_scale_width'].val,\ - twig_random_orientation = PREFS['twig_random_orientation'].val,\ - twig_random_angle = PREFS['twig_random_angle'].val,\ - twig_recursive = PREFS['twig_recursive'].val,\ - twig_recursive_limit = PREFS['twig_recursive_limit'].val,\ - twig_ob_bounds = twig_ob_bounds,\ - twig_ob_bounds_prune = PREFS['twig_ob_bounds_prune'].val,\ - twig_ob_bounds_prune_taper = PREFS['twig_ob_bounds_prune_taper'].val,\ - twig_placement_maxradius = PREFS['twig_placement_maxradius'].val,\ - twig_placement_maxtwig = PREFS['twig_placement_maxtwig'].val,\ - twig_follow_parent = PREFS['twig_follow_parent'].val,\ - twig_follow_x = PREFS['twig_follow_x'].val,\ - twig_follow_y = PREFS['twig_follow_y'].val,\ - twig_follow_z = PREFS['twig_follow_z'].val,\ - do_variation = PREFS['do_variation'].val,\ - variation_seed = PREFS['variation_seed'].val,\ - variation_orientation = PREFS['variation_orientation'].val,\ - variation_scale = PREFS['variation_scale'].val,\ - do_twigs_fill = PREFS['do_twigs_fill'].val,\ - twig_fill_levels = PREFS['twig_fill_levels'].val,\ - twig_fill_rand_scale = PREFS['twig_fill_rand_scale'].val,\ - twig_fill_fork_angle_max = PREFS['twig_fill_fork_angle_max'].val,\ - twig_fill_radius_min = PREFS['twig_fill_radius_min'].val,\ - twig_fill_radius_factor = PREFS['twig_fill_radius_factor'].val,\ - twig_fill_shape_type = PREFS['twig_fill_shape_type'].val,\ - twig_fill_shape_rand = PREFS['twig_fill_shape_rand'].val,\ - twig_fill_shape_power = PREFS['twig_fill_shape_power'].val,\ - ) - - time4 = Blender.sys.time() # time print - print '%.4f sec' % (time4-time3) - print '\toptimizing point spacing...', - - t.optimizeSpacing(\ - seg_density=PREFS['seg_density'].val,\ - seg_density_angle=PREFS['seg_density_angle'].val,\ - seg_density_radius=PREFS['seg_density_radius'].val,\ - joint_compression = PREFS['seg_joint_compression'].val,\ - joint_smooth = PREFS['seg_joint_smooth'].val\ - ) - - time5 = Blender.sys.time() # time print - print '%.4f sec' % (time5-time4) - print '\tbuilding mesh...', - - ob_mesh = getObChild(ob_curve, 'Mesh') - if not ob_mesh: - # New object - mesh = bpy.data.meshes.new('tree_' + ob_curve.name) - ob_mesh = newObChild(ob_curve, mesh) - # do subsurf later - - else: - # Existing object - mesh = ob_mesh.getData(mesh=1) - ob_mesh.setMatrix(Matrix()) - - # Do we need a do_uv_blend_layer? - if PREFS['do_material'].val and PREFS['material_stencil'].val and PREFS['material_texture'].val: - do_uv_blend_layer = True - else: - do_uv_blend_layer = False - - mesh = t.toMesh(mesh,\ - do_uv = PREFS['do_uv'].val,\ - uv_image = image,\ - do_uv_keep_vproportion = PREFS['do_uv_keep_vproportion'].val,\ - do_uv_vnormalize = PREFS['do_uv_vnormalize'].val,\ - do_uv_uscale = PREFS['do_uv_uscale'].val,\ - uv_x_scale = PREFS['uv_x_scale'].val,\ - uv_y_scale = PREFS['uv_y_scale'].val,\ - do_uv_blend_layer = do_uv_blend_layer,\ - do_cap_ends = PREFS['do_cap_ends'].val - ) - - if PREFS['do_leaf'].val: - ob_leaf_dupliface = getObChild(ob_mesh, 'Mesh') - if not ob_leaf_dupliface: # New object - mesh_leaf = bpy.data.meshes.new('leaf_' + ob_curve.name) - ob_leaf_dupliface = newObChild(ob_mesh, mesh_leaf) - else: - mesh_leaf = ob_leaf_dupliface.getData(mesh=1) - ob_leaf_dupliface.setMatrix(Matrix()) - - leaf_object = getObFromName(PREFS['leaf_object'].val) - - mesh_leaf = t.toLeafMesh(mesh_leaf,\ - leaf_branch_limit = PREFS['leaf_branch_limit'].val,\ - leaf_branch_limit_rand = PREFS['leaf_branch_limit_rand'].val,\ - leaf_size = PREFS['leaf_size'].val,\ - leaf_size_rand = PREFS['leaf_size_rand'].val,\ - leaf_branch_density = PREFS['leaf_branch_density'].val,\ - leaf_branch_pitch_angle = PREFS['leaf_branch_pitch_angle'].val,\ - leaf_branch_pitch_rand = PREFS['leaf_branch_pitch_rand'].val,\ - leaf_branch_roll_rand = PREFS['leaf_branch_roll_rand'].val,\ - leaf_branch_angle = PREFS['leaf_branch_angle'].val,\ - leaf_rand_seed = PREFS['leaf_rand_seed'].val,\ - leaf_object = leaf_object,\ - ) - - if leaf_object: - ob_leaf_dupliface.enableDupFaces = True - ob_leaf_dupliface.enableDupFacesScale = True - ob_leaf_dupliface.makeParent([leaf_object], 1) - else: - ob_leaf_dupliface.enableDupFaces = False - - mesh.calcNormals() - - if PREFS['do_material'].val: - - materials = mesh.materials - if PREFS['material_use_existing'].val and materials: - t.material = materials[0] - else: - t.material = bpy.data.materials.new(ob_curve.name) - mesh.materials = [t.material] - - if PREFS['material_texture'].val: - - # Set up the base image texture - t.texBase = bpy.data.textures.new('base_' + ob_curve.name) - t.material.setTexture(0, t.texBase, Blender.Texture.TexCo.UV, Blender.Texture.MapTo.COL) - t.texBase.type = Blender.Texture.Types.IMAGE - if image: - t.texBase.image = image - t.texBaseMTex = t.material.getTextures()[0] - t.texBaseMTex.uvlayer = 'base' - - if PREFS['material_stencil'].val: - # Set up the blend texture - t.texBlend = bpy.data.textures.new('blend_' + ob_curve.name) - t.material.setTexture(1, t.texBlend, Blender.Texture.TexCo.UV, 0) # map to None - t.texBlend.type = Blender.Texture.Types.BLEND - t.texBlend.flags |= Blender.Texture.Flags.FLIPBLEND - t.texBlendMTex = t.material.getTextures()[1] - t.texBlendMTex.stencil = True - t.texBlendMTex.uvlayer = 'blend' - - - # Now make the texture for the stencil to blend, can reuse texBase here, jus tdifferent settings for the mtex - t.material.setTexture(2, t.texBase, Blender.Texture.TexCo.UV, Blender.Texture.MapTo.COL) - t.texJoinMTex = t.material.getTextures()[2] - t.texJoinMTex.uvlayer = 'join' - - # Add a UV layer for blending - - - - - time6 = Blender.sys.time() # time print - print '%.4f sec' % (time6-time5) - - # Do armature stuff.... - if PREFS['do_armature'].val: - - print '\tbuilding armature & animation...', - - ob_arm = getObChild(ob_curve, 'Armature') - if ob_arm: - armature = ob_arm.data - ob_arm.setMatrix(Matrix()) - else: - armature = bpy.data.armatures.new() - ob_arm = newObChild(ob_curve, armature) - - t.toArmature(ob_arm, armature) - - # Add the modifier. - if not hasModifier(Blender.Modifier.Types.ARMATURE): - mod = ob_mesh.modifiers.append(Blender.Modifier.Types.ARMATURE) - - # TODO - assigne object anyway, even if an existing modifier exists. - mod[Blender.Modifier.Settings.OBJECT] = ob_arm - - if PREFS['do_anim'].val: - try: - tex = bpy.data.textures[PREFS['anim_tex'].val] - except: - tex = None - Blender.Draw.PupMenu('error no texture, cannot animate bones') - - if tex: - t.toAction(ob_arm, tex,\ - anim_speed = PREFS['anim_speed'].val,\ - anim_magnitude = PREFS['anim_magnitude'].val,\ - anim_speed_size_scale= PREFS['anim_speed_size_scale'].val,\ - anim_offset_scale=PREFS['anim_offset_scale'].val - ) - - time7 = Blender.sys.time() # time print - print '%.4f sec\n' % (time7-time6) - else: - time7 = Blender.sys.time() # time print - - print 'done in %.4f sec' % (time7 - time1) - - # Add subsurf last it needed. so armature skinning is done first. - # Do subsurf? - if PREFS['do_subsurf'].val: - if not hasModifier(Blender.Modifier.Types.SUBSURF): - mod = ob_mesh.modifiers.append(Blender.Modifier.Types.SUBSURF) - - #ob_mesh.makeDisplayList() - #mesh.update() - bpy.data.scenes.active.update() - -def do_pref_read(e=0,v=0, quiet=False): - ''' - We dont care about e and v values, only there because its a callback - ''' - sce = bpy.data.scenes.active - ob = sce.objects.active - - if not ob: - if not quiet: - Blender.Draw.PupMenu('No active curve object') - return - - if ob.type != 'Curve': - ob = ob.parent - - if ob == None or ob.type != 'Curve': - if not quiet: - Blender.Draw.PupMenu('No active curve object') - return - - if not IDProp2Prefs(ob.properties, PREFS): - if not quiet: - Blender.Draw.PupMenu('Curve object has no settings stored on it') - return - - Blender.Draw.Redraw() - -def do_pref_write(e,v): - - objects = getContextCurveObjects() - if not objects: - Blender.Draw.PupMenu('No curve objects selected') - return - - for ob in objects: - Prefs2IDProp(ob.properties, PREFS) - -def do_pref_clear(e,v): - objects = getContextCurveObjects() - if not objects: - Blender.Draw.PupMenu('No curve objects selected') - return - - for ob in objects: - try: del ob.properties[ID_SLOT_NAME] - except: pass - -def do_tex_check(e,v): - if not v: return - try: - bpy.data.textures[v] - except: - PREFS['anim_tex'].val = '' - Draw.PupMenu('Texture dosnt exist!') - Draw.Redraw() - -def do_ob_check(e,v): - if not v: return - try: - bpy.data.objects[v] - except: - # PREFS['twig_ob_bounds'].val = '' - Draw.PupMenu('Object dosnt exist!') - Draw.Redraw() - -def do_group_check(e,v): - if not v: return - try: - bpy.data.groups[v] - except: - # PREFS['leaf_object'].val = '' - Draw.PupMenu('dosnt exist!') - Draw.Redraw() - -# Button callbacks -def do_active_image(e,v): - img = bpy.data.images.active - if img: - PREFS['image_main'].val = img.name - else: - PREFS['image_main'].val = '' - -# Button callbacks -def do_tree_generate__real(): - sce = bpy.data.scenes.active - objects = getContextCurveObjects() - - if not objects: - Draw.PupMenu('Select one or more curve objects or a mesh/armature types with curve parents') - - is_editmode = Blender.Window.EditMode() - if is_editmode: - Blender.Window.EditMode(0, '', 0) - Blender.Window.WaitCursor(1) - - for ob in objects: - buildTree(ob, len(objects)==1) - - if is_editmode: - Blender.Window.EditMode(1, '', 0) - - Blender.Window.RedrawAll() - - Blender.Window.WaitCursor(0) - - -# Profile -# Had to do this to get it to work in ubuntu "sudo aptitude install python-profiler" -''' -import hotshot -import profile -from hotshot import stats -''' -def do_tree_generate(e,v): - - do_tree_generate__real() - ''' - prof = hotshot.Profile("hotshot_edi_stats") - prof.runcall(do_tree_generate__real) - prof.close() - s = stats.load("hotshot_edi_stats") - s.sort_stats("time").print_stats() - ''' - if GLOBALS['non_bez_error']: - Blender.Draw.PupMenu('Error%t|Nurbs and Poly curve types cant be used!') - GLOBALS['non_bez_error'] = 0 - -def do_tree_help(e,v): - url = 'http://wiki.blender.org/index.php/Scripts/Manual/Wizards/TreeFromCurves' - print 'Trying to open web browser with documentation at this address...' - print '\t' + url - - try: - import webbrowser - webbrowser.open(url) - except: - print '...could not open a browser window.' - - -def evt(e,val): - pass - -def bevt(e): - - if e==EVENT_NONE: - return - - if e == EVENT_UPDATE or e == EVENT_UPDATE_AND_UI: - if GLOBAL_PREFS['realtime_update'].val: - do_tree_generate(0,0) # values dont matter - - if e == EVENT_REDRAW or e == EVENT_UPDATE_AND_UI: - Draw.Redraw() - if e == EVENT_EXIT: - Draw.Exit() - pass - -def gui(): - MARGIN = 4 - rect = BPyWindow.spaceRect() - but_width = int((rect[2]-MARGIN*2)/4.0) # 72 - # Clamp - if but_width>100: but_width = 100 - but_height = 17 - - x=MARGIN - y=rect[3]-but_height-MARGIN - xtmp = x - - Blender.Draw.BeginAlign() - PREFS['do_twigs_fill'] = Draw.Toggle('Fill Twigs',EVENT_UPDATE_AND_UI, xtmp, y, but_width*2, but_height, PREFS['do_twigs_fill'].val, 'Generate child branches based existing branches'); xtmp += but_width*2; - if PREFS['do_twigs_fill'].val: - - PREFS['twig_fill_levels'] = Draw.Number('Generations', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['twig_fill_levels'].val, 1, 32, 'How many generations to make for filled twigs'); xtmp += but_width*2; - y-=but_height - xtmp = x - - # ---------- ---------- ---------- ---------- - # WARNING USED IN 2 PLACES!! - see below - PREFS['twig_ob_bounds'] = Draw.String('OB Bound: ', EVENT_UPDATE_AND_UI, xtmp, y, but_width*2, but_height, PREFS['twig_ob_bounds'].val, 64, 'Only grow twigs inside this mesh object', do_ob_check); xtmp += but_width*2; - PREFS['twig_fill_rand_scale'] = Draw.Number('Randomize Scale', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['twig_fill_rand_scale'].val, 0.0, 1.0, 'Randomize twig scale from the bounding mesh'); xtmp += but_width*2; - - y-=but_height - xtmp = x - - PREFS['twig_fill_radius_min'] = Draw.Number('Min Radius', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['twig_fill_radius_min'].val, 0.0, 1.0, 'Radius at endpoints of all twigs'); xtmp += but_width*2; - PREFS['twig_fill_radius_factor'] = Draw.Number('Inherit Scale', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['twig_fill_radius_factor'].val, 0.0, 1.0, 'What attaching to branches, scale the radius by this value for filled twigs, 0.0 for fixed width twigs.'); xtmp += but_width*2; - - y-=but_height - xtmp = x - - #PREFS['twig_fill_shape_type'] = Draw.Number('Shape Type', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['twig_fill_shape_type'].val, 0.0, 1.0, 'Shape used for the fork'); xtmp += but_width*2; - PREFS['twig_fill_shape_type'] = Draw.Menu('Join Type%t|Even%x0|Smooth One Child%x1|Smooth Both Children%x2',EVENT_UPDATE_AND_UI, xtmp, y, but_width*2, but_height, PREFS['twig_fill_shape_type'].val, 'Select the wat twigs '); xtmp += but_width*2; - PREFS['twig_fill_fork_angle_max'] = Draw.Number('Shape Max Ang', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['twig_fill_fork_angle_max'].val, 0.0, 180.0, 'Maximum fork angle'); xtmp += but_width*2; - - y-=but_height - xtmp = x - - PREFS['twig_fill_shape_rand'] = Draw.Number('Shape Rand', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['twig_fill_shape_rand'].val, 0.0, 1.0, 'Randomize the shape of forks'); xtmp += but_width*2; - PREFS['twig_fill_shape_power'] = Draw.Number('Shape Strength', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['twig_fill_shape_power'].val, 0.0, 1.0, 'Strength of curves'); xtmp += but_width*2; - - Blender.Draw.EndAlign() - - y-=but_height+MARGIN - xtmp = x - # ---------- ---------- ---------- ---------- - - - - # ---------- ---------- ---------- ---------- - Blender.Draw.BeginAlign() - PREFS['do_twigs'] = Draw.Toggle('Grow Twigs',EVENT_UPDATE_AND_UI, xtmp, y, but_width*2, but_height, PREFS['do_twigs'].val, 'Generate child branches based existing branches'); xtmp += but_width*2; - if PREFS['do_twigs'].val: - - PREFS['twig_ratio'] = Draw.Number('Twig Multiply', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['twig_ratio'].val, 0.01, 500.0, 'How many twigs to generate per branch'); xtmp += but_width*2; - y-=but_height - xtmp = x - - # ---------- ---------- ---------- ---------- - PREFS['twig_select_mode'] = Draw.Menu('Branch Selection Method%t|From Short%x0|From Long%x1|From Straight%x2|From Bent%x3|',EVENT_UPDATE_AND_UI, xtmp, y, but_width*2, but_height, PREFS['twig_select_mode'].val, 'Select branches to use as twigs based on this attribute'); xtmp += but_width*2; - PREFS['twig_select_factor'] = Draw.Number('From Factor', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['twig_select_factor'].val, 0.0, 16, 'Select branches, lower value is more strict and will give you less variation'); xtmp += but_width*2; - y-=but_height - xtmp = x - - # ---------- ---------- ---------- ---------- - PREFS['twig_recursive'] = Draw.Toggle('Recursive Twigs',EVENT_UPDATE_AND_UI, xtmp, y, but_width*2, but_height, PREFS['twig_recursive'].val, 'Recursively add twigs into eachother'); xtmp += but_width*2; - PREFS['twig_recursive_limit'] = Draw.Number('Generations', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['twig_recursive_limit'].val, 0.0, 16, 'Number of generations allowed, 0 is inf'); xtmp += but_width*2; - y-=but_height - xtmp = x - - # ---------- ---------- ---------- ---------- - - PREFS['twig_scale'] = Draw.Number('Twig Scale', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['twig_scale'].val, 0.01, 10.0, 'Scale down twigs in relation to their parents each generation'); xtmp += but_width*2; - PREFS['twig_scale_width'] = Draw.Number('Twig Scale Width', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['twig_scale_width'].val, 0.01, 20.0, 'Scale the twig length only (not thickness)'); xtmp += but_width*2; - y-=but_height - xtmp = x - - # ---------- ---------- ---------- ---------- - - PREFS['twig_random_orientation'] = Draw.Number('Rand Orientation', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['twig_random_orientation'].val, 0.0, 360.0, 'Random rotation around the parent'); xtmp += but_width*2; - PREFS['twig_random_angle'] = Draw.Number('Rand Angle', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['twig_random_angle'].val, 0.0, 360.0, 'Random rotation to the parent joint'); xtmp += but_width*2; - y-=but_height - xtmp = x - - # ---------- ---------- ---------- ---------- - - PREFS['twig_placement_maxradius'] = Draw.Number('Place Max Radius', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['twig_placement_maxradius'].val, 0.0, 50.0, 'Only place twigs on branches below this radius'); xtmp += but_width*2; - PREFS['twig_placement_maxtwig'] = Draw.Number('Place Max Count', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['twig_placement_maxtwig'].val, 0.0, 50.0, 'Limit twig placement to this many per branch'); xtmp += but_width*2; - - y-=but_height - xtmp = x - # ---------- ---------- ---------- ---------- - - PREFS['twig_follow_parent'] = Draw.Number('ParFollow', EVENT_UPDATE, xtmp, y, but_width, but_height, PREFS['twig_follow_parent'].val, 0.0, 10.0, 'Follow the parent branch'); xtmp += but_width; - PREFS['twig_follow_x'] = Draw.Number('Grav X', EVENT_UPDATE, xtmp, y, but_width, but_height, PREFS['twig_follow_x'].val, -10.0, 10.0, 'Twigs gravitate on the X axis'); xtmp += but_width; - PREFS['twig_follow_y'] = Draw.Number('Grav Y', EVENT_UPDATE, xtmp, y, but_width, but_height, PREFS['twig_follow_y'].val, -10.0, 10.0, 'Twigs gravitate on the Y axis'); xtmp += but_width; - PREFS['twig_follow_z'] = Draw.Number('Grav Z', EVENT_UPDATE, xtmp, y, but_width, but_height, PREFS['twig_follow_z'].val, -10.0, 10.0, 'Twigs gravitate on the Z axis'); xtmp += but_width; - - y-=but_height - xtmp = x - - # ---------- ---------- ---------- ---------- - # WARNING USED IN 2 PLACES!! - PREFS['twig_ob_bounds'] = Draw.String('OB Bound: ', EVENT_UPDATE_AND_UI, xtmp, y, but_width*2, but_height, PREFS['twig_ob_bounds'].val, 64, 'Only grow twigs inside this mesh object', do_ob_check); xtmp += but_width*2; - - if PREFS['twig_ob_bounds_prune'].val: - but_width_tmp = but_width - else: - but_width_tmp = but_width*2 - - PREFS['twig_ob_bounds_prune'] = Draw.Toggle('Prune',EVENT_UPDATE_AND_UI, xtmp, y, but_width_tmp, but_height, PREFS['twig_ob_bounds_prune'].val, 'Prune twigs to the mesh object bounds'); xtmp += but_width_tmp; - if PREFS['twig_ob_bounds_prune'].val: - PREFS['twig_ob_bounds_prune_taper'] = Draw.Number('Taper', EVENT_UPDATE_AND_UI, xtmp, y, but_width, but_height, PREFS['twig_ob_bounds_prune_taper'].val, 0.0, 1.0, 'Taper pruned branches to a point'); xtmp += but_width; - - #PREFS['image_main'] = Draw.String('IM: ', EVENT_UPDATE, xtmp, y, but_width*3, but_height, PREFS['image_main'].val, 64, 'Image to apply to faces'); xtmp += but_width*3; - #Draw.PushButton('Use Active', EVENT_UPDATE, xtmp, y, but_width, but_height, 'Get the image from the active image window', do_active_image); xtmp += but_width; - Blender.Draw.EndAlign() - - y-=but_height+MARGIN - xtmp = x - # ---------- ---------- ---------- ---------- - - - - Blender.Draw.BeginAlign() - PREFS['do_leaf'] = Draw.Toggle('Generate Leaves',EVENT_UPDATE_AND_UI, xtmp, y, but_width*2, but_height, PREFS['do_leaf'].val, 'Generate leaves using duplifaces'); xtmp += but_width*2; - - if PREFS['do_leaf'].val: - - PREFS['leaf_object'] = Draw.String('OB: ', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['leaf_object'].val, 64, 'Use this object as a leaf', do_ob_check); xtmp += but_width*2; - # ---------- ---------- ---------- ---------- - y-=but_height - xtmp = x - - PREFS['leaf_size'] = Draw.Number('Size', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['leaf_size'].val, 0.001, 10.0, 'size of the leaf'); xtmp += but_width*2; - PREFS['leaf_size_rand'] = Draw.Number('Randsize', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['leaf_size_rand'].val, 0.0, 1.0, 'randomize the leaf size'); xtmp += but_width*2; - - # ---------- ---------- ---------- ---------- - y-=but_height - xtmp = x - - # Dont use yet - PREFS['leaf_branch_limit'] = Draw.Number('Branch Limit', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['leaf_branch_limit'].val, 0.0, 1.0, 'Maximum thichness where a branch can bare leaves, higher value to place leaves on bigger branches'); xtmp += but_width*2; - PREFS['leaf_branch_limit_rand'] = Draw.Number('Limit Random', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['leaf_branch_limit_rand'].val, 0.0, 1.0, 'Randomize the allowed minimum branch width to place leaves'); xtmp += but_width*2; - - # ---------- ---------- ---------- ---------- - y-=but_height - xtmp = x - - PREFS['leaf_branch_density'] = Draw.Number('Density', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['leaf_branch_density'].val, 0.0, 1.0, 'Chance each segment has of baring a leaf, use a high value for more leaves'); xtmp += but_width*2; - PREFS['leaf_branch_angle'] = Draw.Number('Angle From Branch', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['leaf_branch_angle'].val, 0.0, 90.0, 'angle the leaf is from the branch direction'); xtmp += but_width*2; - - # ---------- ---------- ---------- ---------- - y-=but_height - xtmp = x - - PREFS['leaf_rand_seed'] = Draw.Number('Random Seed', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['leaf_rand_seed'].val, 0.0, 10000.0, 'Set the seed for leaf random values'); xtmp += but_width*2; - PREFS['leaf_branch_pitch_angle'] = Draw.Number('Pitch Angle', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['leaf_branch_pitch_angle'].val, -180, 180.0, 'Change the pitch rotation of leaves, negative angle to point down'); xtmp += but_width*2; - - # ---------- ---------- ---------- ---------- - y-=but_height - xtmp = x - - PREFS['leaf_branch_pitch_rand'] = Draw.Number('Random Pitch', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['leaf_branch_pitch_rand'].val, 0.0, 1.0, 'Randomize the leaf rotation (up-down/pitch)'); xtmp += but_width*2; - PREFS['leaf_branch_roll_rand'] = Draw.Number('Random Roll', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['leaf_branch_roll_rand'].val, 0.0, 1.0, 'Randomize the leaf rotation (roll/tilt/yaw)'); xtmp += but_width*2; - - - Blender.Draw.EndAlign() - - y-=but_height+MARGIN - xtmp = x - # ---------- ---------- ---------- ---------- - - - Blender.Draw.BeginAlign() - if PREFS['do_uv'].val == 0: but_width_tmp = but_width*2 - else: but_width_tmp = but_width*4 - PREFS['do_uv'] = Draw.Toggle('Generate UVs',EVENT_UPDATE_AND_UI, xtmp, y, but_width_tmp, but_height, PREFS['do_uv'].val, 'Calculate UVs coords'); xtmp += but_width_tmp; - - if PREFS['do_uv'].val: - # ---------- ---------- ---------- ---------- - y-=but_height - xtmp = x - - PREFS['do_uv_uscale'] = Draw.Toggle('U-Scale', EVENT_UPDATE, xtmp, y, but_width, but_height, PREFS['do_uv_uscale'].val, 'Scale the width according to the face size (will NOT tile)'); xtmp += but_width; - PREFS['do_uv_keep_vproportion'] = Draw.Toggle('V-Aspect', EVENT_UPDATE, xtmp, y, but_width, but_height, PREFS['do_uv_keep_vproportion'].val, 'Correct the UV aspect with the branch width'); xtmp += but_width; - PREFS['do_uv_vnormalize'] = Draw.Toggle('V-Normaize', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['do_uv_vnormalize'].val, 'Scale the UVs to fit onto the image verticaly'); xtmp += but_width*2; - - y-=but_height - xtmp = x - # ---------- ---------- ---------- ---------- - - PREFS['uv_x_scale'] = Draw.Number('Scale U', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['uv_x_scale'].val, 0.01, 10.0, 'Edge loop spacing around branch join, lower value for less webed joins'); xtmp += but_width*2; - PREFS['uv_y_scale'] = Draw.Number('Scale V', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['uv_y_scale'].val, 0.01, 10.0, 'Edge loop spacing around branch join, lower value for less webed joins'); xtmp += but_width*2; - - y-=but_height - xtmp = x - # ---------- ---------- ---------- ---------- - - PREFS['image_main'] = Draw.String('IM: ', EVENT_UPDATE, xtmp, y, but_width*3, but_height, PREFS['image_main'].val, 64, 'Image to apply to faces'); xtmp += but_width*3; - Draw.PushButton('Use Active', EVENT_UPDATE, xtmp, y, but_width, but_height, 'Get the image from the active image window', do_active_image); xtmp += but_width; - Blender.Draw.EndAlign() - - y-=but_height+MARGIN - xtmp = x - # ---------- ---------- ---------- ---------- - - Blender.Draw.BeginAlign() - PREFS['do_material'] = Draw.Toggle('Generate Material',EVENT_UPDATE_AND_UI, xtmp, y, but_width*2, but_height, PREFS['do_material'].val, 'Create material and textures (for seamless joints)'); xtmp += but_width*2; - - if PREFS['do_material'].val: - PREFS['material_use_existing'] = Draw.Toggle('ReUse Existing',EVENT_UPDATE_AND_UI, xtmp, y, but_width*2, but_height, PREFS['material_use_existing'].val, 'Modify the textures of the existing material'); xtmp += but_width*2; - - # ---------- ---------- ---------- ---------- - y-=but_height - xtmp = x - - PREFS['material_texture'] = Draw.Toggle('Texture', EVENT_UPDATE_AND_UI, xtmp, y, but_width*2, but_height, PREFS['material_texture'].val, 'Create an image texture for this material to use'); xtmp += but_width*2; - PREFS['material_stencil'] = Draw.Toggle('Blend Joints', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['material_stencil'].val, 'Use a 2 more texture and UV layers to blend the seams between joints'); xtmp += but_width*2; - Blender.Draw.EndAlign() - - y-=but_height+MARGIN - xtmp = x - # ---------- ---------- ---------- ---------- - - Blender.Draw.BeginAlign() - if PREFS['do_armature'].val == 0: - but_width_tmp = but_width*2 - else: - but_width_tmp = but_width*4 - - Blender.Draw.BeginAlign() - PREFS['do_armature'] = Draw.Toggle('Generate Motion', EVENT_UPDATE_AND_UI, xtmp, y, but_width_tmp, but_height, PREFS['do_armature'].val, 'Generate Armatuer animation and apply to branches'); xtmp += but_width_tmp; - - # ---------- ---------- ---------- ---------- - if PREFS['do_armature'].val: - y-=but_height - xtmp = x - - PREFS['do_anim'] = Draw.Toggle('Texture Anim', EVENT_UPDATE_AND_UI, xtmp, y, but_width*2, but_height, PREFS['do_anim'].val, 'Use a texture to animate the bones'); xtmp += but_width*2; - - if PREFS['do_anim'].val: - - PREFS['anim_tex'] = Draw.String('TEX: ', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['anim_tex'].val, 64, 'Texture to use for the IPO Driver animation', do_tex_check); xtmp += but_width*2; - y-=but_height - xtmp = x - # ---------- ---------- ---------- ---------- - - PREFS['anim_speed'] = Draw.Number('Speed', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['anim_speed'].val, 0.001, 10.0, 'Animate the movement faster with a higher value'); xtmp += but_width*2; - PREFS['anim_magnitude'] = Draw.Number('Magnitude', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['anim_magnitude'].val, 0.001, 10.0, 'Animate with more motion with a higher value'); xtmp += but_width*2; - y-=but_height - xtmp = x - # ---------- ---------- ---------- ---------- - - PREFS['anim_offset_scale'] = Draw.Number('Unique Offset Scale', EVENT_UPDATE, xtmp, y, but_width*4, but_height, PREFS['anim_offset_scale'].val, 0.001, 10.0, 'Use the curve object location as input into the texture so trees have more unique motion, a low value is less unique'); xtmp += but_width*4; - y-=but_height - xtmp = x - - # ---------- ---------- ---------- ---------- - - PREFS['anim_speed_size_scale'] = Draw.Toggle('Branch Size Scales Speed', EVENT_UPDATE, xtmp, y, but_width*4, but_height, PREFS['anim_speed_size_scale'].val, 'Use the branch size as a factor when calculating speed'); xtmp += but_width*4; - - Blender.Draw.EndAlign() - - y-=but_height+MARGIN - xtmp = x - - - - - # ---------- ---------- ---------- ---------- - - Blender.Draw.BeginAlign() - PREFS['do_variation'] = Draw.Toggle('Generate Variation', EVENT_UPDATE_AND_UI, xtmp, y, but_width*2, but_height, PREFS['do_variation'].val, 'Create a variant by moving the branches'); xtmp += but_width*2; - - # ---------- ---------- ---------- ---------- - if PREFS['do_variation'].val: - PREFS['variation_seed'] = Draw.Number('Rand Seed', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['variation_seed'].val, 1, 100000, 'Change this to get a different variation'); xtmp += but_width*2; - y-=but_height - xtmp = x - - - PREFS['variation_orientation'] = Draw.Number('Orientation', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['variation_orientation'].val, 0, 1.0, 'Randomize rotation of the branch around its parent'); xtmp += but_width*2; - PREFS['variation_scale'] = Draw.Number('Scale', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['variation_scale'].val, 0.0, 1.0, 'Randomize the scale of branches'); xtmp += but_width*2; - - Blender.Draw.EndAlign() - - y-=but_height+(MARGIN*2) - xtmp = x - - - - # ---------- ---------- ---------- ---------- - Blender.Draw.BeginAlign() - PREFS['seg_density'] = Draw.Number('Segment Spacing',EVENT_UPDATE, xtmp, y, but_width*4, but_height, PREFS['seg_density'].val, 0.05, 10.0, 'Scale the limit points collapse, that are closer then the branch width'); xtmp += but_width*4; - - y-=but_height - xtmp = x - - # ---------- ---------- ---------- ---------- - PREFS['seg_density_angle'] = Draw.Number('Angle Spacing', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['seg_density_angle'].val, 0.0, 180.0, 'Segments above this angle will not collapse (lower value for more detail)'); xtmp += but_width*2; - PREFS['seg_density_radius'] = Draw.Number('Radius Spacing', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['seg_density_radius'].val, 0.0, 1.0, 'Segments above this difference in radius will not collapse (lower value for more detail)'); xtmp += but_width*2; - - y-=but_height - xtmp = x - # ---------- ---------- ---------- ---------- - - PREFS['seg_joint_compression'] = Draw.Number('Joint Width', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['seg_joint_compression'].val, 0.1, 2.0, 'Edge loop spacing around branch join, lower value for less webed joins'); xtmp += but_width*2; - PREFS['seg_joint_smooth'] = Draw.Number('Joint Smooth', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['seg_joint_smooth'].val, 0.0, 1.0, 'Edge loop spacing around branch join, lower value for less webed joins'); xtmp += but_width*2; - - y-=but_height - xtmp = x - # ---------- ---------- ---------- ---------- - - PREFS['connect_sloppy'] = Draw.Number('Connect Limit',EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['connect_sloppy'].val, 0.1, 3.0, 'Strictness when connecting branches'); xtmp += but_width*2; - PREFS['connect_base_trim'] = Draw.Number('Joint Bevel', EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['connect_base_trim'].val, 0.0, 2.0, 'low value for a tight join, hi for a smoother bevel'); xtmp += but_width*2; - Blender.Draw.EndAlign() - y-=but_height+MARGIN - xtmp = x - - # ---------- ---------- ---------- ---------- - Blender.Draw.BeginAlign() - PREFS['do_cap_ends'] = Draw.Toggle('Cap Ends',EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['do_cap_ends'].val, 'Add faces onto branch endpoints'); xtmp += but_width*2; - PREFS['do_subsurf'] = Draw.Toggle('SubSurf',EVENT_UPDATE, xtmp, y, but_width*2, but_height, PREFS['do_subsurf'].val, 'Enable subsurf for newly generated objects'); xtmp += but_width*2; - Blender.Draw.EndAlign() - y-=but_height+MARGIN - xtmp = x - - - # ---------- ---------- ---------- ---------- - Blender.Draw.BeginAlign() - Draw.PushButton('Read Active Prefs', EVENT_REDRAW, xtmp, y, but_width*2, but_height, 'Read the ID Property settings from the active curve object', do_pref_read); xtmp += but_width*2; - Draw.PushButton('Write Prefs to Sel', EVENT_NONE, xtmp, y, but_width*2, but_height, 'Save these settings in the ID Properties of all selected curve objects', do_pref_write); xtmp += but_width*2; - - y-=but_height - xtmp = x - - # ---------- ---------- ---------- ---------- - Draw.PushButton('Clear Prefs from Sel', EVENT_NONE, xtmp, y, but_width*4, but_height, 'Remove settings from the selected curve aaobjects', do_pref_clear); xtmp += but_width*4; - Blender.Draw.EndAlign() - - y-=but_height+MARGIN - xtmp = x - # ---------- ---------- ---------- ---------- - - Blender.Draw.BeginAlign() - Draw.PushButton('Exit', EVENT_EXIT, xtmp, y, but_width, but_height, ''); xtmp += but_width; - Draw.PushButton('Help', EVENT_NONE, xtmp, y, but_width, but_height, '', do_tree_help); xtmp += but_width; - Draw.PushButton('Generate from selection', EVENT_REDRAW, xtmp, y, but_width*2, but_height, 'Generate mesh', do_tree_generate); xtmp += but_width*3; - Blender.Draw.EndAlign() - y-=but_height+MARGIN - xtmp = x - # ---------- ---------- ---------- ---------- - - GLOBAL_PREFS['realtime_update'] = Draw.Toggle('Automatic Update', EVENT_UPDATE, xtmp, y, but_width*4, but_height, GLOBAL_PREFS['realtime_update'].val, 'Update automatically when settings change'); xtmp += but_width*4; - - - -if __name__ == '__main__': - # Read the active objects prefs on load. if they exist - do_pref_read(quiet=True) - - Draw.Register(gui, evt, bevt) diff --git a/release/scripts/wizard_landscape_ant.py b/release/scripts/wizard_landscape_ant.py deleted file mode 100644 index 405c06432ca..00000000000 --- a/release/scripts/wizard_landscape_ant.py +++ /dev/null @@ -1,2148 +0,0 @@ -#!BPY -""" -Name: 'Landscape Generator (A.N.T)' -Blender: 248 -Group: 'Wizards' -Tip: 'Create landscape mesh.' -""" - -__author__ = "Jimmy Hazevoet" -__url__ = ('http://wiki.blender.org/index.php/Scripts/Manual/Wizards/ANTLandscape','elysiun') -__version__ = "v.1.05 03-2007" -__bpydoc__ = """\ - -Another Noise Tool 'Landscape' v.1.05 - -This script uses noise functions to create a terrain from a grid mesh. - -Usage: - -Make new terrain: press the "Add New Grid" button, change some noise settings and press the "Update" button. - -Work on previous made grid: select the grid/terrain in the 3D view, and press the "Assign" button. - -Tip: use a low resolution grid mesh and add some Multires levels for detail - -Note: when using Multires materials can get weird, -only apply materials when your terrain is ready, or not use Multires. - -This Script creates a landscape mesh. -Press the Auto button when you start the script. -Then the Generate Button & read it's tooltip. -The mesh created is average 16000 verts. -To me the mesh appears quite small in the 3d view. -Just Press S in the 3d view to scale it up. -This saves overhead drawing the Mesh. - -Known Issues: -If the mesh is not drawn in the 3d view first time, -Move your mouse to the 3d view, or press the button again. - -Not really an issue, more to be aware. -Due to the complex nature & design of the script, it only creates one mesh at a time. -When you press Generate or Reset, -Even if you have Closed then Opened the script or .blend file, -The mesh Will be Overwritten. -To create Multiple Landscapes you Must Re-Name or save the Mesh -in Blender's F7 menu Links & Materials Panel. - -Readme: -v.1.04: -_ New G.U.I. -_ New noise types like: -Double_Terrain, -StatsByAlt_Terrain, -slickRock, -ditorted_heteroTerrain, -vlNoise_turbulence, -and many more. - -New fractalized Effect functions. -Effect types such as: gradient, -waves and bumps, dome, piramide, -squares, grid, shattered rocks, -lunar, and many more. - -Bias types: Sin, Cos, Tri, Saw, -and Default(no bias). - -For example the 'Rings' effect -with 'Sin Bias' makes 'Rings' -and 'Default Bias' makes 'Dome'. -The Effect 'Mix factor' Slider gives control over how much of the Effect is vissible, --1.0=noise, 0.0=average, 1.0=effect -this slider controls also the 'Warp amount' if mix type 'Warp' is selected. - -Image effect: mix image with noise -_ IPOCurve Filter: use Ipo curve to filter terrain height. -I know it's a bit strange to use animation curves for landscape modelling, (actualy i want a curves panel in my G.U.I. but i dont know how to do that) -the downside of this method is that you have this 'Empty' moving around in your scene, so put it on another layer and 'Pin' the Ipo block so that it stays visible. -Usage: -Add one 'Empty' Object to your scene, now add one Loc Key at Frame 1, go to Frame 101 (UpArrow ten times), -move the 'Empty' +100 units in X+ direction and add another Loc Key, open the Ipo Curve Editor Window, rename this IpoBlock if you want, -Copie the first curve to buffer and Paste it in the empty slots (from top to bottom), now you can edit the curves freely. -(use the 'Pin' option to keep the curves visible while other objects are selected) -Set the CurveLength and CurveHeight Button value's according to the length and height of the selected curve. -A curve filter is very versatile when it comes to 'height' filtering. - -_ PreView in UV/Image Editor Window: -The preview image is now rendered as Blender.Image and will be saved to file directory as 'ANTview_size.tga' -you have to select 'ANTview_size.tga' in the UV/Image Editor Window -now it's posible to render and save a large HeightMap image (you can also create nice texture images when the VertCol gradient is enabled), -! If you Change the preview image Size a New Blender.Image object is created. (one for size 256, one for size 512 one for.....) ! - -_ VertexColours: use any image as colour gradient. -This function actualy uses one 'row' of pixels from a image to produce the color gradient, -Make one or more custom gradient images with the Gimp or any other graphics software, the gradients must go from left to right (left is bottom and right is top. -you only need one row of pixels so you can put 10 gradients in a 256*10 image.(higher resolutions like 512*n or 1024*n gives smoother result) -Set Window DrawMode 'Textured' , and set the 'VCol Paint' option in the Materials panel ! - -_ Mesh Tiles: Create large scale terrains. - -_ Vertices Selection: select flat areas. - -_ Keyboard HotKeys: -SPACE = Update mesh. -R = Randomise. -V = Redraw preview. - -_ and more... - -""" - - - - -### -# -# Alt+P to start script. -# -### -# scroll down to see info about updates -## -################################################################################################################ -# Another Noise Tool 'Landscape' -# Jimmy Hazevoet -# license: Do whatever you want with it. -################################################################################################################ - -################################################################################################################ -# v.1.04: -# -# _ New G.U.I. -# _ New noise types like: Double_Terrain, StatsByAlt_Terrain, slickRock, ditorted_heteroTerrain, vlNoise_turbulence, and many more. -# _ New fractalized Effect functions. -# Effect types such as: gradient, waves and bumps, dome, piramide, squares, grid, shattered rocks, lunar, and many more. -# Bias types: Sin, Cos, Tri, Saw, and Default(no bias). -# For example the 'Rings' effect with 'Sin Bias' makes 'Rings' and 'Default Bias' makes 'Dome'. -# _ The Effect 'Mix factor' Slider gives control over how much of the Effect is vissible, -1.0=noise, 0.0=average, 1.0=effect -# this slider controls also the 'Warp amount' if mix type 'Warp' is selected. -# _ Image effect: mix image with noise -# _ IPOCurve Filter: use Ipo curve to filter terrain height. -# I know it's a bit strange to use animation curves for landscape modelling, (actualy i want a curves panel in my G.U.I. but i dont know how to do that) -# the downside of this method is that you have this 'Empty' moving around in your scene, so put it on another layer and 'Pin' the Ipo block so that it stays visible. -# Usage: -# Add one 'Empty' Object to your scene, now add one Loc Key at Frame 1, go to Frame 101 (UpArrow ten times), -# move the 'Empty' +100 units in X+ direction and add another Loc Key, open the Ipo Curve Editor Window, rename this IpoBlock if you want, -# Copie the first curve to buffer and Paste it in the empty slots (from top to bottom), now you can edit the curves freely. -# (use the 'Pin' option to keep the curves visible while other objects are selected) -# Set the CurveLength and CurveHeight Button value's according to the length and height of the selected curve. -# A curve filter is very versatile when it comes to 'height' filtering. -# _ PreView in UV/Image Editor Window: -# The preview image is now rendered as Blender.Image and will be saved to file directory as 'ANTview_size.tga' -# you have to select 'ANTview_size.tga' in the UV/Image Editor Window -# now it's posible to render and save a large HeightMap image (you can also create nice texture images when the VertCol gradient is enabled), -# ! If you Change the preview image Size a New Blender.Image object is created. (one for size 256, one for size 512 one for.....) ! -# _ VertexColours: use any image as colour gradient. -# This function actualy uses one 'row' of pixels from a image to produce the color gradient, -# Make one or more custom gradient images with the Gimp or any other graphics software, the gradients must go from left to right (left is bottom and right is top. -# you only need one row of pixels so you can put 10 gradients in a 256*10 image.(higher resolutions like 512*n or 1024*n gives smoother result) -# Set Window DrawMode 'Textured' , and set the 'VCol Paint' option in the Materials panel ! -# _ Mesh Tiles: Create large scale terrains. -# _ Vertices Selection: select flat areas. -# _ Keyboard HotKeys: -# SPACE = Update mesh. -# R = Randomise. -# V = Redraw preview. -# _ and more... -################################################################################################################ - -################################################################################################################ -# BugFix: Sept./2006 v.1.04a -#----------------------------- -# _Image Effect did not worked well with tiled mesh. Fixed (now use Freq. and Loc. buttons to scale and position image). -# -################################################################################################################ - - -################################################################################################################ -# UPDATE: v.1.05 03-2007 -#--------------------------------------------------------------------------------------------------------------- -# -# _ New: Save and Load function, save your settings to a .ant file. -# __NOTE: when saving/loading settings to/from a file, -# make sure the filename/path is not too long! -# __HOTKEY__ Load from file: L -# __HOTKEY__ Save to file : S -# -# _ New mesh code, uses Mesh instead of NMesh, -# this gives a small speed improvement and alows you to use Multires. -# -# Usage: Select a Grid/Terrain mesh and hit the Assign button, now you can work on it, when ready you assign another. -# -# _ New: 'Musgrave' noise types, 'Random noise' and 'Constant' in 'Effects' section. -# _ New: 'Custom Effect', write custom formulae ( x,y, a,b, from math import *, from Blender.Noise import * ) -# _ New: 'Custom Height Filter', write custom formulae ( x,y, h, a,b, from math import *, from Blender.Noise import * ) -# _ New: 'Change Filter Order', Toggle: OFF = Noise+Effect+Falloff+FILTER / ON = Noise+FILTER+Effect+Falloff -# -# _ If you want to make a tiled terrain, you need to set the coordinates to "WorldSpace" or "Center at Cursor" (in G.U.I.Noise panel), -# create and place the grid meshes. now one by one select, assign and update, you may need to adjust the "EdgeFalloff" size. -# -# WARNING!: when using Multires, materials can get weird (?), so apply materials when your terrain is finnished. -# -############################################################################################################### - - -############################################################################################################### -# -## Execute Script: Alt P -# - - -import Blender -from Blender import * -from math import * -from Blender.Noise import * -from Blender.Draw import * -from Blender.BGL import * -from Blender import Image -import string -from string import strip -import BPyMathutils -from BPyMathutils import genrand -from random import choice -scene = Scene.GetCurrent() - -###--------------------------------------------------------------------------- - -CurVersion = 'A.N.T.Landscape v.1.05' - -##--------------------------------------------------------------------------- -# Customise default settings: ---------------------------------------------- - -# Names: -antfilename = 'Terrain' # Default filename -previewname = Create('') # Default preview Image name -DefaultIpoName = '' # Default Ipo DataBlock name (for height filter) -# G.U.I.: -FullScreen = Create( 0 ) # FullScreen on/off -# gui colors: -ledcolors = [ [1.0,0.498,0.498], [1.0,0.698,0.498], [1.0,0.898,0.498], [0.898,1.0,0.498], [0.698,1.0,0.498], [0.498,1.0,0.498], [0.498,1.0,0.698], [0.498,1.0,0.898], [0.600,0.918,1.0], [0.6,0.757,1.0], [0.6,0.6,1.0], [0.757,0.6,1.0], [0.898,0.498,1.0], [1.0,0.498,0.898] ] -#ledcolor = [ 1.0, 0.5, 0.0 ] -lightgrey = [ 0.76, 0.76, 0.76 ] # gui col. -grey = [ 0.6, 0.6, 0.6 ] # panel col. -background = [ 0.7, 0.7, 0.7, 1.0 ] # background col. -black = [ 0.0, 0.0, 0.0 ] # text col. -white = [ 1.0, 1.0, 1.0 ] -# gui size -size_x = 320 # gui x size -size_y = 280 # gui y size -# tabs -guitabs = [ Create( 1 ), Create( 0 ), Create( 0 ), Create( 0 ), Create( 0 ) ] # gui Tabs -# How long does it take to generate a mesh or image ? -print_time = 0 # 1 = Print time in console. - -# end customise. ---------------------------------------------------------- -##-------------------------------------------------------------------------- -###-------------------------------------------------------------------------- -####-------------------------------------------------------------------------- -##--------------------------------------------------------------------------- - -dirpath=Blender.sys.dirname(Blender.Get('filename')) -fname=dirpath.replace('\\','/')+'/' + antfilename + '.ant' -txtFile = Create( fname ) - -###--------------------------------------------------------------------------- -columns = 10 # gui columns -rows = 13 # gui rows -actob = [] # active object -actme = [] # active mesh -ipoblockname='' -thiscurve=[] -selectedcurve=0 -phi=3.14159265359 -# events -App_Evt = 144 -New_Evt = 166 -SelFile_Evt = 71 -LoadFile_Evt = 72 -SaveFile_Evt = 73 -UseMe_Evt = 74 -No_Evt = 1 -Btn_Evt = 2 -Msh_Evt = 12 -Upd_Evt = 3 -Rndm_Evt = 4 -Load_Evt = 5 -Sel_Evt = 6 -Save_Evt = 7 -Rend_Evt = 8 -End_Evt = 9 -Scrn_Evt = 15 -Im_Evt = 16 -gt0_Evt = 20 -gt1_Evt = 21 -gt2_Evt = 22 -gt3_Evt = 23 -gt4_Evt = 24 -Ipo_Evt = 17 -New_Ipo_Evt=700 - -###--------------------------------------------------------------------------- -# menus -noisetypemenu = "Noise type: %t|multiFractal %x0|ridgedMFractal %x1|hybridMFractal %x2|heteroTerrain %x3|fBm %x4|turbulence %x5|Voronoi turb. %x6|vlNoise turb. %x7|noise %x8|cellNoise %x9|Marble %x10|lava_multiFractal %x11|slopey_noise %x12|duo_multiFractal %x13|distorted_heteroTerrain %x14|slickRock %x15|terra_turbulence %x16|rocky_fBm %x17|StatsByAlt_Terrain %x18|Double_Terrain %x19|Shattered_hTerrain %x20|vlhTerrain %x21" -noisebasismenu = "Basis %t|Blender Original%x0|Original Perlin%x1|Improved Perlin%x2|Voronoi_F1%x3|Voronoi_F2%x4|Voronoi_F3%x5|Voronoi_F4%x6|Voronoi_F2-F1%x7|Voronoi Crackle%x8|CellNoise%x9" -voronitypemenu = "Voronoi type %t|Distance %x0|Distance Squared %x1|Manhattan %x2|Chebychev %x3|Minkovsky 1/2 %x4|Minkovsky 4 %x5|Minkovsky %x6" -tBasismodemenu = "Terrain basis mode: %t|noise %x0|ridged noise %x1|vlNoise %x2|ridged vlNoise %x3" -effecttypemenu = ['Effect Type %t','No Effect %x0','Image %x1','Turbulence %x2','vlNoise %x3','Marble %x4', 'multiFractal %x5','ridgedMFractal %x6','hybridMFractal %x7','heteroTerrain %x8','fBm %x9', 'Gradient %x10','Waves and Bumps %x11','ZigZag %x12','Wavy %x13','Sine Bump %x14','Dots %x15','Rings / Dome %x16','Spiral %x17','Square / Piramide %x18','Blocks %x19','Grid %x20','Tech %x21','Crackle %x22','Sparse Cracks %x23','Shattered Rocks %x24','Lunar %x25','Cosine noise %x26','Spike noise %x27','Stone noise %x28','Flat Turb %x29','Flat Voroni %x30','Random noise %x31','Constant %x32','Custom Effect %x33' ] -mixtypemenu = ['Mix Type %t','Effect only %x0','%l','Mix %x1','Add %x2','Subtract %x3','Multiply %x4','Difference %x5','Screen %x6','addmodulo %x7','Minimum %x8','Maximum %x9','%l','Warp Effect %x10','Warp Noise %x11'] -biastypemenu = "Bias %t|Sin bias %x0|Cos bias %x1|Tri bias %x2|Saw bias %x3|Default (no bias)%x4" -sharptypemenu = "Sharpen %t|Soft %x0|Sharp %x1|Sharper %x2" -filtermodemenu = "Filter Mode %t|No Filter %x0| %l|Default Filters %x1|IPOCurve Filter %x2|Custom Filter %x3" -filtertypemenu = "Filter Type %t|Default Terrace %x0|Sharper Terrace %x1|Rounded Terrace %x2|Posterise Mixed %x3|Posterise %x4|Layered Peaks %x5|Peaked %x6|Smooth-thing %x7|Sin bias %x8|Cos bias %x9|Tri bias %x10|Saw bias %x11|Clamp Max. %x12" -falloftypemenu = "Edge Falloff %t|No Edge Falloff %x0| %l|Soft Falloff %x1|Default Falloff %x2|Hard Falloff %x3|Linear Falloff Y %x4|Linear Falloff X %x5|Diagonal Falloff + %x6|Diagonal Falloff - %x7|Square %x8|Round %x9" -randomtypemenu = "Random type: %t|setRandomSeed() : Blender.Noise %x0|Rand() : Blender.Mathutils %x1|genrand() : BPyMathutils MersenneTwister %x2" - -##-------------------------------------------------- -def Set_ReSet_Values(): - global fileinfo, filemessage - global iScale, Offset, Invert, NSize, Sx, Sy, Lx, Ly, WorldSpaceCo - global NType, Basis, musgr, vlnoi, vlnoiTwo, voron, turbOne, turbTwo, marbleOne, marbleTwo, tBasismod, musgrTwo - global CustomFX, effect_image, Effect_Ctrl, Min, Max, Falloff, CustomFilt, Filter_Mode, Def_Filter_Ctrl, Ipo_Filter_Ctrl, Filter_Order - global RandMod, RSeed, rand_H, rand_S, rand_L, rand_I, AutoUpd, PreView, DefaultIpoName - - filemessage = '' - fileinfo = '' - effect_image = 'Load and Select image.' - AutoUpd = Create( 0 ) - PreView = [ Create( 0 ), Create( 1.0 ), Create( 0.0 ) ] - ## Coords controls: - WorldSpaceCo = Create(0) - iScale = [ Create( 1.0 ), Create( 1.0 ), Create( 0.25) ] - Offset = [ Create( 0.0 ), Create( 0.0), Create( 0.0) ] - Invert = [ Create( 0 ), Create( 0 ), Create( 0 ) ] - NSize = [ Create( 1.0 ), Create( 2.0 ) ] - Sx = [ Create( 1.0 ), Create( 1.0 ) ] - Sy = [ Create( 1.0 ), Create( 1.0 ) ] - Lx = [ Create( 0.0 ), Create( 0.0 ) ] - Ly = [ Create( 0.0 ), Create( 0.0 ) ] - ## Noise controls: - NType = Create( 3 ) - Basis = [ Create( 0 ), Create( 0 ) ] - musgr = [ Create( 1.0 ), Create( 2.0 ), Create( 8 ), Create( 1.0 ), Create( 1.0 ), Create( 0.5 ) ] - vlnoi = [ Create( 1.0 ), Create( 0 ) ] - vlnoiTwo = [ Create( 1.0 ), Create( 0 ) ] - voron = [ Create( 0 ), Create( 2.5 ) ] - turbOne = [ Create( 6 ), Create( 0 ), Create( 0.5 ), Create( 2.0 ) ] - marbleOne = [ Create( 6 ), Create( 0 ), Create( 2.0 ), Create( 0 ), Create( 0 ), Create( 1.0 ) ] - tBasismod = Create(0) - ## Effect controls: - musgrTwo = [ Create( 1.0 ), Create( 2.0 ), Create( 8 ), Create( 1.0 ), Create( 1.0 ) ] - turbTwo = [ Create( 6 ), Create( 0 ), Create( 0.5 ), Create( 2.0 ) ] - marbleTwo = [ Create( 6 ), Create( 0 ), Create( 2.0 ), Create( 0 ), Create( 0 ), Create( 1.0 ) ] - Effect_Ctrl = [ Create( 0 ),Create( 2 ),Create( 0.0 ),Create( 0 ),Create( 0.0 ) ,Create( 0 ),Create( 2.0 ),Create( 0.5 ),Create( 0.5 ) ] - CustomFX = [ Create('sin(x*pi)'), Create('cos(y*pi)'), Create('abs(a*b)*0.5') ] - ## Filter controls: - Min = Create( 0.0 ) - Max = Create( 1.0 ) - Falloff = [ Create( 2 ), Create( 1.0 ), Create( 1.0 ), Create( 0 ) , Create( 0 ) ] - Filter_Mode = Create( 0 ) - Def_Filter_Ctrl = [ Create( 0 ), Create( 3.0 ) ] - Ipo_Filter_Ctrl = [ Create( DefaultIpoName ), Create( 0 ), Create( 100.0 ), Create( 100.0 ) ] - Filter_Order = Create( 0 ) - CustomFilt = [ Create('sqrt(h*h)**2'), Create('0'), Create('a') ] - ## Randomise noise buttons: - RandMod = Create( 1 ) - RSeed = Create( 0 ) - rand_I = Create( 0 ) - rand_H = Create( 0 ) - rand_S = Create( 0 ) - rand_L = Create( 1 ) - -##------------------------- -Set_ReSet_Values() - - -####---------------------------------------------------------------------------------------------------- -###---------------------------------------------------------------------------------------------------- -## G.U.I.: text,backpanel,panel -#-------------------------------------------------- -def draw_Text( ( x, y ), text, color, size ): - glColor3f( color[0],color[1],color[2] ) - glRasterPos2d(x,y) - txtsize = 'small', 'normal', 'large' - Text( text, txtsize[ size ] ) -def draw_BackPanel( text, x, y, w, h, colors ): - glColor3f( colors[0]*0.76, colors[1]*0.76, colors[2]*0.76 ) - glRecti( x, h, w, h+20 ) - glColor3f( colors[0], colors[1], colors[2] ) - glRecti( x, y, w, h ) - glColor3f( colors[0], colors[1], colors[2] ) - glRasterPos2d( x+10, h+5 ) - Text( text, 'small' ) -def draw_Panel( x, y, w, h, colors ): - glColor3f( colors[0], colors[1], colors[2] ) - glRecti( x,y, w,h ) -def draw_Frame( text, x, y, w, h, color ): - glColor3f( color[0], color[1], color[2] ) - glRasterPos2i(x+3,h-3) - Text(text ,'small') - stringwidth = GetStringWidth( text,'small' ) - glColor3f( color[0], color[1], color[2] ) - glBegin(Blender.BGL.GL_LINE_STRIP) - glVertex2i(x,h) - glVertex2i(x,y) - glVertex2i(w,y) - glVertex2i(w,h) - glVertex2i(x+stringwidth+10,h) - glEnd() -def draw_Led( x, y, colors ): - glColor3f( colors[0], colors[1], colors[2] ) - glRecti( x,y, x+4,y+4 ) - - -###---------------------------------------------------------------------------------------------------- -## G.U.I. Buttons: -#---------------------------------------------------------------------------------------------------- - -###------------------------- -## Main / Mesh Buttons: -# -def MeshButtons( col, row, width, height ): - global actme, actob, AutoUpd, txtFile, filemessage, fileinfo - - PushButton("I", UseMe_Evt, col[8], row[3], width[0], height[1], "Info: Here you can write some text to save with the file." ) - draw_Text( ( col[0], row[1]+5 ), 'Info: ' + fileinfo, black, 0 ) - txtFile = String("", No_Evt, col[0], row[2], width[9], height[1], txtFile.val, 256, "File: Full path and filename" ) - PushButton( "Select", SelFile_Evt, col[1], row[3], width[0], height[1], "File: Open FileBrowser and select *.ant file" ) - PushButton( "Load", LoadFile_Evt,col[2], row[3], width[2], height[1], "File: Load settings from file ( HotKey: L )" ) - PushButton( "Save", SaveFile_Evt,col[5], row[3], width[2], height[1], "File: Save settings to file ( HotKey: S )" ) - - activeobname = '' - if actme !=[]: - activeobname = actob[0].name - draw_Text( ( col[5]+5, row[7]-5 ), 'OB: ' + activeobname, [0.0,0.0,1.0], 1 ) - PushButton( "Add New Grid", New_Evt, col[0], row[6], width[4], height[2] ) - PushButton( "Assign Selected", App_Evt, col[5], row[6], width[4], height[2], 'Assign selected terrain') - -###------------------------- -## Noise Buttons: -# -def NoiseButtons( col, row, width, height ): - global NSize, iScale, Offset, Invert, Lx, Ly, Sx, Sy, WorldSpaceCo - global Ha, La, Oc, Of, Ga, Basis, NType, musgr, vlnoi, voron, turbOne, tBasismod - global Depth, Hard, Amp, Freq, vlBasis, Distort, VFunc, VExp, VDep, marbleOne - global RandMod, RSeed, rand_H, rand_S, rand_L, rand_I - - bth = height[1]/2+5 - iScale[0] = Number("iScale:", Btn_Evt, col[5], row[2]+bth, width[3], height[1], iScale[0].val, -10.0, 10.0 , "Noise: Intensity Scale." ) - Invert[0] = Toggle("Inv.", Btn_Evt, col[9], row[2]+bth, width[0], height[1], Invert[0].val, "Noise: Invert") - Offset[0] = Number("Offset:", Btn_Evt, col[5], row[3]+bth, width[4], height[1], Offset[0].val, -10.0, 10.0 , "Noise: Offset " ) - NSize[0] = Number("Noise Size:",Btn_Evt, col[5], row[5], width[4], height[2], NSize[0].val, 0.001, 10.0 , "Noise Size" ) - Sx[0] = Number("Size X:", Btn_Evt, col[5], row[6], width[4], height[1], Sx[0].val, 0.001, 10.0 , "Size X" ) - Sy[0] = Number("Size Y:", Btn_Evt, col[5], row[7], width[4], height[1], Sy[0].val, 0.001, 10.0 , "Size Y" ) - Lx[0] = Number("Loc X:", Btn_Evt, col[5], row[8], width[4], height[1], Lx[0].val, -10000.0, 10000.0 , "Loc X" ) - Ly[0] = Number("Loc Y:", Btn_Evt, col[5], row[9],width[4], height[1], Ly[0].val, -10000.0, 10000.0 , "Loc Y" ) - WorldSpaceCo = Menu( "Coordinates %t|Local Space %x0|World Space %x1|Center at CursorPos %x2", Btn_Evt, col[5], row[10], width[4], height[1], WorldSpaceCo.val, "x,y,z coordinates for noise, effect and height falloff " ) - - NType = Menu( noisetypemenu, Btn_Evt, col[0], row[2], width[4], height[2], NType.val, "Noise type" ) - if NType.val == 6: - voron[0] = Menu( voronitypemenu, Btn_Evt, col[0], row[3], width[4], height[1], voron[0].val, "Voronoi type" ) - else: - if NType.val != 9: - Basis[0] = Menu( noisebasismenu, Btn_Evt, col[0], row[3], width[4], height[1], Basis[0].val, "Noise Basis" ) - - if NType.val in [0,1,2,3,4,11,12,13,14,15,17,18,19,20,21]: - musgr[0] = Slider( "H: ", Btn_Evt, col[0], row[5], width[4], height[1], musgr[0].val, 0.0, 3.0, 0 , "H" ) - musgr[1] = Slider( "Lacu: ", Btn_Evt, col[0], row[6], width[4], height[1], musgr[1].val, 0.0, 6.0, 0 , "Lacunarity" ) - musgr[2] = Slider( "Octs: ", Btn_Evt, col[0], row[4], width[4], height[1], musgr[2].val, 0, 12, 0 , "Octaves" ) - if NType.val in [1,2,3,13,14,15,18,19,20,21]: - musgr[3] = Slider( "Offst: ", Btn_Evt, col[0], row[7], width[4], height[1], musgr[3].val, 0.0, 6.0, 0 , "Offset" ) - if NType.val in [1,2,13,15,18]: - musgr[4] = Slider( "Gain: ", Btn_Evt, col[0], row[8], width[4], height[1], musgr[4].val, 0.0, 6.0, 0 , "Gain" ) - if NType.val == 19: - musgr[5] = Slider( "Thresh: ", Btn_Evt, col[0], row[8], width[4], height[1], musgr[5].val, 0.001, 2.0, 0 , "Threshold" ) - if NType.val in [5,6,7,16]: - turbOne[0] = Number( "Depth:", Btn_Evt, col[0], row[4], width[4], height[1], turbOne[0].val, 0, 12, "Octaves") - turbOne[1] = Toggle( "Hard noise", Btn_Evt, col[0], row[5], width[4], height[1], turbOne[1].val, "Soft noise / Hard noise") - turbOne[2] = Slider( "Amp:", Btn_Evt, col[0], row[6], width[4], height[1], turbOne[2].val, 0.0, 3.0, 0, "Ampscale ") - turbOne[3] = Slider( "Freq:", Btn_Evt, col[0], row[7], width[4], height[1], turbOne[3].val, 0.0, 6.0, 0, "Freqscale") - if NType.val in [18,19]: - tBasismod = Menu( tBasismodemenu, Btn_Evt, col[0], row[9], width[4], height[1], tBasismod.val, "Terrain basis mode.") - if NType.val == 6: - if voron[0].val == 6: - voron[1] = Slider( "Exp: ", Btn_Evt, col[0], row[8], width[4], height[1], voron[1].val, 0.0,10.0, 0, "Minkovsky exponent") - if NType.val in [7,11,12,14,20,21]: - vlnoi[0] = Slider( "Dist: ", Btn_Evt, col[0], row[8], width[4], height[1], vlnoi[0].val, 0.0, 10.0, 0 , "Distort" ) - if NType.val in [7,13,14,15,21]: - vlnoi[1] = Menu(noisebasismenu, Btn_Evt, col[0], row[9], width[4], height[1], vlnoi[1].val, "Distortion Noise") - if NType.val == 10: - marbleOne[0] = Number( "Depth: ", Btn_Evt, col[0], row[6], width[4], height[1], marbleOne[0].val, 0, 12, "Octaves") - marbleOne[2] = Slider( "Turb: ", Btn_Evt, col[0], row[7], width[4], height[1], marbleOne[2].val, 0.0,20.0, 0, "Turbulence ") - marbleOne[3] = Menu( biastypemenu, Btn_Evt ,col[0], row[4], width[4], height[1], marbleOne[3].val, "Bias") - marbleOne[5] = Slider("ReScale: ", Btn_Evt, col[0], row[8], width[4], height[1], marbleOne[5].val, 0.0,20.0, 0, "ReScale") - if marbleOne[3].val != 4: - marbleOne[4] = Menu(sharptypemenu, Btn_Evt ,col[0], row[5], width[4], height[1], marbleOne[4].val, "Sharpen") - - RandMod = Menu( randomtypemenu, No_Evt, col[0], row[10], width[0], height[1], RandMod.val, "Random Type" ) - rand_H = Toggle("TH",No_Evt ,col[1], row[10], width[0], height[1], rand_H.val, "Randomise Terrain Height ( in Height panel )") - rand_I = Toggle("NH",No_Evt ,col[2], row[10], width[0], height[1], rand_I.val, "Randomise Noise Height") - rand_S = Toggle("NS",No_Evt ,col[3], row[10], width[0], height[1], rand_S.val, "Randomise Noise Size") - rand_L = Toggle("NL",No_Evt ,col[4], row[10], width[0], height[1], rand_L.val, "Randomise Noise Location") - -###------------------------- -## Effect Buttons: -# -def EffectButtons( col, row, width, height ): - global Effect_Type, Effect_Ctrl, Blend_Effect, CustomFX - global NSize, iScale, Offset, Invert, Lx, Ly, Sx, Sy - global BasisTwo, turbTwo, marbleTwo, vlnoiTwo, musgrTwo - - Effect_Ctrl[0] = Menu( '|'.join( effecttypemenu ), Btn_Evt, col[0], row[2], width[4], height[2], Effect_Ctrl[0].val, "Effect: Type" ) - if Effect_Ctrl[0].val != 0: - Effect_Ctrl[1] = Menu( '|'.join( mixtypemenu ), Btn_Evt, col[5], row[2], width[4], height[2], Effect_Ctrl[1].val, "Mix: Type" ) - if Effect_Ctrl[1].val in [10,11]: - Effect_Ctrl[2] = Slider("Warp: ", Btn_Evt, col[5], row[3], width[4], height[1], Effect_Ctrl[2].val, -1.0, 1.0, 0, "Mix factor / Warp amount" ) - else: Effect_Ctrl[2] = Slider("Mix: ",Btn_Evt, col[5], row[3], width[4], height[1], Effect_Ctrl[2].val, -1.0, 1.0, 0, "Mix factor / Warp amount" ) - - iScale[1] = Number("iScale:", Btn_Evt, col[5], row[4], width[3], height[1], iScale[1].val, -20.0, 20.0 , "Effect: Intensity Scale " ) - Invert[1] = Toggle("Inv.", Btn_Evt, col[9], row[4], width[0], height[1], Invert[1].val, "Effect: Invert") - Offset[1] = Number("Offset:", Btn_Evt, col[5], row[5], width[4], height[1], Offset[1].val, -20.0, 20.0 , "Effect: Offset " ) - NSize[1] = Number("Frequency:",Btn_Evt, col[5], row[6], width[4], height[1], NSize[1].val, 0.001, 100.0, "Effect Frequency ( Scale )" ) - Sx[1] = Number("Freq X:", Btn_Evt, col[5], row[7], width[4], height[1], Sx[1].val, -50.0, 50.0 , "Effect Frequency X ( ScaleX )" ) - Sy[1] = Number("Freq Y:", Btn_Evt, col[5], row[8], width[4], height[1], Sy[1].val, -50.0, 50.0 , "Effect Frequency Y ( ScaleY )" ) - Lx[1] = Number("Loc X:", Btn_Evt, col[5], row[9], width[4], height[1], Lx[1].val, -1000.0, 1000.0 , "Effect Loc X" ) - Ly[1] = Number("Loc Y:", Btn_Evt, col[5], row[10], width[4], height[1], Ly[1].val, -1000.0, 1000.0 , "Effect Loc Y" ) - - if Effect_Ctrl[0].val == 1: - PushButton("Load Image", Load_Evt, col[0], row[4], width[4], height[2] , "Load Image") - PushButton("Select Image", Sel_Evt, col[0], row[6], width[4], height[3] , "Select Image") - draw_Text( ( col[0]+5, row[7] ), effect_image, black, 1 ) - - if Effect_Ctrl[0].val in [2,3,4,5,6,7,8,9]: - Basis[1] = Menu( noisebasismenu, Btn_Evt, col[0], row[3], width[4], height[1], Basis[1].val, "Basis" ) - - if Effect_Ctrl[0].val == 2: - turbTwo[0] = Number( "Depth:", Btn_Evt, col[0], row[4], width[4], height[1], turbTwo[0].val, 1, 12, "Octaves") - turbTwo[1] = Toggle("Hard noise", Btn_Evt, col[0], row[5], width[4], height[1], turbTwo[1].val, "Hard noise") - turbTwo[2] = Slider( "Amp:", Btn_Evt, col[0], row[6], width[4], height[1], turbTwo[2].val, 0.0, 3.0, 0, "Ampscale ") - turbTwo[3] = Slider( "Freq:", Btn_Evt, col[0], row[7], width[4], height[1], turbTwo[3].val, 0.0, 6.0, 0, "Freqscale") - if Effect_Ctrl[0].val == 3: - vlnoiTwo[1] = Menu(noisebasismenu, Btn_Evt, col[0], row[4], width[4], height[1], vlnoiTwo[1].val, "Distortion Noise") - vlnoiTwo[0] = Slider( "Dist: ", Btn_Evt, col[0], row[5], width[4], height[1], vlnoiTwo[0].val, 0.0, 10.0, 0 , "Distort" ) - if Effect_Ctrl[0].val == 4: - marbleTwo[0] = Number( "Depth: ", Btn_Evt, col[0], row[6], width[4], height[1], marbleTwo[0].val, 1, 12, "Octaves") - marbleTwo[2] = Slider( "Turb: ", Btn_Evt, col[0], row[7], width[4], height[1], marbleTwo[2].val, 0.0,20.0, 0, "Turbulence") - marbleTwo[3] = Menu( biastypemenu, Btn_Evt ,col[0], row[4], width[4], height[1], marbleTwo[3].val, "Bias") - marbleTwo[5] = Slider("ReScale: ", Btn_Evt, col[0], row[8], width[4], height[1], marbleTwo[5].val, 0.0,20.0, 0, "ReScale") - if marbleTwo[3].val != 4: - marbleTwo[4] = Menu(sharptypemenu,Btn_Evt ,col[0], row[5], width[4], height[1], marbleTwo[4].val, "Sharpen") - - if Effect_Ctrl[0].val in [5,6,7,8,9]: - musgrTwo[0] = Slider( "H: ", Btn_Evt, col[0], row[5], width[4], height[1], musgrTwo[0].val, 0.0, 3.0, 0 , "H" ) - musgrTwo[1] = Slider( "Lacu: ", Btn_Evt, col[0], row[6], width[4], height[1], musgrTwo[1].val, 0.0, 6.0, 0 , "Lacunarity" ) - musgrTwo[2] = Slider( "Octs: ", Btn_Evt, col[0], row[4], width[4], height[1], musgrTwo[2].val, 0, 12, 0 , "Octaves" ) - if Effect_Ctrl[0].val in [6,7,8]: - musgrTwo[3] = Slider( "Offst: ", Btn_Evt, col[0], row[7], width[4], height[1], musgrTwo[3].val, 0.0, 6.0, 0 , "Offset" ) - if Effect_Ctrl[0].val in [6,7]: - musgrTwo[4] = Slider( "Gain: ", Btn_Evt, col[0], row[8], width[4], height[1], musgrTwo[4].val, 0.0, 6.0, 0 , "Gain" ) - - if Effect_Ctrl[0].val > 9 and Effect_Ctrl[0].val < 31: - Effect_Ctrl[5] = Number("Depth:", Btn_Evt, col[0], row[4], width[4], height[1], Effect_Ctrl[5].val, 0, 12 , "Fractalize Effect: Octaves" ) - Effect_Ctrl[4] = Number("Distort:",Btn_Evt, col[0], row[7], width[4], height[1], Effect_Ctrl[4].val, 0.0, 50.0 , "Distort Effect: Amount" ) - Effect_Ctrl[6] = Slider("Freq:", Btn_Evt, col[0], row[5], width[4], height[1], Effect_Ctrl[6].val, 0.0, 6.0, 0, "Fractalize Effect: Frequency" ) - Effect_Ctrl[7] = Slider("Amp:", Btn_Evt, col[0], row[6], width[4], height[1], Effect_Ctrl[7].val, 0.0, 3.0, 0, "Fractalize Effect: Amplitude" ) - if Effect_Ctrl[0].val < 22: - Effect_Ctrl[3] = Menu(biastypemenu, Btn_Evt ,col[0], row[3], width[4], height[1], Effect_Ctrl[3].val, "Effect bias") - if Effect_Ctrl[0].val in [31,32]: - Effect_Ctrl[8] = Number("Amount:", Btn_Evt, col[0], row[4], width[4], height[1], Effect_Ctrl[8].val, -20.0, 20.0, "Effect: Amount" ) - if Effect_Ctrl[0].val == 33: - draw_Text( ( col[0]+5, row[4] ), 'Custom math ( h, x,y, a,b )' , black, 0 ) - CustomFX[0] = String( "a = ", Btn_Evt, col[0], row[5], width[4], height[1] ,CustomFX[0].val,96, "a" ) - CustomFX[1] = String( "b = ", Btn_Evt, col[0], row[6], width[4], height[1] ,CustomFX[1].val,96, "b" ) - CustomFX[2] = String( "result = ", Btn_Evt, col[0], row[7], width[4], height[1] ,CustomFX[2].val,96, "result" ) - -###------------------------- -## Filter / Height Buttons: -# -def FilterButtons( col, row, width, height ): - global iScale, Offset, Invert, Min, Max, Falloff, CustomFilt - global Filter_Mode, Def_Filter_Ctrl, Ipo_Filter_Ctrl, DefaultIpoName, Filter_Order - - iScale[2] = Number("Height:", Btn_Evt, col[5], row[2], width[3], height[2], iScale[2].val, -10.0, 10.0 , "Terrain Height: Scale" ) - Invert[2] = Toggle("Inv.", Btn_Evt, col[9], row[2], width[0], height[2], Invert[2].val, "Terrain Height: Invert") - Offset[2] = Number("Offset:", Btn_Evt, col[5], row[3], width[4], height[1], Offset[2].val, -10.0, 10.0 , "Terrain Height: Offset" ) - Max = Number( "Plateau:", Btn_Evt, col[5], row[5], width[4], height[1], Max.val, Min.val, 1.0 , "Terrain Height: Clamp Max. ( Plateau )" ) - Min = Number( "Sealevel:", Btn_Evt, col[5], row[6], width[4], height[1], Min.val, -1.0, Max.val , "Terrain Height: Clamp Min. ( Sealevel )" ) - Falloff[0] = Menu( falloftypemenu, Btn_Evt ,col[5], row[9], width[4], height[2], Falloff[0].val, "Terrain Height: Edge falloff") - if Falloff[0].val !=0: - Falloff[1] = Number("X:", Btn_Evt, col[5], row[10], width[1], height[1], Falloff[1].val , 0.01, 100.0 , "Edge falloff: X Size" ) - Falloff[2] = Number("Y:", Btn_Evt, col[8], row[10], width[1], height[1], Falloff[2].val , 0.01, 100.0 , "Edge falloff: Y Size" ) - Falloff[4] = Toggle("Inv.", Btn_Evt, col[7], row[10], width[0], height[1], Falloff[4].val, "Edge falloff: Invert") - Falloff[3] = Toggle("Edge At Sealevel", Btn_Evt, col[5], row[7], width[4], height[1], Falloff[3].val, "Edge falloff: Edge at Sealevel") - - Filter_Mode = Menu( filtermodemenu, No_Evt, col[0], row[2], width[4], height[2], Filter_Mode.val, "Filter: Mode") - if Filter_Mode.val ==1: - Def_Filter_Ctrl[0] = Menu( filtertypemenu, Btn_Evt, col[0], row[5], width[4], height[2], Def_Filter_Ctrl[0].val, "Filter: Type") - Def_Filter_Ctrl[1] = Number("Amount: ", Btn_Evt, col[0], row[6], width[4], height[1], Def_Filter_Ctrl[1].val, 0.1, 100.0 , "Filter: Amount" ) - - if Filter_Mode.val ==2: - Ipo_Filter_Ctrl[0] = String("IP:", Ipo_Evt, col[0], row[5], width[4], height[2], Ipo_Filter_Ctrl[0].val,20, "Ipo datablock name" ) - if Ipo_Filter_Ctrl[0].val !='': - Ipo_Filter_Ctrl[1] = Number("Use This Curve:",Ipo_Evt, col[0], row[7], width[4], height[3], Ipo_Filter_Ctrl[1].val, 0, 29, "Select curve to use" ) - Ipo_Filter_Ctrl[2] = Number("Curve Length:", Ipo_Evt, col[0], row[8], width[4], height[1], Ipo_Filter_Ctrl[2].val, 0.0, 1000.0, "X: Length (number of frames) of the selected curve." ) - Ipo_Filter_Ctrl[3] = Number("Curve Height:", Ipo_Evt, col[0], row[9], width[4], height[1], Ipo_Filter_Ctrl[3].val, 0.0, 1000.0, "Y: Height (offset) of the selected curve." ) - else: - draw_Text( ( col[0]+5, row[6] ), 'Enter Ipo DataBlock name,' , black, 0 ) - draw_Text( ( col[0]+5, row[9] ), 'or else:' , black, 0 ) - PushButton( "New IpoDataBlock/Object", New_Ipo_Evt, col[0], row[10], width[4], height[1], "Creates new Ipo Object(Empty), and Ipo DataBlock(curves)' to use as height filter") - - if Filter_Mode.val ==3: - draw_Text( ( col[0]+5, row[4] ), 'Custom math ( h, x,y, a,b )' , black, 0 ) - CustomFilt[0] = String( "a = ", Btn_Evt, col[0], row[5], width[4], height[1] ,CustomFilt[0].val,96, "a" ) - CustomFilt[1] = String( "b = ", Btn_Evt, col[0], row[6], width[4], height[1] ,CustomFilt[1].val,96, "b" ) - CustomFilt[2] = String( "result = ", Btn_Evt, col[0], row[7], width[4], height[1] ,CustomFilt[2].val,96, "result" ) - if Filter_Mode.val !=0: - Filter_Order = Toggle("Change Filter Order", Btn_Evt, col[0], row[3], width[4], height[1], Filter_Order.val, "Filter Order: OFF = Noise+Effect+Falloff+FILTER / ON = Noise+FILTER+Effect+Falloff.") - -###------------------------- -## Option / Generate Image Buttons: -# -def OptionButtons( col, row, width, height ): - global PreView, previewname - - PreView[0] = Toggle("Make Image", No_Evt, col[0], row[2], width[4], height[2], PreView[0].val, "Image: On/Off (Make a new Image in UV/ImageEditor Window, and give a name to it)") - if PreView[0].val !=0: - previewname = String( "IM:", No_Evt, col[0], row[3], width[4], height[1] ,previewname.val, 16, "IM:Name, Render terrain height to this image" ) - PreView[1] = Number("", Im_Evt, col[0], row[4], width[1], height[1], PreView[1].val, 0.0, 10.0, "Image: Intensity Scale") - PreView[2] = Number("", Im_Evt, col[3], row[4], width[1], height[1], PreView[2].val,-10.0, 10.0, "Image: Offset") - PushButton( "Draw Image", Im_Evt, col[0], row[5], width[4], height[1] , "Image: Update image ( KEY: V )") - draw_Text( ( col[5], row[1] ), 'Create yourself a new image', black, 0 ) - draw_Text( ( col[5], row[2] ), 'in UV/Image Editor Window,', black, 0 ) - draw_Text( ( col[5], row[3] ), 'give it a name,', black, 0 ) - draw_Text( ( col[5], row[4] ), 'and save it manualy.', black, 0 ) - -####-------------------------------------------------------------------------- -###-------------------------------------------------------------------------- -## Draw G.U.I. ------------------------------------------------------------- -#-------------------------------------------------------------------------- -def drawgui(): - global guitabs, ledcolor, FullScreen, AutoUpd, RandMod, RSeed, filemessage - global Effect_Ctrl, Filter_Mode, Falloff, PreView, rand_H, rand_S, rand_L, rand_I - - glClearColor(background[0],background[1],background[2],background[3]) - glClear(GL_COLOR_BUFFER_BIT) - scissorbox=Buffer(GL_FLOAT,4) - glGetFloatv(GL_SCISSOR_BOX,scissorbox) - scissbleft=int(scissorbox[0]) - scissbbase=int(scissorbox[1]) - scissbwidth=int(scissorbox[2]) - scissbheight=int(scissorbox[3]) - xstart = 5 - ystart = 5 - xgap = 5 - ygap = 5 - if FullScreen.val==1: - guiwidth = scissbwidth-10 - guiheight = scissbheight-25 - if guiwidth < size_x/2: - guiwidth = size_x/2 - if guiheight < size_y/2: - guiheight = size_y/2 - else: - guiwidth = size_x - guiheight = size_y - col,row = [],[] - xpart = ( ( guiwidth-xstart ) / columns ) - ypart = ( ( guiheight-ystart ) / rows ) - width = [] - for c in xrange( columns ): - col.append( xgap + xpart * c + xstart ) - width.append( xpart*(c+1)-xgap ) - height = [ (ypart-ygap)/2 , ypart-ygap, (ypart*3-ygap)/2, ypart*2-ygap, (ypart*5-ygap)/2 ] - for r in xrange( rows ): - row.append( ygap + ypart * r + ystart ) - row.reverse() - - ###------------------------- - ## Draw G.U.I.: - draw_BackPanel( 'Another Noise Tool 1.05', xstart, ystart, guiwidth, guiheight + ygap, lightgrey ) - - FullScreen = Toggle("", Scrn_Evt, guiwidth-32, guiheight+ygap+3, 15, 15, FullScreen.val ,"FullScreen" ) - PushButton( "X", End_Evt, guiwidth-16, guiheight+ygap+3, 15, 15, "Exit" ) - draw_Text(( guiwidth-(guiwidth/2)-width[0], guiheight+ygap+5 ), filemessage, white, 0 ) - - # gui tabs - guitabs[0] = Toggle("Main", gt0_Evt, col[0], row[0], width[1], height[1], guitabs[0].val ,"Main / Mesh settings" ) - guitabs[1] = Toggle("Noise", gt1_Evt, col[2], row[0], width[1], height[1], guitabs[1].val ,"Noise settings" ) - guitabs[2] = Toggle("Effect", gt2_Evt, col[4], row[0], width[1], height[1], guitabs[2].val ,"Add Effect" ) - guitabs[3] = Toggle("Height", gt3_Evt, col[6], row[0], width[1], height[1], guitabs[3].val ,"Height Filter" ) - guitabs[4] = Toggle("Options", gt4_Evt, col[8], row[0], width[1], height[1], guitabs[4].val ,"Options" ) - - if guitabs[0].val !=0: MeshButtons( col, row, width, height ) - elif guitabs[1].val !=0: NoiseButtons( col, row, width, height ) - elif guitabs[2].val !=0: EffectButtons( col, row, width, height ) - elif guitabs[3].val !=0: FilterButtons( col, row, width, height ) - elif guitabs[4].val !=0: OptionButtons( col, row, width, height ) - else: # some info - draw_Panel( col[0], row[0]-5, col[9]+width[0], row[10]-10, black ) - draw_Text( ( col[0]+5, row[1] ), 'Another Noise Tool v.1.05', ledcolors[0], 2 ) - draw_Text( ( col[0]+5, row[2] ), 'by: Jimmy Hazevoet, 01/2005-03/2007', ledcolors[1], 2 ) - draw_Text( ( col[0]+5, row[3] ), 'v.1.05: build/tested in: Blender 2.43 (Wndws)', ledcolors[2], 1 ) - draw_Text( ( col[0]+5, row[4] ), 'HotKeys: ----------------------------', ledcolors[3], 2 ) - draw_Text( ( col[0]+5, row[5] ), 'Space = Update mesh', ledcolors[4], 2 ) - draw_Text( ( col[0]+5, row[6] ), 'V = Update Image', ledcolors[5], 2 ) - draw_Text( ( col[0]+5, row[7] ), 'R = Randomise', ledcolors[6], 2 ) - draw_Text( ( col[0]+5, row[8] ), 'L = Load from file', ledcolors[7], 2 ) - draw_Text( ( col[0]+5, row[9] ), 'S = Save to file', ledcolors[8], 2 ) - draw_Text( ( col[0]+5, row[10] ),'Q = Quit', ledcolors[9], 2 ) - - # auto/generate/randomise buttons - rand_on_off = 0 - if rand_H.val !=0: rand_on_off = 1 - elif rand_I.val !=0: rand_on_off = 1 - elif rand_S.val !=0: rand_on_off = 1 - elif rand_L.val !=0: rand_on_off = 1 - else: rand_on_off = 0 - if rand_on_off != 0: - if RandMod.val in [1,2]: - PushButton( "Randomise", Rndm_Evt, col[2], row[12], width[2], height[2] , "Randomise Noise ( KEY: R )") - else: RSeed = Number("Seed: ", Rndm_Evt, col[2], row[12], width[2], height[2], RSeed.val, 0, 255 , "Random Seed: If seed = 0, the current time will be used as seed." ) - AutoUpd = Toggle("Auto", No_Evt, col[0], row[12], width[1], height[2], AutoUpd.val ,"Automatic update" ) - PushButton("Update", Upd_Evt, col[5], row[12], width[4], height[2] , "Generate / Update. ( KEY: SPACE )") - else: - AutoUpd = Toggle("Auto", No_Evt, col[0], row[12], width[1], height[2], AutoUpd.val ,"Automatic update" ) - PushButton("Update", Upd_Evt, col[2], row[12], width[7], height[2] , "Generate / Update. ( KEY: SPACE )") - ####--------------------------------------------------------------------------- - -###--------------------------------------------------------------------------- -##--------------------------------------------------------------------------- -# Key Events: - -def events(evt, val): - global PreView, txtFile, AutoUpd, PreView - - ## hotkey: Q = Quit - if (evt == QKEY and not val): - name = "Quit ?%t|No %x0|Yes %x1" - result = Blender.Draw.PupMenu(name) - if result==1: - Exit() - - ## hotkey: Space = Generate/Update terrain - if (evt == SPACEKEY and not val): - do_it() - - ## hotkey: R = Randomise noise - if (evt in [ RKEY ] and not val): - if AutoUpd.val != 0: - do_it_random() - else: - randomiseNoise() - Draw() - - ## hotkey: V = Update image - if PreView[0].val != 0: - if (evt in [ VKEY, RKEY ] and not val): - do_it_preview() - - ## hotkey: L = Load from file - if (evt == LKEY and not val): - loadmenu = "Load file ?%t|" + txtFile.val - loadresult = Blender.Draw.PupMenu(loadmenu) - if loadresult==1: - LoadPreset(txtFile.val) - if AutoUpd.val != 0: - do_it() - else: Draw() - - ## hotkey: S = Save to file - if (evt == SKEY and not val): - savemenu = "Save file ?%t|" + txtFile.val - saveresult = Blender.Draw.PupMenu(savemenu) - if saveresult==1: - SavePreset(txtFile.val) - Draw() - -###--------------------------------------------------------------------------- -##--------------------------------------------------------------------------- -# Button events: - -def bevents(evt): - global txtFile, effect_image, PreView, fileinfo, filemessage - global Filter_Mode, Ipo_Filter_Ctrl, iponame, thiscurve, selectedcurve - global antfilename, terrainname - global actob, actme - - # quit/reset event - if (evt == End_Evt ): - name = "OK ?%t|Reset %x1|Quit %x2" - result = Blender.Draw.PupMenu(name) - if result==1: - Set_ReSet_Values() - Draw() - elif result==2: - Exit() - - ## file info string event - if (evt == UseMe_Evt ): - result = Blender.Draw.PupStrInput("Info: ", fileinfo, 96) - if result: - fileinfo = result - Draw() - else: return - - ## none event - if (evt in [No_Evt, Scrn_Evt] ): - Draw() - - ## image event - if (evt == Im_Evt ): - do_it_preview() - - ## generate/update event - if (evt == Upd_Evt ): - if PreView[0].val != 0: - do_it_preview() - do_it() - - ## mesh button event - if (evt == Msh_Evt): - if AutoUpd.val != 0: - do_it() - else: Draw() - - ## button event - if (evt == Btn_Evt ): - if AutoUpd.val != 0: - if PreView[0].val != 0: - do_it_preview() - do_it() - else: Draw() - - ## randomise event - if (evt == Rndm_Evt ): - if AutoUpd.val != 0: - do_it_random() - else: - randomiseNoise() - if PreView[0].val != 0: - do_it_preview() - Draw() - - ###--------------------------------------------------------- - ## Effect Image Load/Select: - if (evt == Load_Evt ): - Blender.Window.FileSelector ( load_image, 'LOAD IMAGE') - if (evt == Sel_Evt ): - try: effect_image = Image_Menu() - except: pass - if AutoUpd.val != 0: - do_it() - else: Draw() - - ###--------------------------------------------------------- - ## Make New IPOCurve to use as Filter: - if (evt == New_Ipo_Evt ): - objname = Create("ANT_Ipo_Empty") - iponame = Create("ANT_IPO") - block = [] - block.append("Enter new names") - block.append("and hit OK button") - block.append(("OB: ", objname, 0, 30, "New Ipo Object Name. (Object type = 'Empty')")) - block.append(("IP: ", iponame, 0, 30, "New Ipo DataBlock Name")) - block.append("Open IpoCurveEditor") - block.append("select Ipo DataBlock" ) - block.append("'Pin' the view" ) - block.append("and edit the curves." ) - retval = PupBlock("Make A.N.T. IpoCurve Object", block) - if retval !=0: - ANTAutoIpo( objname.val, iponame.val ) - Ipo_Filter_Ctrl[0].val = iponame.val - - ###--------------------------------------------------------- - ## get IPOCurve to use as Filter: - if (evt in [Ipo_Evt, New_Ipo_Evt] ): - if Filter_Mode.val == 2: - if AutoUpd.val != 0: - try: - ipoblockname = Ipo.Get( Ipo_Filter_Ctrl[0].val ) - thiscurve = ipoblockname.getCurves() - selectedcurve = thiscurve[ Ipo_Filter_Ctrl[1].val ] - if PreView[0].val != 0: - do_it_preview() - #if AutoUpd.val != 0: - do_it() - except: pass - else: - try: - ipoblockname = Ipo.Get( Ipo_Filter_Ctrl[0].val ) - thiscurve = ipoblockname.getCurves() - selectedcurve = thiscurve[ Ipo_Filter_Ctrl[1].val ] - if PreView[0].val != 0: - do_it_preview() - else: - Draw() - except: pass - - ###--------------------------------------------------------- - ## gui tabs - if (evt == gt0_Evt ): - if guitabs[0].val == 1: - guitabs[1].val = ( 0 ) - guitabs[2].val = ( 0 ) - guitabs[3].val = ( 0 ) - guitabs[4].val = ( 0 ) - Draw() - if (evt == gt1_Evt ): - if guitabs[1].val == 1: - guitabs[0].val = ( 0 ) - guitabs[2].val = ( 0 ) - guitabs[3].val = ( 0 ) - guitabs[4].val = ( 0 ) - Draw() - if (evt == gt2_Evt ): - if guitabs[2].val == 1: - guitabs[0].val = ( 0 ) - guitabs[1].val = ( 0 ) - guitabs[3].val = ( 0 ) - guitabs[4].val = ( 0 ) - Draw() - if (evt == gt3_Evt ): - if guitabs[3].val == 1: - guitabs[0].val = ( 0 ) - guitabs[1].val = ( 0 ) - guitabs[2].val = ( 0 ) - guitabs[4].val = ( 0 ) - Draw() - if (evt == gt4_Evt ): - if guitabs[4].val == 1: - guitabs[0].val = ( 0 ) - guitabs[1].val = ( 0 ) - guitabs[2].val = ( 0 ) - guitabs[3].val = ( 0 ) - Draw() - - ###--------------------------------------------------------- - ## load and save all settings: - if (evt == SelFile_Evt ): - Blender.Window.FileSelector ( callback, "Select .ant File") - if (evt == LoadFile_Evt ): - loadmenu = "Load file ?%t|" + txtFile.val - loadresult = Blender.Draw.PupMenu(loadmenu) - if loadresult==1: - LoadPreset(txtFile.val) - Draw() - if AutoUpd.val != 0: - do_it() - if (evt == SaveFile_Evt ): - savemenu = "Save file ?%t|" + txtFile.val - saveresult = Blender.Draw.PupMenu(savemenu) - if saveresult==1: - SavePreset(txtFile.val) - Draw() - - ###--------------------------------------------------------- - # New Grid - ###------------------------- - if (evt == New_Evt): - scn = Blender.Scene.GetCurrent() - gridname = Create("Terrain") - gridres = Create(256) - curspos = Create(0) - block = [] - block.append(("OB: ", gridname, 0, 30, "New Object Name.")) - block.append(("Resol: ", gridres, 4, 1024, "New grid resolution")) - block.append(("At Cursor", curspos, "New grid at cursor position")) - retval = PupBlock("New Grid Mesh", block) - if retval !=0: - MakeGridMesh( gridres.val, gridname.val, curspos.val, scn ) - obj = scn.objects.active - if obj.type == 'Mesh': - actob=[] - actme=[] - actob.append( obj ) - actme.append( actob[0].getData(mesh=1) ) - Blender.Redraw() - - ###--------------------------------------------------------- - # Assign Grid - ###------------------------- - if (evt == App_Evt): - scn = Blender.Scene.GetCurrent() - obj = scn.objects.active - if obj: - if obj.type == 'Mesh': - actob=[] - actme=[] - actob.append( obj ) - actme.append( actob[0].getData(mesh=1) ) - Draw() - - ###------------------------- - if (evt not in [LoadFile_Evt,SaveFile_Evt] ): - filemessage = '' - #Draw() - - ### end events. ------------------------- - -####------------------------------------------------------------------------------------- -###------------------------------------------------------------------------------------- -##------------------------------------------------------------------------------------- -#------------------------------------------------------------------------------------- - -##---------------------------------- -# A.N.T. Auto Ipo generator: -def ANTAutoIpo( objname, iponame ): - scn=Scene.GetCurrent() - # Deselect all objects: - scn.objects.selected=[] - # Create new 'ANT_IPO_OBJECT': - obj = scn.objects.new('Empty', objname ) - obj.setDrawMode(8) - obj.select(1) - obj.layers = Window.ViewLayers() - # Set current frame at 1: - frame = Get('curframe') - if frame !=1: - Set('curframe',1) - frame = Get('curframe') - # Insert IpoKeys: - obj.setLocation(0.0, 0.0, 0.0) - obj.insertIpoKey(0) - Set('curframe',101) - obj.setLocation(100.0, 100.0, 100.0) - obj.insertIpoKey(0) - Set('curframe',1) - # Set Ipo name: - ip = obj.getIpo() - ip.name = iponame - #------------------------- - print "New ANT_IPO: " + objname +" (Object) and " + iponame + " (Ipo DataBlock) Created!" - #------------------------- - -##------------------------------------------------------------------------------------- - -##------------------------- -# Generate random numbers: -def randnum(low,high): - global RandMod, RSeed - if RandMod.val == 0: - # Noise.random setRandomSeed - s = Noise.setRandomSeed( RSeed.val ) - num = Noise.random() - num = num*(high-low) - num = num+low - elif RandMod.val == 1: - # Mathutils.Rand - num = Mathutils.Rand(low,high) - else: - # BPyMathutils Mersenne Twister genrand - num = genrand() - num = num*(high-low) - num = num+low - return num - -##------------------------- -# Randomise noise: height, size and location: -def randomiseNoise(): - global rand_I, rand_H, rand_S, rand_L, NSize, iScale, Offset, Invert, Lx, Ly, Sx, Sy - - if rand_I.val !=0: - iScale[0] = Create( randnum( 0.2 , 3.0 ) ) - Offset[0] = Create( randnum(-1.0 , 1.0 ) ) - if rand_H.val !=0: - iScale[2] = Create( randnum( 0.10 , 1.0 ) ) - Offset[2] = Create( randnum(-0.25 , 0.25 ) ) - if rand_S.val !=0: - NSize[0] = Create( randnum( 0.25 , 2.5 ) ) - #Sx[0] = Create( randnum( 0.5 , 1.5 ) ) - #Sy[0] = Create( randnum( 0.5 , 1.5 ) ) - if rand_L.val !=0: - Lx[0] = Create( randnum( -10000 , 10000 ) ) - Ly[0] = Create( randnum( -10000 , 10000 ) ) - -##------------------------------------------------------------------------------------- - -###-------------------------- -# Load Image: -def load_image( ImageFileName ): - Image.Load( ImageFileName ) - -###-------------------------- -# Select Image Menu: -def Image_Menu(): - try: - names=[] - imagelist = Image.Get() - imagelist.reverse() - for numbers, obnames in enumerate( imagelist ): - n = obnames.getName() - names.append( n ) - imlistText = string.join( [ '|' + str(names[key]) + '%x' + str(key) for key in xrange(numbers+1) ], '' ) - image_menu = Blender.Draw.PupMenu( "Images: %t" + imlistText ) - if image_menu == -1: - return '' - return imagelist[ image_menu ].getName() - except: - return 'No image found!' - -###-------------------------- -# Get Image Pixels: -def Image_Func( x,y ): - try: - pic = Image.Get( effect_image ) - except: - return 0.0 - w, h = pic.getSize() - x, y = x,-y - x = int(w * ((x + 1.0) % 2.0) / 2.0) - y = int((h-1) - h * ((y + 1.0) % 2.0) / 2.0) - c = pic.getPixelF( x,y ) - return ( c[0] + c[1] + c[2] ) / 3.0 - -##------------------------------------------------------------------------------------- - -# Transpose noise coords: -def Trans((x,y,z), size, loc ): - x = ( x / size[1] / size[0] + loc[0] ) - y = ( y / size[2] / size[0] + loc[1] ) - z = 0.0 #( z / size[3] / size[0] + loc[2] ) - return x,y,z - -# Transpose effect coords: -def Trans_Effect((x,y,z), size, loc ): - x = ( x * size[1] * size[0] + loc[0] ) - y = ( y * size[2] * size[0] + loc[1] ) - z = 0.0 - return x,y,z - -# Height scale: -def HeightScale( input, iscale, offset, invert ): - if invert !=0: - return (1.0-input) * iscale + offset - else: - return input * iscale + offset - -# dist. -def Dist(x,y): - return sqrt( (x*x)+(y*y) ) - -##----------------------------------- -# bias types: -def no_bias(a): - return a -def sin_bias(a): - return 0.5 + 0.5 * sin(a) -def cos_bias(a): - return 0.5 + 0.5 * cos(a) -def tri_bias(a): - b = 2 * phi - a = 1 - 2 * abs(floor((a * (1/b))+0.5) - (a*(1/b))) - return a -def saw_bias(a): - b = 2 * phi - n = int(a/b) - a -= n * b - if a < 0: a += b - return a / b -# sharpen types: -def soft(a): - return a -def sharp(a): - return a**0.5 -def sharper(a): - return sharp(sharp(a)) -Bias_Types = [ sin_bias, cos_bias, tri_bias, saw_bias, no_bias ] -Sharp_Types = [ soft, sharp, sharper ] - -##----------------------------------- -# clamp height -def clamp( height, min, max ): - if ( height < min ): height = min - if ( height > max ): height = max - return height - -##----------------------------------- -# Mix modes -def maximum( a, b ): - if ( a > b ): b = a - return b -def minimum( a, b ): - if ( a < b ): b = a - return b - -def Mix_Modes( (i,j),(x,y,z) , a,b, mixfactor, mode ): - a = a * ( 1.0 - mixfactor ) - b = b * ( 1.0 + mixfactor ) - if mode == 0: return ( b ) #0 effect only - elif mode == 1: return ( a*(1.0-0.5) + (b*0.5) ) #1 mix - elif mode == 2: return ( a + b ) #2 add - elif mode == 3: return ( a - b ) #3 sub. - elif mode == 4: return ( a * b ) #4 mult. - elif mode == 5: return (abs( a - b )) #5 abs diff. - elif mode == 6: return 1.0-((1.0-a)*(1.0-b)/1.0) #6 screen - elif mode == 7: return ( a + b ) % 1.0 #7 addmodulo - elif mode == 8: return min( a, b ) #8 min. - elif mode == 9: return max( a, b ) #9 max. - elif mode == 10: #10 warp: effect - noise = mixfactor * Noise_Function(x,y,z) - return Effects( (i,j),(x+noise,y+noise,z) ) - elif mode == 11: #11 warp: noise - effect = mixfactor * Effects( (i,j),(x,y,z) ) - return Noise_Function( x+effect, y+effect, z ) - else: return a - -###---------------------------------------------------------------------- -# Effect functions: - -# Effect_Basis_Function: -def Effect_Basis_Function((x,y), type, bias ): - - iscale = 1.0 - offset = 0.0 - ## gradient: - if type == 0: - effect = offset + iscale * ( Bias_Types[ bias ]( x + y ) ) - ## waves / bumps: - if type == 1: - effect = offset + iscale * 0.5 * ( Bias_Types[ bias ]( x*phi ) + Bias_Types[ bias ]( y*phi ) ) - ## zigzag: - if type == 2: - effect = offset + iscale * Bias_Types[ bias ]( offset + iscale * sin( x*phi + sin( y*phi ) ) ) - ## wavy: - if type == 3: - effect = offset + iscale * ( Bias_Types[ bias ]( cos( x ) + sin( y ) + cos( x*2+y*2 ) - sin( -x*4+y*4) ) ) - ## sine bump: - if type == 4: - effect = offset + iscale * 1-Bias_Types[ bias ](( sin( x*phi ) + sin( y*phi ) )) - ## dots: - if type == 5: - effect = offset + iscale * ( Bias_Types[ bias ](x*phi*2) * Bias_Types[ bias ](y*phi*2) )-0.5 - ## rings / dome: - if type == 6: - effect = offset + iscale * ( Bias_Types[ bias ]( 1.0-(x*x+y*y) ) ) - ## spiral: - if type == 7: - effect = offset + iscale * Bias_Types[ bias ](( x*sin( x*x+y*y ) + y*cos( x*x+y*y ) ))*0.5 - ## square / piramide: - if type == 8: - effect = offset + iscale * Bias_Types[ bias ](1.0-sqrt( (x*x)**10 + (y*y)**10 )**0.1) - ## blocks: - if type == 9: - effect = ( 0.5-max( Bias_Types[ bias ](x*phi) , Bias_Types[ bias ](y*phi) )) - if effect > 0.0: effect = 1.0 - effect = offset + iscale * effect - ## grid: - if type == 10: - effect = ( 0.025-min( Bias_Types[ bias ](x*phi) , Bias_Types[ bias ](y*phi) )) - if effect > 0.0: effect = 1.0 - effect = offset + iscale * effect - ## tech: - if type == 11: - a = ( max( Bias_Types[ bias ](x*pi) , Bias_Types[ bias ](y*pi) )) - b = ( max( Bias_Types[ bias ](x*pi*2+2) , Bias_Types[ bias ](y*pi*2+2) )) - effect = ( min( Bias_Types[ bias ](a) , Bias_Types[ bias ](b) ))*3.0-2.0 - if effect > 0.5: effect = 1.0 - effect = offset + iscale * effect - - ## crackle: - if type == 12: - t = turbulence(( x, y, 0 ), 6, 0, 0 ) * 0.25 - effect = vlNoise(( x, y, t ), 0.25, 0, 8 ) - if effect > 0.5: effect = 0.5 - effect = offset + iscale * ( effect ) - ## sparse cracks noise: - if type == 13: - effect = 2.5 * abs( noise((x*0.5,y*0.5, 0 ), 1 ) )-0.1 - if effect > 0.25: effect = 0.25 - effect = offset + iscale * ( effect * 2.5 ) - ## shattered rock noise: - if type == 14: - effect = 0.5 + noise((x,y,0), 7 ) - if effect > 0.75: effect = 0.75 - effect = offset + iscale * effect - ## lunar noise: - if type == 15: - effect = 0.25 + 1.5 * voronoi(( x+2, y+2, 0 ), 1 )[0][0] - if effect > 0.5: effect = 0.5 - effect = offset + iscale * ( effect * 2.0 ) - ## cosine noise: - if type == 16: - effect = cos( 5*noise(( x, y, 0 ), 0 ) ) - effect = offset + iscale * ( effect*0.5 ) - ## spikey noise: - if type == 17: - n = 0.5 + 0.5 * turbulence(( x*5, y*5, 0 ), 8, 0, 0 ) - effect = ( ( n*n )**5 ) - effect = offset + iscale * effect - ## stone noise: - if type == 18: - effect = offset + iscale *( noise((x*2,y*2, 0 ), 0 ) * 1.5 - 0.75) - ## Flat Turb: - if type == 19: - t = turbulence(( x, y, 0 ), 6, 0, 0 ) - effect = t*2.0 - if effect > 0.25: effect = 0.25 - effect = offset + iscale * ( effect ) - ## Flat Voroni: - if type == 20: - t = 1-noise(( x, y, 0 ), 3 ) - effect = t*2-1.75 - if effect > 0.25: effect = 0.25 - effect = offset + iscale * ( effect ) - - if effect < 0.0: effect = 0.0 - return effect - -# fractalize Effect_Basis_Function: ------------------------------ -def Effect_Function((x,y), type,bias, turb, depth,frequency,amplitude ): - - ## effect distortion: - if turb != 0.0: - t = vTurbulence(( x, y, 0 ), 6, 0, 0 ) - x = x + ( 0.5 + 0.5 * t[0] ) * turb - y = y + ( 0.5 + 0.5 * t[1] ) * turb - - result = Effect_Basis_Function((x,y), type, bias ) - ## fractalize effect: - if depth != 0: - i=0 - while i < depth: - i+=1 - x *= frequency - y *= frequency - amplitude = amplitude / i - result += Effect_Basis_Function( (x,y), type, bias ) * amplitude - return result - -###-------------------------------------------------- -# Custom effect: -def CustomEffect( x,y,z,h ): - global CustomFX - try: - a = eval( CustomFX[0].val ) - b = eval( CustomFX[1].val ) - result = eval( CustomFX[2].val ) - return result - except: - return 0.0 - -###-------------------------------------------------- -## Effect Selector: - -def Effects( (i,j),(x,y,z), h=0.0 ): - global Effect_Type, Effect_Ctrl, iScale, Offset, Invert - global NSize, Lx, Ly, Lz, Sx, Sy, Sz, marbleTwo, turbTwo, vlnoiTwo, Basis, musgrTwo - - x,y,z = Trans_Effect((x,y,z),( NSize[1].val, Sx[1].val, Sy[1].val, 0 ),( Lx[1].val, Ly[1].val, 0 ) ) - basis = Basis[1].val - if basis == 9: basis = 14 - vbasis = vlnoiTwo[1].val - if vbasis == 9: vbasis = 14 - if Effect_Ctrl[0].val == 1: - try: effect = Image_Func( x,y ) - except: effect = 0.0 - elif Effect_Ctrl[0].val == 2: effect = 0.5+0.5*turbulence(( x,y,z ),turbTwo[0].val, turbTwo[1].val, basis, turbTwo[2].val, turbTwo[3].val ) - elif Effect_Ctrl[0].val == 3: effect = 0.5+0.5*vlNoise(( x,y,z ),vlnoiTwo[0].val, vbasis, basis ) - elif Effect_Ctrl[0].val == 4: effect = 0.5*marbleNoise((x,y,z), marbleTwo[0].val, basis, marbleTwo[2].val, marbleTwo[3].val, marbleTwo[4].val, marbleTwo[5].val ) - elif Effect_Ctrl[0].val == 5: effect = 0.5*multiFractal(( x,y,z ),musgrTwo[0].val, musgrTwo[1].val, musgrTwo[2].val, basis ) - elif Effect_Ctrl[0].val == 6: effect = 0.5*ridgedMFractal(( x,y,z ),musgrTwo[0].val, musgrTwo[1].val, musgrTwo[2].val, musgrTwo[3].val, musgrTwo[4].val, basis ) - elif Effect_Ctrl[0].val == 7: effect = 0.5*hybridMFractal(( x,y,z ),musgrTwo[0].val, musgrTwo[1].val, musgrTwo[2].val, musgrTwo[3].val, musgrTwo[4].val, basis ) - elif Effect_Ctrl[0].val == 8: effect = 0.5*heteroTerrain(( x,y,z ),musgrTwo[0].val, musgrTwo[1].val, musgrTwo[2].val, musgrTwo[3].val, basis )*0.5 - elif Effect_Ctrl[0].val == 9: effect = 0.5*fBm(( x,y,z ),musgrTwo[0].val, musgrTwo[1].val, musgrTwo[2].val, basis )+0.5 - elif Effect_Ctrl[0].val > 9 and Effect_Ctrl[0].val < 31: - effect = Effect_Function((x,y), Effect_Ctrl[0].val-10, Effect_Ctrl[3].val, Effect_Ctrl[4].val, Effect_Ctrl[5].val, Effect_Ctrl[6].val, Effect_Ctrl[7].val ) - elif Effect_Ctrl[0].val == 31: effect = Effect_Ctrl[8].val * random() - elif Effect_Ctrl[0].val == 32: effect = Effect_Ctrl[8].val - elif Effect_Ctrl[0].val == 33: effect = CustomEffect( x,y,z, h ) - effect = HeightScale( effect, iScale[1].val , Offset[1].val, Invert[1].val ) - return effect*2.0 - -###---------------------------------------------------------------------- -# Noise: -##----------------------------------- - -## voronoi_turbulence: -def voroTurbMode((x,y,z), voro, mode ): - if mode == 0: # soft - return voronoi(( x,y,z ),voro[0], voro[1] )[0][0] - if mode == 1: # hard - return ( abs( 0.5-voronoi(( x,y,z ),voro[0], voro[1] )[0][0] ) )+0.5 -def voronoi_turbulence((x,y,z), voro, tur ): - result = voroTurbMode((x,y,z), voro, tur[1] ) - depth = tur[0] - amp = tur[2] - freq = tur[3] - i=0 - for i in xrange( depth ): - i+=1 - result += voroTurbMode( ( x*(freq*i), y*(freq*i), z ), voro, tur[1] )* ( amp*0.5/i ) - return (result*4.0-2.0) - -## DistortedNoise / vlNoise_turbulence: -def vlnTurbMode((x,y,z), vlno, basis, mode ): - if mode == 0: # soft - return vlNoise(( x,y,z ),vlno[0], vlno[1], basis ) - if mode == 1: # hard - return ( abs( -vlNoise(( x,y,z ),vlno[0], vlno[1], basis ) ) ) -def vlNoise_turbulence((x,y,z), vlno, tur, basis ): - result = vlnTurbMode((x,y,z), vlno, basis, tur[1] ) - depth = tur[0] - amp = tur[2] - freq = tur[3] - i=0 - for i in xrange( depth ): - i+=1 - result += vlnTurbMode( ( x*(freq*i), y*(freq*i), z ), vlno, basis, tur[1] ) * ( amp*0.5/i ) - return result*2.0+0.5 - -## marbleNoise: -def marbleNoise( (x,y,z), depth, basis, turb, bias, sharpnes, rescale ): - m = ( x * rescale + y * rescale + z ) * 5 - height = m + turb * turbulence( ( x ,y ,z ), depth, 0, basis, 0.5, 2.0 ) - height = Bias_Types[ bias ]( height ) - if bias != 4: - height = Sharp_Types[ sharpnes ]( height ) - return height*2.0 - -## lava_multiFractal: -def lava_multiFractal( ( x,y,z ),Ha, La, Oc, distort, Basis ): - m = multiFractal( ( x,y,z ), Ha, La, Oc, Basis) - d = m * distort - m2 = 0.5 * multiFractal( ( x+d,y+d,d*0.5 ), Ha, La, Oc, Basis) - return (m * m2)**0.5 - -## slopey_noise: -def slopey_noise((x,y,z), H, lacunarity, octaves, distort, basis ): - x=x*2 - y=y*2 - turb = fBm((x,y,z), H, lacunarity, octaves, 2 ) * 0.5 - map = 0.5 + noise( ( x+turb, y+turb, z ), basis ) - result = map + turb * distort - return result - -## duo_multiFractal: -def double_multiFractal((x,y,z), H, lacunarity, octaves, offset, gain, basis ): - n1 = multiFractal( (x*1.5+1,y*1.5+1,z), 1.0, 1.0, 1.0, basis[0] ) * offset - n2 = multiFractal( (x-1,y-1,z), H, lacunarity, octaves, basis[1] ) * gain - result = ( n1*n1 + n2*n2 )*0.5 - return result - -## distorted_heteroTerrain: -def distorted_heteroTerrain((x,y,z), H, lacunarity, octaves, offset, distort, basis ): - h1 = ( heteroTerrain((x,y,z), 1.0, 2.0, 1.0, 1.0, basis[0] ) * 0.5 ) - h2 = ( heteroTerrain(( x, y, h1*distort ), H, lacunarity, octaves, offset, basis[1] ) * 0.25 ) - result = ( h1*h1 + h2*h2 ) - return result - -## SlickRock: -def SlickRock((x,y,z), H, lacunarity, octaves, offset, gain, basis ): - n = multiFractal( (x,y,z), 1.0, 2.0, 1.0, basis[0] ) - r = ridgedMFractal((x,y,n*0.5), H, lacunarity, octaves, offset, gain, basis[1] )*0.5 - return n+(n*r) - -## terra_turbulence: -def terra_turbulence((x,y,z), depth, hard, basis, amp, freq ): - t2 = turbulence( ( x, y, z ), depth, hard , basis, amp, freq ) - return (t2*t2*t2)+0.5 - -## rocky_fBm: -def rocky_fBm((x,y,z), H, lacunarity, octaves, basis ): - turb = fBm((x,y,z), H, lacunarity, octaves, 2 ) * 0.25 - coords = ( x+turb, y+turb, z ) - map = noise( coords, 7 ) - result = map + fBm( coords, H, lacunarity, octaves, basis ) + 1.0 - return result - -## Shattered_hTerrain: -def Shattered_hTerrain((x,y,z), H, lacunarity, octaves, offset, distort, basis ): - d = ( turbulence( ( x, y, z ), 6, 0, 0, 0.5, 2.0 ) * 0.5 + 0.5 )*distort*0.25 - t0 = ( turbulence( ( x+d, y+d, z ), 0, 0, 7, 0.5, 2.0 ) + 0.5 ) - t2 = ( heteroTerrain(( x*2, y*2, t0*0.5 ), H, lacunarity, octaves, offset, basis ) ) - return (( t0*t2 )+t2*0.5)*0.75 - -## vlhTerrain -def vlhTerrain((x,y,z), H, lacunarity, octaves, offset, basis, vlbasis, distort ): - ht = heteroTerrain(( x, y, z ), H, lacunarity, octaves, offset, basis )*0.5 - vl = ht * vlNoise((x,y,z), distort, basis, vlbasis )*0.5+0.5 - return vl * ht - -####---------------------------------------. -### StatsByAlt, double terrain basis mode: -def TerrainBasisMode((x,y,z), basis, mode ): - if mode == 0: # noise - return noise((x,y,z),basis) - if mode == 1: # noise ridged - return ( 1.0-abs( noise((x,y,z),basis) ) )-0.5 - if mode == 2: # vlNoise - return vlNoise((x,y,z), 1.0, 0, basis ) - else: # vlNoise ridged - return ( 1.0-abs( vlNoise((x,y,z), 1.0, 0, basis ) ) )-0.5 - -#### StatsByAlt terrain: -def StatsByAltTerrain((x,y,z), exp, lacu, octs, offset, amp, basis, mode ): - result = 0.5 * (offset + TerrainBasisMode((x,y,z), basis, mode ) ) - octs = int( octs ) - i = 0 - for i in xrange( 1, octs ): - i += 1 - result += result * amp * 0.5 * (offset + TerrainBasisMode((x,y,z), basis, mode ) ) - x *= lacu - y *= lacu - amp /= ( exp * 0.5 ) * i - return result - -##### double terrain: -def doubleTerrain((x,y,z), exp, lacu, octs, offset, threshold, basis, mode ): - result = amp = freq = 1.0 - #octs = int( octs ) - offset*=0.5 - i = 1 - signal = result = 0.5 * (offset + TerrainBasisMode((x,y,z), basis, mode ) ) - for i in xrange( 1, octs ): - i += 1 - x = x * lacu - y = y * lacu - freq *= lacu - amp = pow( freq, -exp ) - amp *= i - weight = signal / threshold - if weight > 1.0: weight = 1.0 - if weight < 0.0: weigth = 0.0 - signal = weight * 0.5 * ( offset + TerrainBasisMode((x,y,z), basis, mode ) ) - result += amp * signal - return result * 2.0 - -##------------------------------------------------------------ -# Noise Functions: -def Noise_Function(x,y,z): - global Basis, NType, musgr, vlnoi, voron, turbOne, marbleOne, tBasismod - global vlBasis, Distort, VFunc, VExp, VDep - global iScale, Offset, Invert, NSize, Lx, Ly, Sx, Sy - - x,y,z = Trans((x,y,z),( NSize[0].val, Sx[0].val, Sy[0].val, 0 ),( Lx[0].val, Ly[0].val, 0 ) ) - basis = Basis[0].val - if basis == 9: basis = 14 - vbasis = vlnoi[1].val - if vbasis == 9: vbasis = 14 - if NType.val == 0: z = multiFractal(( x,y,z ),musgr[0].val, musgr[1].val, musgr[2].val, basis ) - elif NType.val == 1: z = ridgedMFractal(( x,y,z ),musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, musgr[4].val, basis ) - elif NType.val == 2: z = hybridMFractal(( x,y,z ),musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, musgr[4].val, basis ) - elif NType.val == 3: z = heteroTerrain(( x,y,z ),musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, basis )*0.5 - elif NType.val == 4: z = fBm(( x,y,z ),musgr[0].val, musgr[1].val, musgr[2].val, basis )+0.5 - elif NType.val == 5: z = turbulence(( x,y,z ),turbOne[0].val, turbOne[1].val, basis, turbOne[2].val, turbOne[3].val )+0.5 - elif NType.val == 6: z = voronoi_turbulence((x,y,z),(voron[0].val,voron[1].val),(turbOne[0].val,turbOne[1].val,turbOne[2].val,turbOne[3].val) )*0.5+0.5 - elif NType.val == 7: z = vlNoise_turbulence((x,y,z),(vlnoi[0].val,vbasis), (turbOne[0].val,turbOne[1].val,turbOne[2].val,turbOne[3].val), basis )*0.5+0.5 - elif NType.val == 8: z = noise(( x,y,z ),basis )+0.5 - elif NType.val == 9: z = cellNoise(( x,y,z ))+0.5 - elif NType.val == 10: z = marbleNoise(( x,y,z), marbleOne[0].val, basis, marbleOne[2].val, marbleOne[3].val, marbleOne[4].val, marbleOne[5].val ) - elif NType.val == 11: z = lava_multiFractal(( x,y,z ), musgr[0].val, musgr[1].val, musgr[2].val, vlnoi[0].val, basis ) - elif NType.val == 12: z = slopey_noise(( x,y,z), musgr[0].val, musgr[1].val, musgr[2].val, vlnoi[0].val, basis )+0.5 - elif NType.val == 13: z = double_multiFractal(( x,y,z), musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, musgr[4].val, (vbasis,basis) ) - elif NType.val == 14: z = distorted_heteroTerrain((x,y,z), musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, vlnoi[0].val, (vbasis,basis) ) - elif NType.val == 15: z = SlickRock(( x,y,z), musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, musgr[4].val, (vbasis,basis) ) - elif NType.val == 16: z = terra_turbulence(( x,y,z), turbOne[0].val, turbOne[1].val, basis, turbOne[2].val, turbOne[3].val ) - elif NType.val == 17: z = rocky_fBm(( x,y,z ),musgr[0].val, musgr[1].val, musgr[2].val, basis ) - elif NType.val == 18: z = StatsByAltTerrain( (x,y,z), musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, musgr[4].val*0.5, basis, tBasismod.val ) - elif NType.val == 19: z = doubleTerrain( (x,y,z), musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, musgr[5].val, basis, tBasismod.val ) - elif NType.val == 20: z = Shattered_hTerrain((x,y,z), musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, vlnoi[0].val, basis ) - elif NType.val == 21: z = vlhTerrain((x,y,z), musgr[0].val, musgr[1].val, musgr[2].val, musgr[3].val, basis, vbasis, vlnoi[0].val ) - else: z = 0.0 - return HeightScale( z, iScale[0].val , Offset[0].val, Invert[0].val ) - -###---------------------------------------------------------------------- -##----------------------------------- -# Filter functions: - -##----------------------------------- -# Filter: Clamp height -def Clamp_Max( height, max ): - if ( height > max ): height = max - return height -def Clamp_Min( height, min ): - if ( height < min ): height = min - return height - -##----------------------------------- -# Filters: terrace / posterise / peaked / bias: -def Def_Filter((x,y,z), input, numb, type ): - if type == 0: - s = ( sin( input*numb*phi ) * ( 0.1/numb*phi ) ) - return ( input * (1.0-0.5) + s*0.5 ) * 2.0 - elif type == 1: - s = -abs( sin( input*(numb*0.5)*phi ) * ( 0.1/(numb*0.5)*phi ) ) - return ( input * (1.0-0.5) + s*0.5 ) * 2.0 - elif type == 2: - s = abs( sin( input*(numb*0.5)*phi ) * ( 0.1/(numb*0.5)*phi ) ) - return ( input * (1.0-0.5) + s*0.5 ) * 2.0 - elif type == 3: - numb = numb*0.5 - s = ( int( input*numb ) * 1.0/numb ) - return ( input * (1.0-0.5) + s*0.5 ) * 2.0 - elif type == 4: - numb = numb*0.5 - s = ( int( input*numb ) * 1.0/numb ) - return ( s ) * 2.0 - elif type == 5: - s = ( sin( input*(2*numb)*phi ) * ( 0.1/(2*numb)*phi ) ) - l = ( input * (1.0-0.5) + s*0.5 ) * 2.0 - p = ( ( l*numb*0.25 ) * ( l*numb*0.25 ) )**2 - return ( l * (1.0-0.5) + p*0.5 ) * 2.0 - elif type == 6: - return ( input*numb*0.25 )**4 - elif type == 7: - return 2.0-exp( 1.0-(input*numb/3.0) ) - elif type == 8: - return sin_bias( input*numb )*2.0 - elif type == 9: - return cos_bias( input*numb )*2.0 - elif type == 10: - return tri_bias( input*numb )*2.0 - elif type == 11: - return saw_bias( input*numb )*2.0 - elif type == 12: - return Clamp_Max( input, numb ) - else: - return input - -##----------------------------------- -# Filter: Edge falloff -def EdgeFalloff( (x,y,z), height, type ): - global Falloff, iScale, Offset - - x = x / Falloff[1].val - y = y / Falloff[2].val - - if Falloff[3].val != 0: - sealevel = (Min.val-Offset[2].val)*2.0/iScale[2].val - else: - sealevel = 0.0 - - falltypes = ( 0, sqrt(x*x+y*y), sqrt((x*x)**2+(y*y)**2), sqrt((x*x)**10+(y*y)**10), sqrt(y*y), sqrt(x*x), abs(x-y), abs(x+y), ((x*x)**10+(y*y)**10)**0.1, ((x*x)+(y*y)) ) - - dist = falltypes[ type ] - if Falloff[4].val != 0: - dist = 1.0 - dist - radius = 1.0 - height = height - sealevel - if( dist < radius ): - dist = dist / radius - dist = ( (dist) * (dist) * ( 3-2*(dist) ) ) - height = ( height - height * dist ) + sealevel - else: - height = sealevel - - if Falloff[3].val != 0: - height = Clamp_Min( height, sealevel ) - else: - height = Clamp_Min( height, Min.val ) - - return height - -##----------------------------------- -# Filter: Custom height filter: -def CustomFilter( x,y,z, h ): - global CustomFilt - try: - a = eval(CustomFilt[0].val) - b = eval(CustomFilt[1].val) - result = eval(CustomFilt[2].val) - return result - except: - return 0.0 - -#####-------------------------------------------------------------------------------------##### -####-------------------------------------------------------------------------------------#### -### Combine Functions: (get noise, Add effect, filter height and return result) ### -##-------------------------------------------------------------------------------------## - -def Combine_Functions( (i,j),(x,y,z) ): - global Effect_Ctrl, Blend_Effect, Filter_Mode, Def_Filter_Ctrl, Ipo_Filter_Ctrl, Filter_Order - global iScale, Offset, Invert, Min, Max, Falloff - - # get noise height: - height = Noise_Function(x,y,0.0) - - ### Filter On - if Filter_Mode.val !=0: - ### 0= Default Filter Order: Noise>Effect>Filter --------------------- - if Filter_Order.val ==0: - # mix noise with effect: - if Effect_Ctrl[0].val !=0: - height = Mix_Modes( (i,j),(x,y,z), height , Effects( (i,j),(x,y,z),height ), Effect_Ctrl[2].val, Effect_Ctrl[1].val ) - # edge fallof: - if Falloff[0].val !=0: - height = EdgeFalloff( (x,y,z), height, Falloff[0].val ) - #else: pass - - if Filter_Mode.val !=0: - # height Def_Filter (Terrace/peaked/bias): - if Filter_Mode.val ==1: - height = Def_Filter((x,y,z), height, Def_Filter_Ctrl[ 1 ].val, Def_Filter_Ctrl[ 0 ].val ) - - ## 'IPOCurve' height filter: - elif Filter_Mode.val ==2: - try: - height = selectedcurve.evaluate( 1 + ( height*Ipo_Filter_Ctrl[2].val/2 ) )*2.0/Ipo_Filter_Ctrl[3].val - except: - height = height - - ## Custom filter: - elif Filter_Mode.val ==3: - height = CustomFilter( x,y,z, height ) - - ### 1= Changed Filter Order: Noise>Filter>Effect --------------------- - if Filter_Order.val !=0: - # mix noise with effect: - if Effect_Ctrl[0].val !=0: - height = Mix_Modes( (i,j),(x,y,z), height , Effects( (i,j),(x,y,z),height ), Effect_Ctrl[2].val, Effect_Ctrl[1].val ) - # edge fallof: - if Falloff[0].val !=0: - height = EdgeFalloff( (x,y,z), height, Falloff[0].val ) - #else: pass - - ### Filter Off --------------------- - else: - # mix noise with effect: - if Effect_Ctrl[0].val !=0: - height = Mix_Modes( (i,j),(x,y,z), height , Effects( (i,j),(x,y,z),height ), Effect_Ctrl[2].val, Effect_Ctrl[1].val ) - # edge fallof: - if Falloff[0].val !=0: - height = EdgeFalloff( (x,y,z), height, Falloff[0].val ) - - # height scale: - height = HeightScale( height, 0.5*iScale[2].val , Offset[2].val, Invert[2].val ) - - # clamp height min. max.: - if Falloff[0].val !=1: - height = Clamp_Min( height, Min.val ) - height = Clamp_Max( height, Max.val ) - - # return height: - return height - - -#------------------------------------------------------------ -##------------------------------------------------------------ -### Render Noise to a Image('NAME') (you must create one first) -##------------------------------------------------------------ -#------------------------------------------------------------ - -def HeightFieldImage(): - global PreView, previewname - - iname = previewname.val - try: - pic = Image.Get( iname ) - except: - #print iname, ' No Image with this name' - PupMenu( 'No Image with this name' ) - return - res = pic.getMaxXY() - for i in xrange( res[0] ): - x = i - (res[0]) / 2.0 - x = (x*2.0) / (res[0]) - for j in xrange( res[1] ): - y = j - (res[1]) / 2.0 - y = (y*2.0) / (res[1]) - height = PreView[2].val + PreView[1].val * Combine_Functions( (i,j),(x,y,0) ) - if height > 1.0: height = 1.0 - if height < 0.0: height = 0.0 - pic.setPixelF( i, j, ( height,height,height, 1.0 ) ) - - -#------------------------------------------------------------ -##------------------------------------------------------------ -### Mesh -##------------------------------------------------------------ -#------------------------------------------------------------ - -#------------------------------------------------------------ -## Mesh: make new grid -###------------------------------------------------------------ - -def MakeGridMesh( RESOL=32, NAME='GridMesh', CURSORPOS=0, SCENE=None ): - # scene, object, mesh --------------------------------------- - if not SCENE: - SCENE = Blender.Scene.GetCurrent() - SCENE.objects.selected=[] - newme = Blender.Mesh.New( NAME ) - newob = SCENE.objects.new( newme, NAME ) - n = RESOL - # verts --------------------------------------- - v=[] - for i in xrange( n ): - x = i-(n-1)/2.0 - x = x*2.0/(n-1) - for j in xrange( n ): - y = j-(n-1)/2.0 - y = y*2.0/(n-1) - v.append( [ x, y, 0 ] ) - newme.verts.extend(v) - # faces --------------------------------------- - f=[] - for i in xrange( n-1 ): - for j in xrange( n-1 ): - f.append( [ i*n+j,\ - (i+1)*n+j,\ - (i+1)*n+j+1,\ - i*n+j+1 ] ) - - newme.faces.extend(f, smooth=True) - #--------------------------------------- - newme.calcNormals() - #--------------------------------------- - if CURSORPOS !=0: - newob.loc = Window.GetCursorPos() - newob.select(1) - -#------------------------------------------------------------ -## Mesh: Grid vert displace / update terrain -###------------------------------------------------------------ - -def displace( OB, ME, WORLD=0 ): - if WORLD == 1: - wx,wy,wz = OB.getLocation( 'worldspace' ) - elif WORLD ==2: - l = OB.getLocation( 'worldspace' ) - w = Window.GetCursorPos() - wx,wy,wz = l[0]-w[0], l[1]-w[1], l[2]-w[2] - else: - wx,wy,wz = 0,0,0 - - for v in ME.verts: - co = v.co - co[2] = Combine_Functions( (co[0]+wx,co[1]+wy),(co[0]+wx, co[1]+wy, 0.0+wz) ) - ME.update() - ME.calcNormals() - #OB.makeDisplayList() - - -#---------------------------------------------------------------------------------------------------- -##---------------------------------------------------------------------------------------------------- -###---------------------------------------------------------------------------------------------------- -####---------------------------------------------------------------------------------------------------- -###---------------------------------------------------------------------------------------------------- -## Do_it: -#-------------------------------------- - -#-------------------------------------- -def do_it(): - global PreView, actme, actob, WorldSpaceCo - if actme !=[]: - if print_time !=0: - t= sys.time() - Window.WaitCursor(1) - in_editmode = Window.EditMode() - if in_editmode: Window.EditMode(0) - if PreView[0].val != 0: - do_it_preview() - displace( actob[0], actme[0], WorldSpaceCo.val ) - Window.RedrawAll() - else: - displace( actob[0], actme[0], WorldSpaceCo.val ) - Window.RedrawAll() - if in_editmode: Window.EditMode(1) - Window.WaitCursor(0) - if print_time !=0: - print 'Generate Mesh: done in %.6f' % (sys.time()-t) - -#-------------------------------------- -def do_it_random(): - global PreView, actme, actob - if actme !=[]: - if print_time !=0: - t= sys.time() - Window.WaitCursor(1) - in_editmode = Window.EditMode() - if in_editmode: Window.EditMode(0) - randomiseNoise() - if PreView[0].val != 0: - do_it_preview() - displace( actob[0], actme[0], WorldSpaceCo.val ) - Window.RedrawAll() - else: - displace( actob[0], actme[0], WorldSpaceCo.val ) - Window.RedrawAll() - if in_editmode: Window.EditMode(1) - Window.WaitCursor(0) - if print_time !=0: - print 'Generate Mesh: done in %.6f' % (sys.time()-t) - -#-------------------------------------- -def do_it_preview(): - if print_time !=0: - t= sys.time() - HeightFieldImage() - Window.RedrawAll() - if print_time !=0: - print 'Generate Image: done in %.6f' % (sys.time()-t) - -###--------------------------------------------------------- -###--------------------------------------------------------- -## load and save: -#------------------------- - -def callback( filename ): - txtFile.val = filename - Register(drawgui, events, bevents) -def writeln(f,x): - f.write(str(x)) - f.write("\n") -def readint(f): - return int(f.readline()) -def readfloat(f): - return float(f.readline()) -def readstr(f): - s = (f.readline()) - return strip(s) - -#-------------------------------------------------- -# Save settings to .ant file -def SavePreset(FName): - global iScale, Offset, Invert, NSize, Sx, Sy, Lx, Ly - global NType, Basis, musgr, tBasismod, vlnoi, vlnoiTwo, voron, turbOne, turbTwo, marbleOne, marbleTwo, musgrTwo - global CustomFX, effect_image, Effect_Ctrl, Min, Max, Falloff, CustomFilt, Filter_Mode, Def_Filter_Ctrl, Ipo_Filter_Ctrl, Filter_Order - global RandMod, RSeed, rand_H, rand_S, rand_L, rand_I, filemessage, fileinfo - - try: - f = open(FName,'w') - writeln(f,CurVersion) - except: - filemessage = "Unable to save file." - return - - writeln(f,fileinfo) - writeln(f,iScale[0].val) - writeln(f,iScale[1].val) - writeln(f,iScale[2].val) - writeln(f,Offset[0].val) - writeln(f,Offset[1].val) - writeln(f,Offset[2].val) - writeln(f,Invert[0].val) - writeln(f,Invert[1].val) - writeln(f,Invert[2].val) - writeln(f,NSize[0].val) - writeln(f,NSize[1].val) - writeln(f,Sx[0].val) - writeln(f,Sx[1].val) - writeln(f,Sy[0].val) - writeln(f,Sy[1].val) - writeln(f,Lx[0].val) - writeln(f,Lx[1].val) - writeln(f,Ly[0].val) - writeln(f,Ly[1].val) - writeln(f,NType.val) - writeln(f,Basis[0].val) - writeln(f,Basis[1].val) - writeln(f,musgr[0].val) - writeln(f,musgr[1].val) - writeln(f,musgr[2].val) - writeln(f,musgr[3].val) - writeln(f,musgr[4].val) - writeln(f,musgr[5].val) - writeln(f,tBasismod.val) - writeln(f,vlnoi[0].val) - writeln(f,vlnoi[1].val) - writeln(f,vlnoiTwo[0].val) - writeln(f,vlnoiTwo[1].val) - writeln(f,voron[0].val) - writeln(f,voron[1].val) - writeln(f,turbOne[0].val) - writeln(f,turbOne[1].val) - writeln(f,turbOne[2].val) - writeln(f,turbOne[3].val) - writeln(f,turbTwo[0].val) - writeln(f,turbTwo[1].val) - writeln(f,turbTwo[2].val) - writeln(f,turbTwo[3].val) - writeln(f,marbleOne[0].val) - writeln(f,marbleOne[1].val) - writeln(f,marbleOne[2].val) - writeln(f,marbleOne[3].val) - writeln(f,marbleOne[4].val) - writeln(f,marbleOne[5].val) - writeln(f,marbleTwo[0].val) - writeln(f,marbleTwo[1].val) - writeln(f,marbleTwo[2].val) - writeln(f,marbleTwo[3].val) - writeln(f,marbleTwo[4].val) - writeln(f,marbleTwo[5].val) - writeln(f,musgrTwo[0].val) - writeln(f,musgrTwo[1].val) - writeln(f,musgrTwo[2].val) - writeln(f,musgrTwo[3].val) - writeln(f,musgrTwo[4].val) - writeln(f,effect_image) - writeln(f,Effect_Ctrl[0].val) - writeln(f,Effect_Ctrl[1].val) - writeln(f,Effect_Ctrl[2].val) - writeln(f,Effect_Ctrl[3].val) - writeln(f,Effect_Ctrl[4].val) - writeln(f,Effect_Ctrl[5].val) - writeln(f,Effect_Ctrl[6].val) - writeln(f,Effect_Ctrl[7].val) - writeln(f,Effect_Ctrl[8].val) - writeln(f,CustomFX[0].val) - writeln(f,CustomFX[1].val) - writeln(f,CustomFX[2].val) - writeln(f,Min.val) - writeln(f,Max.val) - writeln(f,Falloff[0].val) - writeln(f,Falloff[1].val) - writeln(f,Falloff[2].val) - writeln(f,Falloff[3].val) - writeln(f,Falloff[4].val) - writeln(f,Filter_Mode.val) - writeln(f,Filter_Order.val) - writeln(f,CustomFilt[0].val) - writeln(f,CustomFilt[1].val) - writeln(f,CustomFilt[2].val) - writeln(f,Def_Filter_Ctrl[0].val) - writeln(f,Def_Filter_Ctrl[1].val) - writeln(f,Ipo_Filter_Ctrl[0].val) - writeln(f,Ipo_Filter_Ctrl[1].val) - writeln(f,Ipo_Filter_Ctrl[2].val) - writeln(f,Ipo_Filter_Ctrl[3].val) - writeln(f,RandMod.val) - writeln(f,RSeed.val) - writeln(f,rand_H.val) - writeln(f,rand_I.val) - writeln(f,rand_S.val) - writeln(f,rand_L.val) - filemessage = 'Settings saved to file.' - f.close() - -#-------------------------------------------------- -# load settings from .ant file -def LoadPreset(FName): - global iScale, Offset, Invert, NSize, Sx, Sy, Lx, Ly - global NType, Basis, musgr, tBasismod, vlnoi, vlnoiTwo, voron, turbOne, turbTwo, marbleOne, marbleTwo, musgrTwo - global CustomFX, effect_image, Effect_Ctrl, Min, Max, Falloff, CustomFilt, Filter_Mode, Def_Filter_Ctrl, Ipo_Filter_Ctrl, Filter_Order - global RandMod, RSeed, rand_H, rand_S, rand_L, rand_I, filemessage, fileinfo - - try: - f = open(FName,'r') - FVersion = readstr(f) - except: - filemessage = "Unable to open file." - return - - fileinfo = readstr(f) - iScale[0].val = readfloat(f) - iScale[1].val = readfloat(f) - iScale[2].val = readfloat(f) - Offset[0].val = readfloat(f) - Offset[1].val = readfloat(f) - Offset[2].val = readfloat(f) - Invert[0].val = readint(f) - Invert[1].val = readint(f) - Invert[2].val = readint(f) - NSize[0].val = readfloat(f) - NSize[1].val = readfloat(f) - Sx[0].val = readfloat(f) - Sx[1].val = readfloat(f) - Sy[0].val = readfloat(f) - Sy[1].val = readfloat(f) - Lx[0].val = readfloat(f) - Lx[1].val = readfloat(f) - Ly[0].val = readfloat(f) - Ly[1].val = readfloat(f) - NType.val = readint(f) - Basis[0].val = readint(f) - Basis[1].val = readint(f) - musgr[0].val = readfloat(f) - musgr[1].val = readfloat(f) - musgr[2].val = readint(f) - musgr[3].val = readfloat(f) - musgr[4].val = readfloat(f) - musgr[5].val = readfloat(f) - tBasismod.val = readint(f) - vlnoi[0].val = readfloat(f) - vlnoi[1].val = readint(f) - vlnoiTwo[0].val = readfloat(f) - vlnoiTwo[1].val = readint(f) - voron[0].val = readint(f) - voron[1].val = readfloat(f) - turbOne[0].val = readint(f) - turbOne[1].val = readint(f) - turbOne[2].val = readfloat(f) - turbOne[3].val = readfloat(f) - turbTwo[0].val = readint(f) - turbTwo[1].val = readint(f) - turbTwo[2].val = readfloat(f) - turbTwo[3].val = readfloat(f) - marbleOne[0].val = readint(f) - marbleOne[1].val = readint(f) - marbleOne[2].val = readfloat(f) - marbleOne[3].val = readint(f) - marbleOne[4].val = readint(f) - marbleOne[5].val = readfloat(f) - marbleTwo[0].val = readint(f) - marbleTwo[1].val = readint(f) - marbleTwo[2].val = readfloat(f) - marbleTwo[3].val = readint(f) - marbleTwo[4].val = readint(f) - marbleTwo[5].val = readfloat(f) - musgrTwo[0].val = readfloat(f) - musgrTwo[1].val = readfloat(f) - musgrTwo[2].val = readint(f) - musgrTwo[3].val = readfloat(f) - musgrTwo[4].val = readfloat(f) - effect_image = readstr(f) - Effect_Ctrl[0].val = readint(f) - Effect_Ctrl[1].val = readint(f) - Effect_Ctrl[2].val = readfloat(f) - Effect_Ctrl[3].val = readint(f) - Effect_Ctrl[4].val = readfloat(f) - Effect_Ctrl[5].val = readint(f) - Effect_Ctrl[6].val = readfloat(f) - Effect_Ctrl[7].val = readfloat(f) - Effect_Ctrl[8].val = readfloat(f) - CustomFX[0].val = readstr(f) - CustomFX[1].val = readstr(f) - CustomFX[2].val = readstr(f) - Min.val = readfloat(f) - Max.val = readfloat(f) - Falloff[0].val = readint(f) - Falloff[1].val = readfloat(f) - Falloff[2].val = readfloat(f) - Falloff[3].val = readint(f) - Falloff[4].val = readint(f) - Filter_Mode.val = readint(f) - Filter_Order.val = readint(f) - CustomFilt[0].val = readstr(f) - CustomFilt[1].val = readstr(f) - CustomFilt[2].val = readstr(f) - Def_Filter_Ctrl[0].val = readint(f) - Def_Filter_Ctrl[1].val = readfloat(f) - Ipo_Filter_Ctrl[0].val = readstr(f) - Ipo_Filter_Ctrl[1].val = readint(f) - Ipo_Filter_Ctrl[2].val = readfloat(f) - Ipo_Filter_Ctrl[3].val = readfloat(f) - RandMod.val = readint(f) - RSeed.val = readint(f) - rand_H.val = readint(f) - rand_I.val = readint(f) - rand_S.val = readint(f) - rand_L.val = readint(f) - filemessage = 'Settings loaded from file.' - f.close() - -##--------------------------------------------------------------------------- -# Register: - -Register( drawgui, events, bevents ) -###-------------------------------------------------------------------------- -
\ No newline at end of file diff --git a/release/scripts/x3d_export.py b/release/scripts/x3d_export.py deleted file mode 100644 index b12ff67d8a6..00000000000 --- a/release/scripts/x3d_export.py +++ /dev/null @@ -1,1051 +0,0 @@ -#!BPY -""" Registration info for Blender menus: -Name: 'X3D Extensible 3D (.x3d)...' -Blender: 245 -Group: 'Export' -Tooltip: 'Export selection to Extensible 3D file (.x3d)' -""" - -__author__ = ("Bart", "Campbell Barton") -__email__ = ["Bart, bart:neeneenee*de"] -__url__ = ["Author's (Bart) homepage, http://www.neeneenee.de/vrml"] -__version__ = "2006/01/17" -__bpydoc__ = """\ -This script exports to X3D format. - -Usage: - -Run this script from "File->Export" menu. A pop-up will ask whether you -want to export only selected or all relevant objects. - -Known issues:<br> - Doesn't handle multiple materials (don't use material indices);<br> - Doesn't handle multiple UV textures on a single mesh (create a mesh for each texture);<br> - Can't get the texture array associated with material * not the UV ones; -""" - - -# $Id$ -# -#------------------------------------------------------------------------ -# X3D exporter for blender 2.36 or above -# -# ***** 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 ***** -# - -#################################### -# Library dependancies -#################################### - -import Blender -from Blender import Object, Lamp, Draw, Image, Text, sys, Mesh -from Blender.Scene import Render -import math -import BPyObject -import BPyMesh - -# -DEG2RAD=0.017453292519943295 -MATWORLD= Blender.Mathutils.RotationMatrix(-90, 4, 'x') - -#################################### -# Global Variables -#################################### - -filename = Blender.Get('filename') -_safeOverwrite = True - -extension = '' - -########################################################## -# Functions for writing output file -########################################################## - -class x3d_class: - - def __init__(self, filename): - #--- public you can change these --- - self.writingcolor = 0 - self.writingtexture = 0 - self.writingcoords = 0 - self.proto = 1 - self.matonly = 0 - self.share = 0 - self.billnode = 0 - self.halonode = 0 - self.collnode = 0 - self.tilenode = 0 - self.verbose=2 # level of verbosity in console 0-none, 1-some, 2-most - self.cp=3 # decimals for material color values 0.000 - 1.000 - self.vp=3 # decimals for vertex coordinate values 0.000 - n.000 - self.tp=3 # decimals for texture coordinate values 0.000 - 1.000 - self.it=3 - - #--- class private don't touch --- - self.texNames={} # dictionary of textureNames - self.matNames={} # dictionary of materiaNames - self.meshNames={} # dictionary of meshNames - self.indentLevel=0 # keeps track of current indenting - self.filename=filename - self.file = None - if filename.lower().endswith('.x3dz'): - try: - import gzip - self.file = gzip.open(filename, "w") - except: - print "failed to import compression modules, exporting uncompressed" - self.filename = filename[:-1] # remove trailing z - - if self.file == None: - self.file = open(self.filename, "w") - - self.bNav=0 - self.nodeID=0 - self.namesReserved=[ "Anchor","Appearance","Arc2D","ArcClose2D","AudioClip","Background","Billboard", - "BooleanFilter","BooleanSequencer","BooleanToggle","BooleanTrigger","Box","Circle2D", - "Collision","Color","ColorInterpolator","ColorRGBA","component","Cone","connect", - "Contour2D","ContourPolyline2D","Coordinate","CoordinateDouble","CoordinateInterpolator", - "CoordinateInterpolator2D","Cylinder","CylinderSensor","DirectionalLight","Disk2D", - "ElevationGrid","EspduTransform","EXPORT","ExternProtoDeclare","Extrusion","field", - "fieldValue","FillProperties","Fog","FontStyle","GeoCoordinate","GeoElevationGrid", - "GeoLocationLocation","GeoLOD","GeoMetadata","GeoOrigin","GeoPositionInterpolator", - "GeoTouchSensor","GeoViewpoint","Group","HAnimDisplacer","HAnimHumanoid","HAnimJoint", - "HAnimSegment","HAnimSite","head","ImageTexture","IMPORT","IndexedFaceSet", - "IndexedLineSet","IndexedTriangleFanSet","IndexedTriangleSet","IndexedTriangleStripSet", - "Inline","IntegerSequencer","IntegerTrigger","IS","KeySensor","LineProperties","LineSet", - "LoadSensor","LOD","Material","meta","MetadataDouble","MetadataFloat","MetadataInteger", - "MetadataSet","MetadataString","MovieTexture","MultiTexture","MultiTextureCoordinate", - "MultiTextureTransform","NavigationInfo","Normal","NormalInterpolator","NurbsCurve", - "NurbsCurve2D","NurbsOrientationInterpolator","NurbsPatchSurface", - "NurbsPositionInterpolator","NurbsSet","NurbsSurfaceInterpolator","NurbsSweptSurface", - "NurbsSwungSurface","NurbsTextureCoordinate","NurbsTrimmedSurface","OrientationInterpolator", - "PixelTexture","PlaneSensor","PointLight","PointSet","Polyline2D","Polypoint2D", - "PositionInterpolator","PositionInterpolator2D","ProtoBody","ProtoDeclare","ProtoInstance", - "ProtoInterface","ProximitySensor","ReceiverPdu","Rectangle2D","ROUTE","ScalarInterpolator", - "Scene","Script","Shape","SignalPdu","Sound","Sphere","SphereSensor","SpotLight","StaticGroup", - "StringSensor","Switch","Text","TextureBackground","TextureCoordinate","TextureCoordinateGenerator", - "TextureTransform","TimeSensor","TimeTrigger","TouchSensor","Transform","TransmitterPdu", - "TriangleFanSet","TriangleSet","TriangleSet2D","TriangleStripSet","Viewpoint","VisibilitySensor", - "WorldInfo","X3D","XvlShell","VertexShader","FragmentShader","MultiShaderAppearance","ShaderAppearance" ] - self.namesStandard=[ "Empty","Empty.000","Empty.001","Empty.002","Empty.003","Empty.004","Empty.005", - "Empty.006","Empty.007","Empty.008","Empty.009","Empty.010","Empty.011","Empty.012", - "Scene.001","Scene.002","Scene.003","Scene.004","Scene.005","Scene.06","Scene.013", - "Scene.006","Scene.007","Scene.008","Scene.009","Scene.010","Scene.011","Scene.012", - "World","World.000","World.001","World.002","World.003","World.004","World.005" ] - self.namesFog=[ "","LINEAR","EXPONENTIAL","" ] - -########################################################## -# Writing nodes routines -########################################################## - - def writeHeader(self): - #bfile = sys.expandpath( Blender.Get('filename') ).replace('<', '<').replace('>', '>') - bfile = self.filename.replace('<', '<').replace('>', '>') # use outfile name - self.file.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n") - self.file.write("<!DOCTYPE X3D PUBLIC \"ISO//Web3D//DTD X3D 3.0//EN\" \"http://www.web3d.org/specifications/x3d-3.0.dtd\">\n") - self.file.write("<X3D version=\"3.0\" profile=\"Immersive\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema-instance\" xsd:noNamespaceSchemaLocation=\"http://www.web3d.org/specifications/x3d-3.0.xsd\">\n") - self.file.write("<head>\n") - self.file.write("\t<meta name=\"filename\" content=\"%s\" />\n" % sys.basename(bfile)) - self.file.write("\t<meta name=\"generator\" content=\"Blender %s\" />\n" % Blender.Get('version')) - self.file.write("\t<meta name=\"translator\" content=\"X3D exporter v1.55 (2006/01/17)\" />\n") - self.file.write("</head>\n") - self.file.write("<Scene>\n") - - # This functionality is poorly defined, disabling for now - campbell - ''' - def writeInline(self): - inlines = Blender.Scene.Get() - allinlines = len(inlines) - if scene != inlines[0]: - return - else: - for i in xrange(allinlines): - nameinline=inlines[i].name - if (nameinline not in self.namesStandard) and (i > 0): - self.file.write("<Inline DEF=\"%s\" " % (self.cleanStr(nameinline))) - nameinline = nameinline+".x3d" - self.file.write("url=\"%s\" />" % nameinline) - self.file.write("\n\n") - - - def writeScript(self): - textEditor = Blender.Text.Get() - alltext = len(textEditor) - for i in xrange(alltext): - nametext = textEditor[i].name - nlines = textEditor[i].getNLines() - if (self.proto == 1): - if (nametext == "proto" or nametext == "proto.js" or nametext == "proto.txt") and (nlines != None): - nalllines = len(textEditor[i].asLines()) - alllines = textEditor[i].asLines() - for j in xrange(nalllines): - self.writeIndented(alllines[j] + "\n") - elif (self.proto == 0): - if (nametext == "route" or nametext == "route.js" or nametext == "route.txt") and (nlines != None): - nalllines = len(textEditor[i].asLines()) - alllines = textEditor[i].asLines() - for j in xrange(nalllines): - self.writeIndented(alllines[j] + "\n") - self.writeIndented("\n") - ''' - - def writeViewpoint(self, ob, mat, scene): - context = scene.render - ratio = float(context.imageSizeY())/float(context.imageSizeX()) - lens = (360* (math.atan(ratio *16 / ob.data.getLens()) / math.pi))*(math.pi/180) - lens = min(lens, math.pi) - - # get the camera location, subtract 90 degress from X to orient like X3D does - # mat = ob.matrixWorld - mat is now passed! - - loc = self.rotatePointForVRML(mat.translationPart()) - rot = mat.toEuler() - rot = (((rot[0]-90)*DEG2RAD), rot[1]*DEG2RAD, rot[2]*DEG2RAD) - nRot = self.rotatePointForVRML( rot ) - # convert to Quaternion and to Angle Axis - Q = self.eulerToQuaternions(nRot[0], nRot[1], nRot[2]) - Q1 = self.multiplyQuaternions(Q[0], Q[1]) - Qf = self.multiplyQuaternions(Q1, Q[2]) - angleAxis = self.quaternionToAngleAxis(Qf) - self.file.write("<Viewpoint DEF=\"%s\" " % (self.cleanStr(ob.name))) - self.file.write("description=\"%s\" " % (ob.name)) - self.file.write("centerOfRotation=\"0 0 0\" ") - self.file.write("position=\"%3.2f %3.2f %3.2f\" " % (loc[0], loc[1], loc[2])) - self.file.write("orientation=\"%3.2f %3.2f %3.2f %3.2f\" " % (angleAxis[0], angleAxis[1], -angleAxis[2], angleAxis[3])) - self.file.write("fieldOfView=\"%.3f\" />\n\n" % (lens)) - - def writeFog(self, world): - if world: - mtype = world.getMistype() - mparam = world.getMist() - grd = world.getHor() - grd0, grd1, grd2 = grd[0], grd[1], grd[2] - else: - return - if (mtype == 1 or mtype == 2): - self.file.write("<Fog fogType=\"%s\" " % self.namesFog[mtype]) - self.file.write("color=\"%s %s %s\" " % (round(grd0,self.cp), round(grd1,self.cp), round(grd2,self.cp))) - self.file.write("visibilityRange=\"%s\" />\n\n" % round(mparam[2],self.cp)) - else: - return - - def writeNavigationInfo(self, scene): - self.file.write('<NavigationInfo headlight="FALSE" visibilityLimit="0.0" type=\'"EXAMINE","ANY"\' avatarSize="0.25, 1.75, 0.75" />\n') - - def writeSpotLight(self, ob, mtx, lamp, world): - safeName = self.cleanStr(ob.name) - if world: - ambi = world.amb - ambientIntensity = ((float(ambi[0] + ambi[1] + ambi[2]))/3)/2.5 - else: - ambi = 0 - ambientIntensity = 0 - - # compute cutoff and beamwidth - intensity=min(lamp.energy/1.75,1.0) - beamWidth=((lamp.spotSize*math.pi)/180.0)*.37; - cutOffAngle=beamWidth*1.3 - - dx,dy,dz=self.computeDirection(mtx) - # note -dx seems to equal om[3][0] - # note -dz seems to equal om[3][1] - # note dy seems to equal om[3][2] - - #location=(ob.matrixWorld*MATWORLD).translationPart() # now passed - location=(mtx*MATWORLD).translationPart() - - radius = lamp.dist*math.cos(beamWidth) - self.file.write("<SpotLight DEF=\"%s\" " % safeName) - self.file.write("radius=\"%s\" " % (round(radius,self.cp))) - self.file.write("ambientIntensity=\"%s\" " % (round(ambientIntensity,self.cp))) - self.file.write("intensity=\"%s\" " % (round(intensity,self.cp))) - self.file.write("color=\"%s %s %s\" " % (round(lamp.col[0],self.cp), round(lamp.col[1],self.cp), round(lamp.col[2],self.cp))) - self.file.write("beamWidth=\"%s\" " % (round(beamWidth,self.cp))) - self.file.write("cutOffAngle=\"%s\" " % (round(cutOffAngle,self.cp))) - self.file.write("direction=\"%s %s %s\" " % (round(dx,3),round(dy,3),round(dz,3))) - self.file.write("location=\"%s %s %s\" />\n\n" % (round(location[0],3), round(location[1],3), round(location[2],3))) - - - def writeDirectionalLight(self, ob, mtx, lamp, world): - safeName = self.cleanStr(ob.name) - if world: - ambi = world.amb - ambientIntensity = ((float(ambi[0] + ambi[1] + ambi[2]))/3)/2.5 - else: - ambi = 0 - ambientIntensity = 0 - - intensity=min(lamp.energy/1.75,1.0) - (dx,dy,dz)=self.computeDirection(mtx) - self.file.write("<DirectionalLight DEF=\"%s\" " % safeName) - self.file.write("ambientIntensity=\"%s\" " % (round(ambientIntensity,self.cp))) - self.file.write("color=\"%s %s %s\" " % (round(lamp.col[0],self.cp), round(lamp.col[1],self.cp), round(lamp.col[2],self.cp))) - self.file.write("intensity=\"%s\" " % (round(intensity,self.cp))) - self.file.write("direction=\"%s %s %s\" />\n\n" % (round(dx,4),round(dy,4),round(dz,4))) - - def writePointLight(self, ob, mtx, lamp, world): - safeName = self.cleanStr(ob.name) - if world: - ambi = world.amb - ambientIntensity = ((float(ambi[0] + ambi[1] + ambi[2]))/3)/2.5 - else: - ambi = 0 - ambientIntensity = 0 - - # location=(ob.matrixWorld*MATWORLD).translationPart() # now passed - location= (mtx*MATWORLD).translationPart() - - self.file.write("<PointLight DEF=\"%s\" " % safeName) - self.file.write("ambientIntensity=\"%s\" " % (round(ambientIntensity,self.cp))) - self.file.write("color=\"%s %s %s\" " % (round(lamp.col[0],self.cp), round(lamp.col[1],self.cp), round(lamp.col[2],self.cp))) - self.file.write("intensity=\"%s\" " % (round( min(lamp.energy/1.75,1.0) ,self.cp))) - self.file.write("radius=\"%s\" " % lamp.dist ) - self.file.write("location=\"%s %s %s\" />\n\n" % (round(location[0],3), round(location[1],3), round(location[2],3))) - ''' - def writeNode(self, ob, mtx): - obname=str(ob.name) - if obname in self.namesStandard: - return - else: - dx,dy,dz = self.computeDirection(mtx) - # location=(ob.matrixWorld*MATWORLD).translationPart() - location=(mtx*MATWORLD).translationPart() - self.writeIndented("<%s\n" % obname,1) - self.writeIndented("direction=\"%s %s %s\"\n" % (round(dx,3),round(dy,3),round(dz,3))) - self.writeIndented("location=\"%s %s %s\"\n" % (round(location[0],3), round(location[1],3), round(location[2],3))) - self.writeIndented("/>\n",-1) - self.writeIndented("\n") - ''' - def secureName(self, name): - name = name + str(self.nodeID) - self.nodeID=self.nodeID+1 - if len(name) <= 3: - newname = "_" + str(self.nodeID) - return "%s" % (newname) - else: - for bad in ['"','#',"'",',','.','[','\\',']','{','}']: - name=name.replace(bad,'_') - if name in self.namesReserved: - newname = name[0:3] + "_" + str(self.nodeID) - return "%s" % (newname) - elif name[0].isdigit(): - newname = "_" + name + str(self.nodeID) - return "%s" % (newname) - else: - newname = name - return "%s" % (newname) - - def writeIndexedFaceSet(self, ob, mesh, mtx, world, EXPORT_TRI = False): - imageMap={} # set of used images - sided={} # 'one':cnt , 'two':cnt - vColors={} # 'multi':1 - meshName = self.cleanStr(ob.name) - - meshME = self.cleanStr(ob.getData(mesh=1).name) # We dont care if its the mesh name or not - if len(mesh.faces) == 0: return - mode = 0 - if mesh.faceUV: - for face in mesh.faces: - mode |= face.mode - - if mode & Mesh.FaceModes.HALO and self.halonode == 0: - self.writeIndented("<Billboard axisOfRotation=\"0 0 0\">\n",1) - self.halonode = 1 - elif mode & Mesh.FaceModes.BILLBOARD and self.billnode == 0: - self.writeIndented("<Billboard axisOfRotation=\"0 1 0\">\n",1) - self.billnode = 1 - elif mode & Mesh.FaceModes.OBCOL and self.matonly == 0: - self.matonly = 1 - elif mode & Mesh.FaceModes.TILES and self.tilenode == 0: - self.tilenode = 1 - elif not mode & Mesh.FaceModes.DYNAMIC and self.collnode == 0: - self.writeIndented("<Collision enabled=\"false\">\n",1) - self.collnode = 1 - - nIFSCnt=self.countIFSSetsNeeded(mesh, imageMap, sided, vColors) - - if nIFSCnt > 1: - self.writeIndented("<Group DEF=\"%s%s\">\n" % ("G_", meshName),1) - - if sided.has_key('two') and sided['two'] > 0: - bTwoSided=1 - else: - bTwoSided=0 - - # mtx = ob.matrixWorld * MATWORLD # mtx is now passed - mtx = mtx * MATWORLD - - loc= mtx.translationPart() - sca= mtx.scalePart() - quat = mtx.toQuat() - rot= quat.axis - - # self.writeIndented('<Transform rotation="%.6f %.6f %.6f %.6f">\n' % (rot[0], rot[1], rot[2], rot[3])) - self.writeIndented('<Transform DEF="%s" translation="%.6f %.6f %.6f" scale="%.6f %.6f %.6f" rotation="%.6f %.6f %.6f %.6f">\n' % \ - (meshName, loc[0], loc[1], loc[2], sca[0], sca[1], sca[2], rot[0], rot[1], rot[2], quat.angle*DEG2RAD) ) - - self.writeIndented("<Shape>\n",1) - maters=mesh.materials - hasImageTexture=0 - issmooth=0 - - if len(maters) > 0 or mesh.faceUV: - self.writeIndented("<Appearance>\n", 1) - # right now this script can only handle a single material per mesh. - if len(maters) >= 1: - mat=maters[0] - matFlags = mat.getMode() - if not matFlags & Blender.Material.Modes['TEXFACE']: - self.writeMaterial(mat, self.cleanStr(maters[0].name,''), world) - if len(maters) > 1: - print "Warning: mesh named %s has multiple materials" % meshName - print "Warning: only one material per object handled" - - #-- textures - if mesh.faceUV: - for face in mesh.faces: - if (hasImageTexture == 0) and (face.image): - self.writeImageTexture(face.image) - hasImageTexture=1 # keep track of face texture - if self.tilenode == 1: - self.writeIndented("<TextureTransform scale=\"%s %s\" />\n" % (face.image.xrep, face.image.yrep)) - self.tilenode = 0 - self.writeIndented("</Appearance>\n", -1) - - #-- IndexedFaceSet or IndexedLineSet - - # user selected BOUNDS=1, SOLID=3, SHARED=4, or TEXTURE=5 - ifStyle="IndexedFaceSet" - # look up mesh name, use it if available - if self.meshNames.has_key(meshME): - self.writeIndented("<%s USE=\"ME_%s\">" % (ifStyle, meshME), 1) - self.meshNames[meshME]+=1 - else: - if int(mesh.users) > 1: - self.writeIndented("<%s DEF=\"ME_%s\" " % (ifStyle, meshME), 1) - self.meshNames[meshME]=1 - else: - self.writeIndented("<%s " % ifStyle, 1) - - if bTwoSided == 1: - self.file.write("solid=\"false\" ") - else: - self.file.write("solid=\"true\" ") - - for face in mesh.faces: - if face.smooth: - issmooth=1 - break - if issmooth==1: - creaseAngle=(mesh.degr)*(math.pi/180.0) - self.file.write("creaseAngle=\"%s\" " % (round(creaseAngle,self.cp))) - - #--- output textureCoordinates if UV texture used - if mesh.faceUV: - if self.matonly == 1 and self.share == 1: - self.writeFaceColors(mesh) - elif hasImageTexture == 1: - self.writeTextureCoordinates(mesh) - #--- output coordinates - self.writeCoordinates(ob, mesh, meshName, EXPORT_TRI) - - self.writingcoords = 1 - self.writingtexture = 1 - self.writingcolor = 1 - self.writeCoordinates(ob, mesh, meshName, EXPORT_TRI) - - #--- output textureCoordinates if UV texture used - if mesh.faceUV: - if hasImageTexture == 1: - self.writeTextureCoordinates(mesh) - elif self.matonly == 1 and self.share == 1: - self.writeFaceColors(mesh) - #--- output vertexColors - self.matonly = 0 - self.share = 0 - - self.writingcoords = 0 - self.writingtexture = 0 - self.writingcolor = 0 - #--- output closing braces - self.writeIndented("</%s>\n" % ifStyle, -1) - self.writeIndented("</Shape>\n", -1) - self.writeIndented("</Transform>\n", -1) - - if self.halonode == 1: - self.writeIndented("</Billboard>\n", -1) - self.halonode = 0 - - if self.billnode == 1: - self.writeIndented("</Billboard>\n", -1) - self.billnode = 0 - - if self.collnode == 1: - self.writeIndented("</Collision>\n", -1) - self.collnode = 0 - - if nIFSCnt > 1: - self.writeIndented("</Group>\n", -1) - - self.file.write("\n") - - def writeCoordinates(self, ob, mesh, meshName, EXPORT_TRI = False): - # create vertex list and pre rotate -90 degrees X for VRML - - if self.writingcoords == 0: - self.file.write('coordIndex="') - for face in mesh.faces: - fv = face.v - - if len(face)==3: - self.file.write("%i %i %i -1, " % (fv[0].index, fv[1].index, fv[2].index)) - else: - if EXPORT_TRI: - self.file.write("%i %i %i -1, " % (fv[0].index, fv[1].index, fv[2].index)) - self.file.write("%i %i %i -1, " % (fv[0].index, fv[2].index, fv[3].index)) - else: - self.file.write("%i %i %i %i -1, " % (fv[0].index, fv[1].index, fv[2].index, fv[3].index)) - - self.file.write("\">\n") - else: - #-- vertices - # mesh.transform(ob.matrixWorld) - self.writeIndented("<Coordinate DEF=\"%s%s\" \n" % ("coord_",meshName), 1) - self.file.write("\t\t\t\tpoint=\"") - for v in mesh.verts: - self.file.write("%.6f %.6f %.6f, " % tuple(v.co)) - self.file.write("\" />") - self.writeIndented("\n", -1) - - def writeTextureCoordinates(self, mesh): - texCoordList=[] - texIndexList=[] - j=0 - - for face in mesh.faces: - for uv in face.uv: - texIndexList.append(j) - texCoordList.append(uv) - j=j+1 - texIndexList.append(-1) - if self.writingtexture == 0: - self.file.write("\n\t\t\ttexCoordIndex=\"") - texIndxStr="" - for i in xrange(len(texIndexList)): - texIndxStr = texIndxStr + "%d, " % texIndexList[i] - if texIndexList[i]==-1: - self.file.write(texIndxStr) - texIndxStr="" - self.file.write("\"\n\t\t\t") - else: - self.writeIndented("<TextureCoordinate point=\"", 1) - for i in xrange(len(texCoordList)): - self.file.write("%s %s, " % (round(texCoordList[i][0],self.tp), round(texCoordList[i][1],self.tp))) - self.file.write("\" />") - self.writeIndented("\n", -1) - - def writeFaceColors(self, mesh): - if self.writingcolor == 0: - self.file.write("colorPerVertex=\"false\" ") - else: - self.writeIndented("<Color color=\"", 1) - for face in mesh.faces: - if face.col: - c=face.col[0] - if self.verbose > 2: - print "Debug: face.col r=%d g=%d b=%d" % (c.r, c.g, c.b) - aColor = self.rgbToFS(c) - self.file.write("%s, " % aColor) - self.file.write("\" />") - self.writeIndented("\n",-1) - - def writeMaterial(self, mat, matName, world): - # look up material name, use it if available - if self.matNames.has_key(matName): - self.writeIndented("<Material USE=\"MA_%s\" />\n" % matName) - self.matNames[matName]+=1 - return; - - self.matNames[matName]=1 - - ambient = mat.amb/3 - diffuseR, diffuseG, diffuseB = mat.rgbCol[0], mat.rgbCol[1],mat.rgbCol[2] - if world: - ambi = world.getAmb() - ambi0, ambi1, ambi2 = (ambi[0]*mat.amb)*2, (ambi[1]*mat.amb)*2, (ambi[2]*mat.amb)*2 - else: - ambi0, ambi1, ambi2 = 0, 0, 0 - emisR, emisG, emisB = (diffuseR*mat.emit+ambi0)/2, (diffuseG*mat.emit+ambi1)/2, (diffuseB*mat.emit+ambi2)/2 - - shininess = mat.hard/512.0 - specR = (mat.specCol[0]+0.001)/(1.25/(mat.spec+0.001)) - specG = (mat.specCol[1]+0.001)/(1.25/(mat.spec+0.001)) - specB = (mat.specCol[2]+0.001)/(1.25/(mat.spec+0.001)) - transp = 1-mat.alpha - matFlags = mat.getMode() - if matFlags & Blender.Material.Modes['SHADELESS']: - ambient = 1 - shine = 1 - specR = emitR = diffuseR - specG = emitG = diffuseG - specB = emitB = diffuseB - self.writeIndented("<Material DEF=\"MA_%s\" " % matName, 1) - self.file.write("diffuseColor=\"%s %s %s\" " % (round(diffuseR,self.cp), round(diffuseG,self.cp), round(diffuseB,self.cp))) - self.file.write("specularColor=\"%s %s %s\" " % (round(specR,self.cp), round(specG,self.cp), round(specB,self.cp))) - self.file.write("emissiveColor=\"%s %s %s\" \n" % (round(emisR,self.cp), round(emisG,self.cp), round(emisB,self.cp))) - self.writeIndented("ambientIntensity=\"%s\" " % (round(ambient,self.cp))) - self.file.write("shininess=\"%s\" " % (round(shininess,self.cp))) - self.file.write("transparency=\"%s\" />" % (round(transp,self.cp))) - self.writeIndented("\n",-1) - - def writeImageTexture(self, image): - name = image.name - filename = image.filename.split('/')[-1].split('\\')[-1] - if self.texNames.has_key(name): - self.writeIndented("<ImageTexture USE=\"%s\" />\n" % self.cleanStr(name)) - self.texNames[name] += 1 - return - else: - self.writeIndented("<ImageTexture DEF=\"%s\" " % self.cleanStr(name), 1) - self.file.write("url=\"%s\" />" % name) - self.writeIndented("\n",-1) - self.texNames[name] = 1 - - def writeBackground(self, world, alltextures): - if world: worldname = world.name - else: return - blending = world.getSkytype() - grd = world.getHor() - grd0, grd1, grd2 = grd[0], grd[1], grd[2] - sky = world.getZen() - sky0, sky1, sky2 = sky[0], sky[1], sky[2] - mix0, mix1, mix2 = grd[0]+sky[0], grd[1]+sky[1], grd[2]+sky[2] - mix0, mix1, mix2 = mix0/2, mix1/2, mix2/2 - self.file.write("<Background ") - if worldname not in self.namesStandard: - self.file.write("DEF=\"%s\" " % self.secureName(worldname)) - # No Skytype - just Hor color - if blending == 0: - self.file.write("groundColor=\"%s %s %s\" " % (round(grd0,self.cp), round(grd1,self.cp), round(grd2,self.cp))) - self.file.write("skyColor=\"%s %s %s\" " % (round(grd0,self.cp), round(grd1,self.cp), round(grd2,self.cp))) - # Blend Gradient - elif blending == 1: - self.file.write("groundColor=\"%s %s %s, " % (round(grd0,self.cp), round(grd1,self.cp), round(grd2,self.cp))) - self.file.write("%s %s %s\" groundAngle=\"1.57, 1.57\" " %(round(mix0,self.cp), round(mix1,self.cp), round(mix2,self.cp))) - self.file.write("skyColor=\"%s %s %s, " % (round(sky0,self.cp), round(sky1,self.cp), round(sky2,self.cp))) - self.file.write("%s %s %s\" skyAngle=\"1.57, 1.57\" " %(round(mix0,self.cp), round(mix1,self.cp), round(mix2,self.cp))) - # Blend+Real Gradient Inverse - elif blending == 3: - self.file.write("groundColor=\"%s %s %s, " % (round(sky0,self.cp), round(sky1,self.cp), round(sky2,self.cp))) - self.file.write("%s %s %s\" groundAngle=\"1.57, 1.57\" " %(round(mix0,self.cp), round(mix1,self.cp), round(mix2,self.cp))) - self.file.write("skyColor=\"%s %s %s, " % (round(grd0,self.cp), round(grd1,self.cp), round(grd2,self.cp))) - self.file.write("%s %s %s\" skyAngle=\"1.57, 1.57\" " %(round(mix0,self.cp), round(mix1,self.cp), round(mix2,self.cp))) - # Paper - just Zen Color - elif blending == 4: - self.file.write("groundColor=\"%s %s %s\" " % (round(sky0,self.cp), round(sky1,self.cp), round(sky2,self.cp))) - self.file.write("skyColor=\"%s %s %s\" " % (round(sky0,self.cp), round(sky1,self.cp), round(sky2,self.cp))) - # Blend+Real+Paper - komplex gradient - elif blending == 7: - self.writeIndented("groundColor=\"%s %s %s, " % (round(sky0,self.cp), round(sky1,self.cp), round(sky2,self.cp))) - self.writeIndented("%s %s %s\" groundAngle=\"1.57, 1.57\" " %(round(grd0,self.cp), round(grd1,self.cp), round(grd2,self.cp))) - self.writeIndented("skyColor=\"%s %s %s, " % (round(sky0,self.cp), round(sky1,self.cp), round(sky2,self.cp))) - self.writeIndented("%s %s %s\" skyAngle=\"1.57, 1.57\" " %(round(grd0,self.cp), round(grd1,self.cp), round(grd2,self.cp))) - # Any Other two colors - else: - self.file.write("groundColor=\"%s %s %s\" " % (round(grd0,self.cp), round(grd1,self.cp), round(grd2,self.cp))) - self.file.write("skyColor=\"%s %s %s\" " % (round(sky0,self.cp), round(sky1,self.cp), round(sky2,self.cp))) - alltexture = len(alltextures) - for i in xrange(alltexture): - namemat = alltextures[i].name - pic = alltextures[i].getImage() - if (namemat == "back") and (pic != None): - self.file.write("\n\tbackUrl=\"%s\" " % pic.filename.split('/')[-1].split('\\')[-1]) - elif (namemat == "bottom") and (pic != None): - self.writeIndented("bottomUrl=\"%s\" " % pic.filename.split('/')[-1].split('\\')[-1]) - elif (namemat == "front") and (pic != None): - self.writeIndented("frontUrl=\"%s\" " % pic.filename.split('/')[-1].split('\\')[-1]) - elif (namemat == "left") and (pic != None): - self.writeIndented("leftUrl=\"%s\" " % pic.filename.split('/')[-1].split('\\')[-1]) - elif (namemat == "right") and (pic != None): - self.writeIndented("rightUrl=\"%s\" " % pic.filename.split('/')[-1].split('\\')[-1]) - elif (namemat == "top") and (pic != None): - self.writeIndented("topUrl=\"%s\" " % pic.filename.split('/')[-1].split('\\')[-1]) - self.writeIndented("/>\n\n") - -########################################################## -# export routine -########################################################## - - def export(self, scene, world, alltextures,\ - EXPORT_APPLY_MODIFIERS = False,\ - EXPORT_TRI= False,\ - ): - - print "Info: starting X3D export to " + self.filename + "..." - self.writeHeader() - # self.writeScript() - self.writeNavigationInfo(scene) - self.writeBackground(world, alltextures) - self.writeFog(world) - self.proto = 0 - - - # COPIED FROM OBJ EXPORTER - if EXPORT_APPLY_MODIFIERS: - temp_mesh_name = '~tmp-mesh' - - # Get the container mesh. - used for applying modifiers and non mesh objects. - containerMesh = meshName = tempMesh = None - for meshName in Blender.NMesh.GetNames(): - if meshName.startswith(temp_mesh_name): - tempMesh = Mesh.Get(meshName) - if not tempMesh.users: - containerMesh = tempMesh - if not containerMesh: - containerMesh = Mesh.New(temp_mesh_name) - # -------------------------- - - - for ob_main in scene.objects.context: - for ob, ob_mat in BPyObject.getDerivedObjects(ob_main): - objType=ob.type - objName=ob.name - self.matonly = 0 - if objType == "Camera": - self.writeViewpoint(ob, ob_mat, scene) - elif objType in ("Mesh", "Curve", "Surf", "Text") : - if EXPORT_APPLY_MODIFIERS or objType != 'Mesh': - me= BPyMesh.getMeshFromObject(ob, containerMesh, EXPORT_APPLY_MODIFIERS, False, scene) - else: - me = ob.getData(mesh=1) - - self.writeIndexedFaceSet(ob, me, ob_mat, world, EXPORT_TRI = EXPORT_TRI) - elif objType == "Lamp": - data= ob.data - datatype=data.type - if datatype == Lamp.Types.Lamp: - self.writePointLight(ob, ob_mat, data, world) - elif datatype == Lamp.Types.Spot: - self.writeSpotLight(ob, ob_mat, data, world) - elif datatype == Lamp.Types.Sun: - self.writeDirectionalLight(ob, ob_mat, data, world) - else: - self.writeDirectionalLight(ob, ob_mat, data, world) - # do you think x3d could document what to do with dummy objects? - #elif objType == "Empty" and objName != "Empty": - # self.writeNode(ob, ob_mat) - else: - #print "Info: Ignoring [%s], object type [%s] not handle yet" % (object.name,object.getType) - pass - - self.file.write("\n</Scene>\n</X3D>") - - if EXPORT_APPLY_MODIFIERS: - if containerMesh: - containerMesh.verts = None - - self.cleanup() - -########################################################## -# Utility methods -########################################################## - - def cleanup(self): - self.file.close() - self.texNames={} - self.matNames={} - self.indentLevel=0 - print "Info: finished X3D export to %s\n" % self.filename - - def cleanStr(self, name, prefix='rsvd_'): - """cleanStr(name,prefix) - try to create a valid VRML DEF name from object name""" - - newName=name[:] - if len(newName) == 0: - self.nNodeID+=1 - return "%s%d" % (prefix, self.nNodeID) - - if newName in self.namesReserved: - newName='%s%s' % (prefix,newName) - - if newName[0].isdigit(): - newName='%s%s' % ('_',newName) - - for bad in [' ','"','#',"'",',','.','[','\\',']','{','}']: - newName=newName.replace(bad,'_') - return newName - - def countIFSSetsNeeded(self, mesh, imageMap, sided, vColors): - """ - countIFFSetsNeeded() - should look at a blender mesh to determine - how many VRML IndexFaceSets or IndexLineSets are needed. A - new mesh created under the following conditions: - - o - split by UV Textures / one per mesh - o - split by face, one sided and two sided - o - split by smooth and flat faces - o - split when faces only have 2 vertices * needs to be an IndexLineSet - """ - - imageNameMap={} - faceMap={} - nFaceIndx=0 - - if mesh.faceUV: - for face in mesh.faces: - sidename=''; - if face.mode & Mesh.FaceModes.TWOSIDE: - sidename='two' - else: - sidename='one' - - if sided.has_key(sidename): - sided[sidename]+=1 - else: - sided[sidename]=1 - - image = face.image - if image: - faceName="%s_%s" % (face.image.name, sidename); - try: - imageMap[faceName].append(face) - except: - imageMap[faceName]=[face.image.name,sidename,face] - - if self.verbose > 2: - for faceName in imageMap.iterkeys(): - ifs=imageMap[faceName] - print "Debug: faceName=%s image=%s, solid=%s facecnt=%d" % \ - (faceName, ifs[0], ifs[1], len(ifs)-2) - - return len(imageMap) - - def faceToString(self,face): - - print "Debug: face.flag=0x%x (bitflags)" % face.flag - if face.sel: - print "Debug: face.sel=true" - - print "Debug: face.mode=0x%x (bitflags)" % face.mode - if face.mode & Mesh.FaceModes.TWOSIDE: - print "Debug: face.mode twosided" - - print "Debug: face.transp=0x%x (enum)" % face.transp - if face.transp == Mesh.FaceTranspModes.SOLID: - print "Debug: face.transp.SOLID" - - if face.image: - print "Debug: face.image=%s" % face.image.name - print "Debug: face.materialIndex=%d" % face.materialIndex - - def getVertexColorByIndx(self, mesh, indx): - c = None - for face in mesh.faces: - j=0 - for vertex in face.v: - if vertex.index == indx: - c=face.col[j] - break - j=j+1 - if c: break - return c - - def meshToString(self,mesh): - print "Debug: mesh.hasVertexUV=%d" % mesh.vertexColors - print "Debug: mesh.faceUV=%d" % mesh.faceUV - print "Debug: mesh.hasVertexColours=%d" % mesh.hasVertexColours() - print "Debug: mesh.verts=%d" % len(mesh.verts) - print "Debug: mesh.faces=%d" % len(mesh.faces) - print "Debug: mesh.materials=%d" % len(mesh.materials) - - def rgbToFS(self, c): - s="%s %s %s" % ( - round(c.r/255.0,self.cp), - round(c.g/255.0,self.cp), - round(c.b/255.0,self.cp)) - return s - - def computeDirection(self, mtx): - x,y,z=(0,-1.0,0) # point down - - ax,ay,az = (mtx*MATWORLD).toEuler() - - ax *= DEG2RAD - ay *= DEG2RAD - az *= DEG2RAD - # rot X - x1=x - y1=y*math.cos(ax)-z*math.sin(ax) - z1=y*math.sin(ax)+z*math.cos(ax) - - # rot Y - x2=x1*math.cos(ay)+z1*math.sin(ay) - y2=y1 - z2=z1*math.cos(ay)-x1*math.sin(ay) - - # rot Z - x3=x2*math.cos(az)-y2*math.sin(az) - y3=x2*math.sin(az)+y2*math.cos(az) - z3=z2 - - return [x3,y3,z3] - - - # swap Y and Z to handle axis difference between Blender and VRML - #------------------------------------------------------------------------ - def rotatePointForVRML(self, v): - x = v[0] - y = v[2] - z = -v[1] - - vrmlPoint=[x, y, z] - return vrmlPoint - - # For writing well formed VRML code - #------------------------------------------------------------------------ - def writeIndented(self, s, inc=0): - if inc < 1: - self.indentLevel = self.indentLevel + inc - - spaces="" - for x in xrange(self.indentLevel): - spaces = spaces + "\t" - self.file.write(spaces + s) - - if inc > 0: - self.indentLevel = self.indentLevel + inc - - # Converts a Euler to three new Quaternions - # Angles of Euler are passed in as radians - #------------------------------------------------------------------------ - def eulerToQuaternions(self, x, y, z): - Qx = [math.cos(x/2), math.sin(x/2), 0, 0] - Qy = [math.cos(y/2), 0, math.sin(y/2), 0] - Qz = [math.cos(z/2), 0, 0, math.sin(z/2)] - - quaternionVec=[Qx,Qy,Qz] - return quaternionVec - - # Multiply two Quaternions together to get a new Quaternion - #------------------------------------------------------------------------ - def multiplyQuaternions(self, Q1, Q2): - result = [((Q1[0] * Q2[0]) - (Q1[1] * Q2[1]) - (Q1[2] * Q2[2]) - (Q1[3] * Q2[3])), - ((Q1[0] * Q2[1]) + (Q1[1] * Q2[0]) + (Q1[2] * Q2[3]) - (Q1[3] * Q2[2])), - ((Q1[0] * Q2[2]) + (Q1[2] * Q2[0]) + (Q1[3] * Q2[1]) - (Q1[1] * Q2[3])), - ((Q1[0] * Q2[3]) + (Q1[3] * Q2[0]) + (Q1[1] * Q2[2]) - (Q1[2] * Q2[1]))] - - return result - - # Convert a Quaternion to an Angle Axis (ax, ay, az, angle) - # angle is in radians - #------------------------------------------------------------------------ - def quaternionToAngleAxis(self, Qf): - scale = math.pow(Qf[1],2) + math.pow(Qf[2],2) + math.pow(Qf[3],2) - ax = Qf[1] - ay = Qf[2] - az = Qf[3] - - if scale > .0001: - ax/=scale - ay/=scale - az/=scale - - angle = 2 * math.acos(Qf[0]) - - result = [ax, ay, az, angle] - return result - -########################################################## -# Callbacks, needed before Main -########################################################## - -def x3d_export(filename, \ - EXPORT_APPLY_MODIFIERS= False,\ - EXPORT_TRI= False,\ - EXPORT_GZIP= False,\ - ): - - if EXPORT_GZIP: - if not filename.lower().endswith('.x3dz'): - filename = '.'.join(filename.split('.')[:-1]) + '.x3dz' - else: - if not filename.lower().endswith('.x3d'): - filename = '.'.join(filename.split('.')[:-1]) + '.x3d' - - - scene = Blender.Scene.GetCurrent() - world = scene.world - alltextures = Blender.Texture.Get() - - wrlexport=x3d_class(filename) - wrlexport.export(\ - scene,\ - world,\ - alltextures,\ - \ - EXPORT_APPLY_MODIFIERS = EXPORT_APPLY_MODIFIERS,\ - EXPORT_TRI = EXPORT_TRI,\ - ) - - -def x3d_export_ui(filename): - if not filename.endswith(extension): - filename += extension - #if _safeOverwrite and sys.exists(filename): - # result = Draw.PupMenu("File Already Exists, Overwrite?%t|Yes%x1|No%x0") - #if(result != 1): - # return - - # Get user options - EXPORT_APPLY_MODIFIERS = Draw.Create(1) - EXPORT_TRI = Draw.Create(0) - EXPORT_GZIP = Draw.Create( filename.lower().endswith('.x3dz') ) - - # Get USER Options - pup_block = [\ - ('Apply Modifiers', EXPORT_APPLY_MODIFIERS, 'Use transformed mesh data from each object.'),\ - ('Triangulate', EXPORT_TRI, 'Triangulate quads.'),\ - ('Compress', EXPORT_GZIP, 'GZip the resulting file, requires a full python install'),\ - ] - - if not Draw.PupBlock('Export...', pup_block): - return - - Blender.Window.EditMode(0) - Blender.Window.WaitCursor(1) - - x3d_export(filename,\ - EXPORT_APPLY_MODIFIERS = EXPORT_APPLY_MODIFIERS.val,\ - EXPORT_TRI = EXPORT_TRI.val,\ - EXPORT_GZIP = EXPORT_GZIP.val\ - ) - - Blender.Window.WaitCursor(0) - - - -######################################################### -# main routine -######################################################### - - -if __name__ == '__main__': - Blender.Window.FileSelector(x3d_export_ui,"Export X3D", Blender.Get('filename').replace('.blend', '.x3d')) - - diff --git a/release/scripts/xsi_export.py b/release/scripts/xsi_export.py deleted file mode 100644 index d86d8cb82cf..00000000000 --- a/release/scripts/xsi_export.py +++ /dev/null @@ -1,1227 +0,0 @@ -#!BPY - - -""" -Name: 'SoftImage XSI (.xsi)...' -Blender: 236 -Group: 'Export' -Tooltip: 'Export to a SoftImage XSI file' -""" - -__author__ = ("Elira") -__url__ = ["Author's site, http://www.creative-realms.net/~elira/blender.html", -"SoftImage's site, www.softimage.com", "blenderartists.org"] -__email__ = ["scripts"] -__version__ = "2005/11/01" - - -__bpydoc__ = """\ -This script exports to the XSI format. - -Usage: - -Run this script from "File->Export" menu. - -Note:<br> -- Updates by Mal Duffin, to assist with XSI to Shockwave 3D conversion. -""" - -# $Id: xsi_export.py,v 1.4.6 2005/11/01 -# -#------------------------------------------------------------------------ -# XSI exporter for blender 2.36 or above -# -# ***** 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 ***** -# - - -# -# --------------------------------------------------------------------------- -# XSI Export V 1.4.1 by Elira (at) creative-realms (dot) net -# -# Updates by Mal Duffin, to assist with XSI to Shockwave 3D conversion -# --------------------------------------------------------------------------- -# 0.0.0 - This header and having blender ID the file. -# 0.1.0 - Output the statis xsi header elements -# 0.2.0 - create a full shell output (no content just structure) -# 0.3.0 - output used materials from the full materials list -# 0.4.0 - output the object model minor data -# 0.5.0 - output the object shape data, storing a uv table -# 0.6.0 - output the triangle lists (uv references stored uv table) -# 0.7.0 - convert output to genuine file writes. -# 1.0.0 - Admit this script exists and wait for flames -# 1.1.0 - Correctly export mesh shapes -# 1.2.0 - Mesh positioning corrected, added back normals -# 1.3.0 - conditionally output uv co-ordinates -# 1.4.0 - export vertex paint colours. -# --------------------------------------------------------------------------- -# 1.4.1 - added basic normal export code, -# to get XSI to Shockwave 3D converter working ( Mal Duffin ) -# 1.4.2 - invalid mesh checking -# better normal exporting -# general code clean up -# 1.4.3 - basic light exporting -# fix for ambient light being ignored by Shockwave 3D converter -# 1.4.4 - basic camera exporting -# 1.4.5 - exports normals correctly -# 1.4.6 - exports multiple materials per object -# --------------------------------------------------------------------------- -# TO DO -# - Support texturing -# - for both methods of texturing ( render method, and Game Engine method ) -# --------------------------------------------------------------------------- -# add required modules - -import Blender -from Blender import sys as bsys -from Blender import Mathutils -from Blender import Lamp -from Blender import Camera -import math - - - -# --------------------------------------------------------------------------- -# globals to make things a lot lot easier -OBJ = [] # the object list -MAT = [] # the materials list -UVC = [] # uv vert co-ords -UVI = [] # uv vert index -VCC = [] # vert colour co-ords -VCI = [] # vert colour index -FD = [] # file handle -NORMALS = [] # normal list -mats = [] -EXPORT_DIR = '' -WORLD = Blender.World.GetCurrent() - -# --------------------------------------------------------------------------- -# get_path returns the path portion o/wf the supplied filename. -# --------------------------------------------------------------------------- -def get_path(file): - l=len(file) - r=0 - for i in range(l, 0, -1): - if r == 0: - if file[i-1] == "/" or file[i-1] == "\\": - r = i - return file[:r] - - - -# --------------------------------------------------------------------------- -# r2d - radians to degrees -# --------------------------------------------------------------------------- -def r2d(r): - return round(r*180.0/math.pi,4) - - - -# --------------------------------------------------------------------------- -# d2r - degrees to radians -# --------------------------------------------------------------------------- -def d2r(d): - return (d*math.pi)/180.0 - - - -# --------------------------------------------------------------------------- -# get_filename returns the filename -# --------------------------------------------------------------------------- -def get_filename(file): - l=len(file) - r=0 - for i in range(l, 0, -1): - if r == 0: - if file[i-1] == "/" or file[i-1] == "\\": - r = i - return file[r:] - - -# --------------------------------------------------------------------------- -# find materials returns all materials on an object. -# --------------------------------------------------------------------------- -def get_materials(obj): - - # any materials attached to the object itself - mats = obj.getMaterials(0) - - if 'Mesh' != obj.type: - return mats - - # now drop down to the mesh level - #mesh = Blender.NMesh.GetRaw(obj.data.name) - - mats.extend(obj.getData(mesh=1).materials) - - # return the materials list - - # Is this correct!!?? - None materials raise an error otherwise - # but it might screw up the indicies.. TODO... check the exported files. - return [m for m in mats if m] - -# --------------------------------------------------------------------------- -# do_header writes out the header data -# --------------------------------------------------------------------------- -def do_header(): - - global FD - - # this says which xsi version - FD.write("xsi 0300txt 0032\n\n") - - # static fileinfo block - FD.write("SI_FileInfo {\n") - FD.write(" \"Blender Scene\",\n") - FD.write(" \"Blender User\",\n") - FD.write(" \"Now\",\n") - FD.write(" \"xsi_export Blender Scene Exporter\",\n") - FD.write("}\n\n") - - # static scene block - FD.write("SI_Scene no_name {\n") - FD.write(" \"FRAMES\",\n") - FD.write(" 0.000000,\n") - FD.write(" 100.000000,\n") - FD.write(" 30.000000,\n") - FD.write("}\n\n") - - # static co-ordinate system block - FD.write("SI_CoordinateSystem coord {\n") - FD.write(" 1,\n") - FD.write(" 0,\n") - FD.write(" 1,\n") - FD.write(" 0,\n") - FD.write(" 5,\n") - FD.write(" 2,\n") - FD.write("}\n\n") - - # static angle block - FD.write("SI_Angle {\n") - FD.write(" 0,\n") - FD.write("}\n\n") - - # static ambience block - if WORLD: ambient = WORLD.getAmb() - else: ambient = 0,0,0 - - FD.write("SI_Ambience {\n") - FD.write(" %f,\n" % ambient[0]) - FD.write(" %f,\n" % ambient[1]) - FD.write(" %f,\n" % ambient[2]) - FD.write("}\n\n") - - - -# --------------------------------------------------------------------------- -# do_materiallibrary writes out the materials subsection. -# --------------------------------------------------------------------------- -def do_materiallibrary(): - - global OBJ, MAT, FD - - # set some flags first - mnum = 0 - - # run through every material, how many used? - for mat in MAT: - nmat = mat.name - - # first, is this material on any of the objects. - f = 0 - for obj in OBJ: - ml = get_materials(obj) - for mli in ml: - nmli = mli.name - if nmli == nmat: - f = 1 - mnum += 1 - break - if f == 1: - break - - bCreateDefault = 0 - # if none then exit - if not mnum: - bCreateDefault = 1 -# return - - # get to work create the materiallibrary wrapper and fill. - FD.write("SI_MaterialLibrary {\n") - FD.write(" " + str(mnum) + ",\n") - - # run through every material, write the used ones - for mat in MAT: - nmat = mat.name - - # find out if on any object, if so we write. - f = 0 - for obj in OBJ: - ml = get_materials(obj) - for mli in ml: - nmli = mli.name - if nmli == nmat: - do_material(mat) - f = 1 - break - if f == 1: - break - - if bCreateDefault == 1: - do_material ( 0 ) - - # clean up - FD.write("}\n\n") - - -def removeSpacesFromName(name): - name = name.replace ( " ", "_" ) - return name - - -# --------------------------------------------------------------------------- -# do_material writes out this material. -# --------------------------------------------------------------------------- -def do_material(mat): - - global FD - - if mat == 0: - name = "__default" - cr = 1.0 - cg = 1.0 - cb = 1.0 - ca = 1.0 - sp = 0.0 - sr = 0.0 - sg = 0.0 - sb = 0.0 - em = 0.0 - am = 1.0 - sm = 0 - else: - - - # get the name first - name = mat.name - - # face colour r, g, b, a - # power (spec decay) fl - # spec colour r, g, b - # emmisive colourm r, g, b - # shading model int constant, lambert, phong, blinn, shadow, vertex - # ambient colour r, g, b - - # get and print the base material block - cr, cg, cb = mat.getRGBCol() - ca = mat.getAlpha() - - sp = 0.0 - sr, sg, sb = mat.getSpecCol() - em = mat.getEmit() - am = mat.getAmb() - - # how do we render this material? start with constant (0) - sm = 0 - fl = mat.getMode() - if fl & Blender.Material.Modes['VCOL_PAINT']: - sm = 5 - - - FD.write(" SI_Material " + removeSpacesFromName(name) + " {\n") - FD.write(" %f,\n" % cr) - FD.write(" %f,\n" % cg) - FD.write(" %f,\n" % cb) - FD.write(" %f,\n" % ca) - FD.write(" %f,\n" % sp) - FD.write(" %f,\n" % sr) - FD.write(" %f,\n" % sg) - FD.write(" %f,\n" % sb) - FD.write(" %f,\n" % em) - FD.write(" %f,\n" % em) - FD.write(" %f,\n" % em) - FD.write(" %d,\n" % sm) - #FD.write(" %f,\n" % am) - #FD.write(" %f,\n" % am) - #FD.write(" %f,\n" % am) - FD.write(" %f,\n" % cr) - FD.write(" %f,\n" % cg) - FD.write(" %f,\n" % cb) - - if mat != 0: - # if this material has a texture, then add here - mtex = mat.getTextures() - for mt in mtex: - if mt: - do_texture(mt) - - FD.write(" }\n") - - - -# --------------------------------------------------------------------------- -# do_texture writes out this texture if usable. -# --------------------------------------------------------------------------- -def do_texture(mtex): - global FD - - - # get our texture - tex = mtex.tex - tn = tex.name - - - # what type of texture, we are limitd - if tex.type != Blender.Texture.Types.IMAGE: - return - - - FD.write(" SI_Texture2D " + tn + " {\n") - - img = tex.getImage() - iname = get_filename(img.getFilename()) - - FD.write(" \"" + iname + "\",\n") - - # mapping type ? uv map wrapped is 4, how to detect? - # start with a simple xy mapping ie 0 - FD.write(" 4,\n") - - if img.has_data: ix, iy = img.getSize() - else: ix, iy = 512,512 - - # image width, and height - FD.write(" %d,\n" % ix) - FD.write(" %d,\n" % iy) - # u crop min/max, v crop min/max - mincu, mincv, maxcu, maxcv = tex.crop - FD.write(" %d,\n" % ( mincu * ix ) ) - FD.write(" %d,\n" % ( maxcu * ix - 1 ) ) - FD.write(" %d,\n" % ( mincv * iy ) ) - FD.write(" %d,\n" % ( maxcv * iy - 1) ) - # uv swap - uvs =0 - if (tex.flags & Blender.Texture.Flags.FLIPBLEND): - uvs = 1 - FD.write(" %d,\n" % uvs ) - # u/v repeat - if img.has_data: iru = img.getXRep() - else: iru = 1 - FD.write(" %d,\n" % iru ) - if img.has_data: irv = img.getYRep() - else: irv = 1 - - FD.write(" %d,\n" % irv ) - # u/v alt - 0, 0 - FD.write(" 0,\n" ) - FD.write(" 0,\n" ) - # u/v scale - 1,1 - FD.write(" 1.000000,\n" ) - FD.write(" 1.000000,\n" ) - # u/v offset - 0,0 - FD.write(" 0.000000,\n" ) - FD.write(" 0.000000,\n" ) - # proj mat 4x4 1 0 0 0, 0 1 0 0, 0 0 1 0, 0 0 0 1 is default - FD.write(" 1.000000,\n" ) - FD.write(" 0.000000,\n" ) - FD.write(" 0.000000,\n" ) - FD.write(" 0.000000,\n" ) - - FD.write(" 0.000000,\n" ) - FD.write(" 1.000000,\n" ) - FD.write(" 0.000000,\n" ) - FD.write(" 0.000000,\n" ) - - FD.write(" 0.000000,\n" ) - FD.write(" 0.000000,\n" ) - FD.write(" 1.000000,\n" ) - FD.write(" 0.000000,\n" ) - - FD.write(" 0.000000,\n" ) - FD.write(" 0.000000,\n" ) - FD.write(" 0.000000,\n" ) - FD.write(" 1.000000,\n" ) - - # blending type - 3 - FD.write(" 3,\n" ) - # blending - 1 - FD.write(" 1.000000,\n" ) - # ambient - 0 - FD.write(" 0.000000,\n" ) - # diffuse - 1 - FD.write(" 1.000000,\n" ) - # speculara - 0 - FD.write(" 0.000000,\n" ) - # transparent - 0 - FD.write(" 0.000000,\n" ) - # reflective - 0 - FD.write(" 0.000000,\n" ) - # roughness - 0 - FD.write(" 0.000000,\n" ) - - # close off this texture - FD.write(" }\n") - - - -# --------------------------------------------------------------------------- -# do_model_transform dumps out the transform data -# --------------------------------------------------------------------------- -def do_model_transform(obj): - - global FD - - # now output - FD.write(" SI_Transform SRT-" + removeSpacesFromName( obj.name ) + " {\n" ) - - - - # write out the object size? (scaling) - FD.write(" %f,\n" % obj.SizeX ) - FD.write(" %f,\n" % obj.SizeY ) - FD.write(" %f,\n" % obj.SizeZ ) - - # write out the object rotation - FD.write(" %f,\n" % r2d(obj.RotX) ) - FD.write(" %f,\n" % r2d(obj.RotY) ) - FD.write(" %f,\n" % r2d(obj.RotZ) ) - - # this is the position of the object's axis - FD.write(" %f,\n" % obj.LocX ) - FD.write(" %f,\n" % obj.LocY ) - FD.write(" %f,\n" % obj.LocZ ) - FD.write(" }\n\n") - - - -# --------------------------------------------------------------------------- -# do_model_visibility marks if the model is visible or not??? -# --------------------------------------------------------------------------- -def do_model_visibility(obj): - - global FD - - # for now this is a static block - FD.write(" SI_Visibility {\n" ) - FD.write(" 1,\n" ) - FD.write(" }\n\n" ) - - - -# --------------------------------------------------------------------------- -# do_model_material sets the global material for the model -# --------------------------------------------------------------------------- -def do_model_material(obj): - - global FD - - # do we have one? - ml = get_materials(obj) - - - n = 0 - for mli in ml: - if mli: - n+=1 - if n == 1: - mat=mli - - - # if no materials just go back - if n == 0: - return - - # for now we grab the first material on the list. - - for mat in ml: - FD.write(" SI_GlobalMaterial {\n" ) - FD.write(" \"" + removeSpacesFromName(mat.name) + "\",\n" ) - FD.write(" \"NODE\",\n" ) - FD.write(" }\n\n" ) - - -# --------------------------------------------------------------------------- -# do_collect_uv, makes an easy to use list out of the uv data -# todo, remove duplicates and compress the list size, xsi supports this. -# --------------------------------------------------------------------------- -def do_collect_uv(mesh): - - global UVC, UVI - - # reset the uv details first. - UVI = [] - UVC = [] - - #print "Textures..." - #mtex = mat.getTextures() - #for mt in mtex: - # print mt - - - # if no uv data then return - if not mesh.hasFaceUV(): - return - - # run through all the faces - j = 0 - for f in mesh.faces: - for uv in f.uv: - UVI.append(j) - UVC.append(uv) - j+=1 - UVI.append(-1) - - - -# --------------------------------------------------------------------------- -# do_collect_colour, makes an easy to use list out of the colour data -# todo, remove duplicates and compress the list size, xsi supports this. -# --------------------------------------------------------------------------- -def do_collect_colour(mesh): - - global VCC, VCI - - # reset the uv details first. - VCC = [] - VCI = [] - - # if no uv data then return - if not mesh.hasVertexColours(): - return - - # run through all the faces - j = 0 - for f in mesh.faces: - for c in f.col: - VCI.append(j) - VCC.append(c) - j+=1 - VCI.append(-1) - - - -# --------------------------------------------------------------------------- -# do_mesh_shape outputs the shape data -# --------------------------------------------------------------------------- -def do_mesh_shape(obj): - - global UVC, UVI, VCC, VCI, FD, NORMALS - - # Grab the mesh itself - mesh = obj.data - - # get the world matrix - matrix = obj.getMatrix('worldspace') - - # we need to decide about vertex and uv details first. - do_collect_uv(mesh) - do_collect_colour(mesh) - - # output the shell - elements=2 - if len(UVC): - elements+=1 - if len(VCC): - elements+=1 - FD.write(" SI_Shape SHP-" + removeSpacesFromName ( obj.name ) + "-ORG {\n" ) - FD.write(" %d,\n" % elements ) - FD.write(" \"ORDERED\",\n\n" ) - - # vertices first - FD.write(" %d,\n" % len(mesh.verts) ) - FD.write(" \"POSITION\",\n" ) - for v in mesh.verts: - FD.write(" %f,%f,%f,\n" % (v.co[0], v.co[1], v.co[2]) ) - FD.write("\n") - - - print " MESH NAME = " + mesh.name - - NORMALS = [] - for f in mesh.faces: - NORMALS.append ( f.no ) - for v in mesh.verts: - aTemp = [v.no[0], v.no[1], v.no[2]] - NORMALS.append ( aTemp ) - - - FD.write(" %d,\n" % len(NORMALS) ) - FD.write(" \"NORMAL\",\n" ) - - for n in NORMALS: - FD.write(" %f,%f,%f,\n" % ( n[0], n[1], n[2] ) ) - - # if vertex colour data then process - if mesh.hasVertexColours(): - - # put out the co-ord header - FD.write(" %d,\n" % len(VCC) ) - FD.write(" \"COLOR\",\n" ) - - # now output them - for vc in VCC: - FD.write(" %f,%f,%f,%f,\n" % (vc.r/255.0, vc.g/255.0, vc.b/255.0, vc.a/255.0) ) - - - - # if uv data then process - if mesh.hasFaceUV(): - # put out the co-ord header - FD.write(" %d,\n" % len(UVC) ) - FD.write(" \"TEX_COORD_UV\",\n" ) - - # now output them - for uv in UVC: - FD.write(" %f,%f\n" % (uv[0], uv[1]) ) - - # close off - FD.write(" }\n" ) - - - -# --------------------------------------------------------------------------- -# do_mesh_faces outputs the faces data -# --------------------------------------------------------------------------- -def do_mesh_faces(obj): - - global FD, UVI, VCI, mats - - # do we have a texture? - ml = get_materials(obj) - n = 0 - for mli in ml: - if mli: - n+=1 - if n == 1: - mat=mli - - # Grab the mesh itself - # mesh = Blender.NMesh.GetRaw(obj.data.name) - - # mesh = Blender.NMesh.GetRawFromObject(obj.name) - - mesh = obj.data - - - - tris = [] - normalX = [] - mats = [] - for f in mesh.faces: - tris.extend ( triangulate_face(f) ) - aVal = triangulate_normals(mesh,f) - - for v in aVal: - normalX.append ( v ) - - - triangles = len(tris) - - if n == 0: - FD.write(" SI_TriangleList " + removeSpacesFromName(obj.name) + " {\n") - FD.write(" %d,\n" % triangles) - - ostring=" \"NORMAL" - if len(VCI): - ostring += "|COLOR" - if len(UVC): - ostring += "|TEX_COORD_UV" - ostring += "\",\n" - FD.write(ostring) - - FD.write(" \"\",\n\n") - - for t in tris: - FD.write(" %d,%d,%d,\n" % (t[0], t[2], t[1])) - - FD.write("\n") - - for n in normalX: - FD.write(" %d,%d,%d,\n" % ( n[0], n[1], n[2] ) ) - - # finally close this triangle list off - FD.write(" }\n\n") - - - - print "total materials" - print ml - - for mIndex in range (0,len(ml)): - mat = ml[mIndex] - print "checking materials" - print mat - - aTriCount = 0 - for tIndex in range ( 0, len ( tris ) ): - aMat = mats[tIndex] - if aMat == mIndex: - aTriCount = aTriCount + 1 - - # - # output the shell - FD.write(" SI_TriangleList " + removeSpacesFromName(obj.name) + " {\n") - # FD.write(" %d,\n" % triangles) - FD.write(" %d,\n" % aTriCount) - - ostring=" \"NORMAL" - if len(VCI): - ostring += "|COLOR" - if len(UVC): - ostring += "|TEX_COORD_UV" - ostring += "\",\n" - FD.write(ostring) - - - FD.write(" \"" + removeSpacesFromName ( mat.name ) + "\",\n\n") - -# FD.write(" \"\",\n\n") - - - for tIndex in range ( 0, len ( tris ) ): - aMat = mats[tIndex] - if mIndex == aMat: - t = tris[tIndex] - FD.write(" %d,%d,%d,\n" % (t[0], t[2], t[1])) - - FD.write("\n") - - - -# for n in normalX: - for tIndex in range ( 0, len ( tris ) ): - aMat = mats[tIndex] - if mIndex == aMat: - n = normalX[tIndex] - FD.write(" %d,%d,%d,\n" % ( n[0], n[1], n[2] ) ) - - - - # if we have it, put out the colour vertex list - # ostring = " " - # for i in range(len(VCI)): - # if a -1 its end of line, write. - # if VCI[i] == -1: - # ostring = ostring + "\n" - # FD.write(ostring) - # ostring=" " - # else: - # ostring = ostring + "%d," % VCI[i] - - # The final set is to work out the uv list, its one set per face - # ostring = " " - # for i in range(len(UVI)): - # # if a -1 its end of line, write. - # if UVI[i] == -1: - # ostring = ostring + "\n" - # FD.write(ostring) - # ostring=" " - # else: - # ostring = ostring + "%d," % UVI[i] - - # finally close this triangle list off - FD.write(" }\n\n") - - -def getNormalInfo(mesh, faceInfo): - global NORMALS - aNL = [] - for fi in faceInfo: - aN = [] - - aFace = mesh.faces[fi[0]] - - print aFace - - if (aFace.smooth): - aN.append ( NORMALS.index ( aFace.v.no[0] ) ) - aN.append ( NORMALS.index ( aFace.v.no[1] ) ) - aN.append ( NORMALS.index ( aFace.v.no[2] ) ) - else: - aN.append ( NORMALS.index ( aFace.no ) ) - aN.append ( NORMALS.index ( aFace.no ) ) - aN.append ( NORMALS.index ( aFace.no ) ) - -# aN.append ( NORMALS.index ( mesh.faces[fi[0]].no ) ) -# aN.append ( NORMALS.index ( mesh.faces[fi[0]].no ) ) -# aN.append ( NORMALS.index ( mesh.faces[fi[0]].no ) ) - - aNL.append ( aN ) - return aNL - - - -# copy of code to triangulate mesh -################################## -def triangulate_face(f): - if len(f.v) <= 3: - #newFaces = [ [f.v[0].index, f.v[1].index, f.v[2].index] ] - newFaces = [ [f.v[0].index, f.v[2].index, f.v[1].index] ] - mats.append ( f.materialIndex ) - else: - #newFaces = [ [f.v[0].index, f.v[1].index, f.v[2].index] ] - #newFaces.append ( [f.v[3].index, f.v[0].index, f.v[2].index] ) - newFaces = [ [f.v[0].index, f.v[2].index, f.v[1].index] ] - newFaces.append ( [f.v[3].index, f.v[2].index, f.v[0].index] ) - mats.append ( f.materialIndex ) - mats.append ( f.materialIndex ) - - return newFaces - -# copy of code to triangulate mesh -################################## -def triangulate_normals(mesh, f): - - if len(f.v) <= 3: - if f.smooth: - n1 = get_normal_index ( mesh, [f.v[0].no[0], f.v[0].no[1], f.v[0].no[2]] ) - n2 = get_normal_index ( mesh, [f.v[1].no[0], f.v[1].no[1], f.v[1].no[2]] ) - n3 = get_normal_index ( mesh, [f.v[2].no[0], f.v[2].no[1], f.v[2].no[2]] ) - newNormals = [[ n1, n2, n3 ]] - else: - n1 = get_normal_index ( mesh, [f.no[0], f.no[1], f.no[2]] ) - newNormals = [[ n1, n1, n1 ]] - else: - if f.smooth: - n1 = get_normal_index ( mesh, [f.v[0].no[0], f.v[0].no[1], f.v[0].no[2]] ) - n2 = get_normal_index ( mesh, [f.v[1].no[0], f.v[1].no[1], f.v[1].no[2]] ) - n3 = get_normal_index ( mesh, [f.v[2].no[0], f.v[2].no[1], f.v[2].no[2]] ) - n4 = get_normal_index ( mesh, [f.v[3].no[0], f.v[3].no[1], f.v[3].no[2]] ) - newNormals = [ [ n1, n2, n3 ] ] - newNormals.append ( [ n4, n1, n3 ] ) - -# newNormals = [[ n1, n3, n2 ]] -# newNormals.append ( [ n4, n3, n1 ] ) - else: - n1 = get_normal_index ( mesh, [f.no[0], f.no[1], f.no[2]] ) - newNormals = [[ n1, n1, n1 ]] - newNormals.append ( [ n1, n1, n1 ] ) - - return newNormals - - - -################################## -def get_normal_index(mesh,normal): - global NORMALS - - indx=NORMALS.index(normal) - return indx - - -# --------------------------------------------------------------------------- -# do_model_mesh outputs the shape/triangelist wrapper block -# --------------------------------------------------------------------------- -def do_model_mesh(obj): - - global FD - - # output the shell - FD.write(" SI_Mesh MSH-" + removeSpacesFromName(obj.name) + " {\n") - - # todo, add calc normals and calc uv here - # these can be used in both the following sections. - - # next the shape - do_mesh_shape(obj) - - # finally the trangle list - do_mesh_faces(obj) - - # finally close this mesh off - FD.write(" }\n\n") - - - -# --------------------------------------------------------------------------- -# do_model actually outputs a mesh model -# --------------------------------------------------------------------------- -def do_model(obj): - - global FD - - # we only want meshes for now. - if 'Mesh' != obj.type: - return - - # check if the mesh is valid - if validMesh(obj) <> 0: - print "INVALID MESH " + obj.name - return - - - print "Exporting model " + obj.name - - # start model - FD.write(" SI_Model MDL-" + removeSpacesFromName(obj.name) + " {\n") - - # do transform - do_model_transform(obj) - - # do visibility - do_model_visibility(obj) - - # do global material - do_model_material(obj) - - # do the mesh - do_model_mesh(obj) - - # close this model - FD.write(" }\n") - -# -# check for invalid mesh ( faces that have < 3 vertices ) -# - -def validMesh (obj): - mesh = obj.data - for f in mesh.faces: - if len(f.v) < 3: - print "MESH HAS FACES WITH < 3 VERTICES" - return 1 - if len (mesh.faces) == 0: - print "MESH HAS NO FACES" - return 1 - - return 0 - -# --------------------------------------------------------------------------- -# do_models is the process which allows us to write out a bunch of models -# --------------------------------------------------------------------------- -def do_models(): - - global OBJ, MAT, FD - - #create the full scene wrapper object - FD.write("SI_Model MDL-SceneRoot {\n") - FD.write(" SI_Transform SRT-SceneRoot {\n" ) - FD.write(" 1.000000,\n") - FD.write(" 1.000000,\n") - FD.write(" 1.000000,\n") - FD.write(" -90.000000,\n") - FD.write(" 0.000000,\n") - FD.write(" 0.000000,\n") - FD.write(" 0.000000,\n") - FD.write(" 0.000000,\n") - FD.write(" 0.000000,\n") - FD.write(" }\n\n") - - # now process the actual selected meshes themselves - for obj in OBJ: - do_model(obj) - - for obj in OBJ: - do_light(obj) - - for obj in OBJ: - do_camera(obj) - - do_light_ambient () - - # finally close off the model list - FD.write("}\n") - - -# --------------------------------------------------------------------------- -# do_light actually outputs a light model -# --------------------------------------------------------------------------- -def do_light(obj): - - global FD - - # we only want lights for now. - if 'Lamp' != obj.type: - return - - print "Exporting light " + obj.name - - aLampType = 1 - - lmpName=Lamp.Get(obj.getData(name_only=1)) - lmpType=lmpName.getType() - - if lmpType == Lamp.Types.Lamp: - aLampType = 0 - elif lmpType == Lamp.Types.Spot: - aLampType = 0 - elif lmpType == Lamp.Types.Sun: - aLampType = 1 - else: - aLampType = 0 - - # start model - FD.write(" SI_Light " + removeSpacesFromName(obj.name) + " {\n") - - # do type - FD.write(" %d,\n" % aLampType) - - lampName= obj.data - colour = lampName.col - - # do color - FD.write(" %f,\n" % colour[0] ) - FD.write(" %f,\n" % colour[1] ) - FD.write(" %f,\n" % colour[2] ) - - # do position - - FD.write(" %f,\n" % obj.LocX ) - FD.write(" %f,\n" % obj.LocY ) - FD.write(" %f,\n" % obj.LocZ ) - - - # close this model - FD.write(" }\n") - - -# --------------------------------------------------------------------------- -# do_light actually outputs a light model -# --------------------------------------------------------------------------- -def do_camera(obj): - - global FD - - # we only want cameras for now. - if 'Camera' != obj.type: - return - - print "Exporting camera " + obj.name - - - - # start model - FD.write(" SI_Camera " + removeSpacesFromName(obj.name) + " {\n") - - - cameraName=obj.data - - # colour = cameraName.col - - # do position - - FD.write(" %f,\n" % obj.LocX ) - FD.write(" %f,\n" % obj.LocY ) - FD.write(" %f,\n" % obj.LocZ ) - - # looking at - - FD.write(" %f,\n" % 0.0 ) - FD.write(" %f,\n" % 0.0 ) - FD.write(" %f,\n" % 0.0 ) - - # roll - FD.write(" %f,\n" % 0.0 ) - - aLens = cameraName.getLens() - - # field of view - FD.write(" %f,\n" % aLens ) - - # near plane - FD.write(" %f,\n" % 1.0 ) - - # far plane - FD.write(" %f,\n" % 10000000.0 ) - - - # close this model - FD.write(" }\n") - - - -# --------------------------------------------------------------------------- -# write out the ambient light ( for Shockwave 3D converter ) -# --------------------------------------------------------------------------- - -def do_light_ambient(): - if WORLD: ambient = WORLD.getAmb() - else: ambient = 0,0,0 - - FD.write(" SI_Light ambient_sw3d {\n") - - FD.write(" 9,\n") - FD.write(" %f,\n" % ambient[0]) - FD.write(" %f,\n" % ambient[1]) - FD.write(" %f,\n" % ambient[2]) - FD.write(" 0.00000000,\n") - FD.write(" 0.00000000,\n") - FD.write(" 0.00000000,\n") - - FD.write(" }\n") - - - -# --------------------------------------------------------------------------- -# export_xsi is the wrapper function to process the loading of an xsi model. -# --------------------------------------------------------------------------- -def export_xsi(filename): - - global OBJ, MAT, FD, EXPORT_DIR - - # safety check - if filename.find('.xsi', -4) <= 0: - print "XSI not found" - filename += '.xsi' - - - export_dir = bsys.dirname(filename) - if export_dir != EXPORT_DIR: - EXPORT_DIR = export_dir - - # open our output - FD = open(filename, 'w') - - # get the selected objects, otherwise get them all - #OBJ = Blender.Object.GetSelected() - #if not OBJ: - - OBJ = list(Blender.Scene.GetCurrent().objects) #Blender.Object.Get() - - # we need some objects, if none specified stop - if not OBJ: - return - - # if any exist, grab the materials - MAT = Blender.Material.Get() - - # output the header data - do_header() - - # output the materials used by the selected objects. - do_materiallibrary() - - # we punch out the models, that is, the meshes themselves - do_models() - - - # finally close our file - FD.close() - - - -# --------------------------------------------------------------------------- -# Lets trigger it off now -# Blender.Window.FileSelector(export_xsi, 'Export SoftImage XSI') - -fname = bsys.makename(ext=".xsi") -if EXPORT_DIR <> '': - fname = bsys.join(EXPORT_DIR, bsys.basename(fname)) - -Blender.Window.FileSelector(export_xsi, "Export SoftImage XSI", fname) diff --git a/source/blender/blenloader/BLO_readfile.h b/source/blender/blenloader/BLO_readfile.h index 6e2772efea4..52295dc3092 100644 --- a/source/blender/blenloader/BLO_readfile.h +++ b/source/blender/blenloader/BLO_readfile.h @@ -211,7 +211,7 @@ void BLO_library_append_named_part(const struct bContext *C, struct Main *mainl, void BLO_library_append_end(const struct bContext *C, struct Main *mainl, BlendHandle** bh, int idcode, short flag); /* deprecated */ -#if 0 +#if 1 void BLO_script_library_append(BlendHandle **bh, char *dir, char *name, int idcode, short flag, struct Main *mainvar, struct Scene *scene, struct ReportList *reports); #endif diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c index 3e28bc7968f..f83f605bafc 100644 --- a/source/blender/python/intern/bpy_interface.c +++ b/source/blender/python/intern/bpy_interface.c @@ -577,7 +577,7 @@ void BPY_run_ui_scripts(bContext *C, int reload) char *file_extension; char *dirname; char path[FILE_MAX]; - char *dirs[] = {"ui", "io", NULL}; + char *dirs[] = {"scripts/ui", "scripts/io", NULL}; int path_flags[] = {BLI_GETHOME_LOCAL|BLI_GETHOME_SYSTEM, BLI_GETHOME_USER}; /* SYSTEM / NON-SYSTEM */ int a, err, flag_iter; diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index f260002feac..95dbe9ecb37 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -139,8 +139,7 @@ IF(WITH_INSTALL) ADD_CUSTOM_COMMAND( TARGET blender POST_BUILD MAIN_DEPENDENCY blender COMMENT "copying blender scripts..." - COMMAND cp -R ${CMAKE_SOURCE_DIR}/release/ui ${TARGETDIR}/.blender/ - COMMAND cp -R ${CMAKE_SOURCE_DIR}/release/io ${TARGETDIR}/.blender/ + COMMAND cp -R ${CMAKE_SOURCE_DIR}/release/scripts ${TARGETDIR}/.blender/ COMMAND find ${TARGETDIR} -name "*.py?" -prune -exec rm -rf {} "\;" ) @@ -228,8 +227,7 @@ IF(WITH_INSTALL) IF(WITH_PYTHON) ADD_CUSTOM_COMMAND( TARGET blender POST_BUILD MAIN_DEPENDENCY blender - COMMAND cp -Rf ${CMAKE_SOURCE_DIR}/release/ui ${TARGETDIR}/blender.app/Contents/MacOS/.blender/ - COMMAND cp -Rf ${CMAKE_SOURCE_DIR}/release/io ${TARGETDIR}/blender.app/Contents/MacOS/.blender/ + COMMAND cp -Rf ${CMAKE_SOURCE_DIR}/release/scripts ${TARGETDIR}/blender.app/Contents/MacOS/.blender/ COMMAND mkdir ${TARGETDIR}/blender.app/Contents/MacOS/.blender/python/ COMMAND unzip -q ${LIBDIR}/release/python.zip -d ${TARGETDIR}/blender.app/Contents/MacOS/.blender/python/ COMMAND find ${TARGETDIR}/blender.app -name "*.py?" -prune -exec rm -rf {} "\;" @@ -251,15 +249,12 @@ IF(WITH_INSTALL) MAIN_DEPENDENCY blender COMMAND if not exist \"${TARGETDIR}\\.blender\" mkdir \"${TARGETDIR}\\.blender\" COMMAND if not exist \"${TARGETDIR}\\.blender\\locale\" mkdir \"${TARGETDIR}\\.blender\\locale\" - COMMAND if not exist \"${TARGETDIR}\\.blender\\ui\" mkdir \"${TARGETDIR}\\.blender\\ui\" - COMMAND if not exist \"${TARGETDIR}\\.blender\\io\" mkdir \"${TARGETDIR}\\.blender\\io\" + COMMAND if not exist \"${TARGETDIR}\\.blender\\scripts\" mkdir \"${TARGETDIR}\\.blender\\scripts\" COMMAND if not exist \"${TARGETDIR}\\plugins\" mkdir \"${TARGETDIR}\\plugins\" COMMAND copy /Y \"${WIN_SOURCE_DIR}\\bin\\.blender\\.Blanguages\" \"${TARGETDIR}\\.blender\\\" COMMAND copy /Y \"${WIN_SOURCE_DIR}\\bin\\.blender\\.bfont.ttf\" \"${TARGETDIR}\\.blender\\\" COMMAND xcopy /E /Y \"${WIN_SOURCE_DIR}\\bin\\.blender\\locale\\*.*\" \"${TARGETDIR}\\.blender\\locale\" COMMAND xcopy /E /Y \"${WIN_SOURCE_DIR}\\release\\scripts\\*.*\" \"${TARGETDIR}\\.blender\\scripts\" - COMMAND xcopy /E /Y \"${WIN_SOURCE_DIR}\\release\\ui\\*.*\" \"${TARGETDIR}\\.blender\\ui\" - COMMAND xcopy /E /Y \"${WIN_SOURCE_DIR}\\release\\io\\*.*\" \"${TARGETDIR}\\.blender\\io\" COMMAND xcopy /E /Y \"${WIN_SOURCE_DIR}\\release\\plugins\\*.*\" \"${TARGETDIR}\\plugins\" COMMAND copy /Y \"${WIN_SOURCE_DIR}\\release\\text\\*.*\" \"${TARGETDIR}\" COMMAND copy /Y \"${WIN_SOURCE_DIR}\\release\\windows\\extra\\python26.zip\" \"${TARGETDIR}\\\" diff --git a/source/darwin/Makefile b/source/darwin/Makefile index 35842b43eae..1431ab817ff 100644 --- a/source/darwin/Makefile +++ b/source/darwin/Makefile @@ -49,8 +49,6 @@ ifeq ($(APPLICATION), blender) @echo "---> copying .blender/ scripts" @cp -R $(NANBLENDERHOME)/bin/.blender $(DIR)/bin/$(APPLICATION).app/Contents/MacOS @cp -R $(NANBLENDERHOME)/release/scripts $(DIR)/bin/$(APPLICATION).app/Contents/MacOS/.blender/ - @echo "---> copying ui scripts" - @cp -R $(NANBLENDERHOME)/release/ui $(DIR)/bin/$(APPLICATION).app/Contents/MacOS/.blender/ @echo "---> copying python modules" @mkdir $(DIR)/bin/$(APPLICATION).app/Contents/MacOS/.blender/python @unzip -q $(LCGDIR)/release/python.zip -d $(DIR)/bin/$(APPLICATION).app/Contents/MacOS/.blender/python/ |