X-Git-Url: http://git.osdn.jp/view?a=blobdiff_plain;ds=sidebyside;f=swig%2Fblender%2Fbl24.py;h=5d4fceb364093a4bc2408b911dec79e612e320f9;hb=27731d958ce5b65b60bf05cbed0e19707144b030;hp=81220e64e20ec892d559be708c9feb5884aefa2e;hpb=f2259e5b8ba88f08265f8d74be0efc8f62d6dc93;p=meshio%2Fmeshio.git diff --git a/swig/blender/bl24.py b/swig/blender/bl24.py old mode 100644 new mode 100755 index 81220e6..5d4fceb --- a/swig/blender/bl24.py +++ b/swig/blender/bl24.py @@ -1,9 +1,13 @@ # coding: utf-8 import sys import os -import Blender -from Blender import Mathutils +try: + import Blender + from Blender import Mathutils + import bpy +except: + pass # ファイルシステムの文字コード # 改造版との共用のため @@ -13,12 +17,50 @@ if os.path.exists(os.path.dirname(sys.argv[0])+"/utf8"): else: INTERNAL_ENCODING=FS_ENCODING +SCENE=None +def initialize(name, scene): + global SCENE + SCENE=scene + progress_start(name) + # set object mode + mode_edit = Blender.Window.EditMode() + if mode_edit: + Blender.Window.EditMode(0) + +def finalize(): + scene.update(SCENE) + progress_finish() + # restore edit mode + #if mode_edit: + # Blender.Window.EditMode(1) + +def message(msg): + res=Blender.Draw.PupMenu(msg + "%t|OK") + print(res) + +def enterEditMode(): + Blender.Window.EditMode(1) + +def exitEditMode(): + Blender.Window.EditMode(0) + +def createVector(x, y, z): + return Mathutils.Vector(x, y, z) + -############################################################################### -# Writer -############################################################################### class Writer(object): + ''' + io wrapper + ''' + __slots__=[ + 'io', 'encoding', + ] def __init__(self, path, encoding): + ''' + path: file path to open + encoding: text encoding to write + + ''' self.io=open(path, "wb") self.encoding=encoding @@ -32,15 +74,17 @@ class Writer(object): self.io.close() -############################################################################### -# ProgressBar -############################################################################### class ProgressBar(object): + ''' + progress bar wrapper + ''' + __slots__=['base', 'start', 'progress',] def __init__(self, base): - print "#### %s ####" % base + print("#### %s ####" % base) self.base=base self.start=Blender.sys.time() self.set('', 0) + Blender.Window.WaitCursor(1) def advance(self, message, progress): self.progress+=float(progress) @@ -51,7 +95,7 @@ class ProgressBar(object): self._print(message) def _print(self, message): - print message + print(message) message="%s: %s" % (self.base, message) if message.__class__ is unicode: message=message.encode(FS_ENCODING) @@ -61,580 +105,428 @@ class ProgressBar(object): self.progress=1.0 message='finished in %.2f sec' % (Blender.sys.time()-self.start) self.set(message, 1.0) - - -############################################################################### -# for mqo mikoto bone. -############################################################################### -class MikotoBone(object): - __slots__=[ - 'name', - 'iHead', 'iTail', 'iUp', - 'vHead', 'vTail', 'vUp', - 'parent', 'isFloating', - 'children', - ] - def __init__(self, face=None, vertices=None, materials=None): - self.parent=None - self.isFloating=False - self.children=[] - if not face: - self.name='root' - return - - self.name=materials[face.material_index].name.encode('utf-8') - - i0=face.indices[0] - i1=face.indices[1] - i2=face.indices[2] - v0=vertices[i0] - v1=vertices[i1] - v2=vertices[i2] - e01=v1-v0 - e12=v2-v1 - e20=v0-v2 - sqNorm0=e01.getSqNorm() - sqNorm1=e12.getSqNorm() - sqNorm2=e20.getSqNorm() - if sqNorm0>sqNorm1: - if sqNorm1>sqNorm2: - # e01 > e12 > e20 - self.iHead=i2 - self.iTail=i1 - self.iUp=i0 - else: - if sqNorm0>sqNorm2: - # e01 > e20 > e12 - self.iHead=i2 - self.iTail=i0 - self.iUp=i1 - else: - # e20 > e01 > e12 - self.iHead=i1 - self.iTail=i0 - self.iUp=i2 - else: - # 0 < 1 - if sqNorm1 e12 > e01 - self.iHead=i1 - self.iTail=i2 - self.iUp=i0 - else: - if sqNorm0 e20 > e01 - self.iHead=i0 - self.iTail=i2 - self.iUp=i1 - else: - # e12 > e01 > e20 - self.iHead=i0 - self.iTail=i1 - self.iUp=i2 - self.vHead=vertices[self.iHead] - self.vTail=vertices[self.iTail] - self.vUp=vertices[self.iUp] - - if self.name.endswith('[]'): - basename=self.name[0:-2] - # expand LR name - if self.vTail.x>0: - self.name="%s_L" % basename - else: - self.name="%s_R" % basename - - - def setParent(self, parent, floating=False): - if floating: - self.isFloating=True - self.parent=parent - parent.children.append(self) - - def printTree(self, indent=''): - print("%s%s" % (indent, self.name)) - for child in self.children: - child.printTree(indent+' ') - - -def build_armature(armature, mikotoBone, parent=None): - """ - create a armature bone. - """ - bone = Armature.Editbone() - bone.name = mikotoBone.name.encode('utf-8') - armature.bones[bone.name] = bone - - bone.head = Mathutils.Vector(*mikotoBone.vHead.to_a()) - bone.tail = Mathutils.Vector(*mikotoBone.vTail.to_a()) - if parent: - bone.parent=parent - if mikotoBone.isFloating: - pass - else: - bone.options=[Armature.CONNECTED] - - for child in mikotoBone.children: - build_armature(armature, child, bone) - - -def create_armature(scene, mqo): - """ - create armature - """ - boneObject=None - for o in mqo.objects: - if o.name.startswith('bone'): - boneObject=o - break - if not boneObject: - return - - tailMap={} - for f in boneObject.faces: - if f.index_count!=3: - print("invalid index_count: %d" % f.index_count) - continue - b=MikotoBone(f, boneObject.vertices, mqo.materials) - tailMap[b.iTail]=b - - #################### - # build mikoto bone tree - #################### - mikotoRoot=MikotoBone() - - for b in tailMap.values(): - # each bone has unique parent or is root bone. - if b.iHead in tailMap: - b.setParent(tailMap[b.iHead]) - else: - isFloating=False - for e in boneObject.edges: - if b.iHead==e.indices[0]: - # floating bone - if e.indices[1] in tailMap: - b.setParent(tailMap[e.indices[1]], True) - isFloating=True - break - elif b.iHead==e.indices[1]: - # floating bone - if e.indices[0] in tailMap: - b.setParent(tailMap[e.indices[0]], True) - isFloating=True - break - if isFloating: - continue - - # no parent bone - b.setParent(mikotoRoot, True) - - if len(mikotoRoot.children)==0: - print("no root bone") - return - - if len(mikotoRoot.children)==1: - # single root - mikotoRoot=mikotoRoot.children[0] - mikotoRoot.parent=None - else: - mikotoRoot.vHead=Vector3(0, 10, 0) - mikotoRoot.vTail=Vector3(0, 0, 0) - - #################### - # create armature - #################### - armature = Armature.New() - # link to object - armature_object = scene.objects.new(armature) - # create action - act = Armature.NLA.NewAction() - act.setActive(armature_object) - # set XRAY - armature_object.drawMode |= Object.DrawModes.XRAY - # armature settings - armature.drawType = Armature.OCTAHEDRON - armature.envelopes = False - armature.vertexGroups = True - armature.mirrorEdit = True - armature.drawNames=True - - # edit bones - armature.makeEditable() - build_armature(armature, mikotoRoot) - armature.update() - - return armature_object - - -class TrianglePlane(object): - """ - mikoto方式ボーンのアンカーウェイト計算用。 - (不完全) - """ - __slots__=['normal', - 'v0', 'v1', 'v2', - ] - def __init__(self, v0, v1, v2): - self.v0=v0 - self.v1=v1 - self.v2=v2 - - def isInsideXY(self, p): - v0=Vector2(self.v0.x, self.v0.y) - v1=Vector2(self.v1.x, self.v1.y) - v2=Vector2(self.v2.x, self.v2.y) - e01=v1-v0 - e12=v2-v1 - e20=v0-v2 - c0=Vector2.cross(e01, p-v0) - c1=Vector2.cross(e12, p-v1) - c2=Vector2.cross(e20, p-v2) - if c0>=0 and c1>=0 and c2>=0: - return True - if c0<=0 and c1<=0 and c2<=0: - return True - - def isInsideYZ(self, p): - v0=Vector2(self.v0.y, self.v0.z) - v1=Vector2(self.v1.y, self.v1.z) - v2=Vector2(self.v2.y, self.v2.z) - e01=v1-v0 - e12=v2-v1 - e20=v0-v2 - c0=Vector2.cross(e01, p-v0) - c1=Vector2.cross(e12, p-v1) - c2=Vector2.cross(e20, p-v2) - if c0>=0 and c1>=0 and c2>=0: - return True - if c0<=0 and c1<=0 and c2<=0: - return True - - def isInsideZX(self, p): - v0=Vector2(self.v0.z, self.v0.x) - v1=Vector2(self.v1.z, self.v1.x) - v2=Vector2(self.v2.z, self.v2.x) - e01=v1-v0 - e12=v2-v1 - e20=v0-v2 - c0=Vector2.cross(e01, p-v0) - c1=Vector2.cross(e12, p-v1) - c2=Vector2.cross(e20, p-v2) - if c0>=0 and c1>=0 and c2>=0: - return True - if c0<=0 and c1<=0 and c2<=0: - return True - - -class MikotoAnchor(object): - """ - mikoto方式スケルトンのアンカー。 - """ - __slots__=[ - "triangles", "bbox", - ] - def __init__(self): - self.triangles=[] - self.bbox=None - - def push(self, face, vertices): - if face.index_count==3: - self.triangles.append(TrianglePlane( - vertices[face.indices[0]], - vertices[face.indices[1]], - vertices[face.indices[2]] - )) - elif face.index_count==4: - self.triangles.append(TrianglePlane( - vertices[face.indices[0]], - vertices[face.indices[1]], - vertices[face.indices[2]] - )) - self.triangles.append(TrianglePlane( - vertices[face.indices[2]], - vertices[face.indices[3]], - vertices[face.indices[0]] - )) - # bounding box - if not self.bbox: - self.bbox=BoundingBox(vertices[face.indices[0]]) - for i in face.indices: - self.bbox.expand(vertices[i]) - - - def calcWeight(self, v): - if not self.bbox.isInside(v): - return 0 - - if self.anyXY(v.x, v.y) and self.anyYZ(v.y, v.z) and self.anyZX(v.z, v.x): - return 1.0 - else: - return 0 - - def anyXY(self, x, y): - for t in self.triangles: - if t.isInsideXY(Vector2(x, y)): - return True - return False - - def anyYZ(self, y, z): - for t in self.triangles: - if t.isInsideYZ(Vector2(y, z)): - return True - return False - - def anyZX(self, z, x): - for t in self.triangles: - if t.isInsideZX(Vector2(z, x)): - return True - return False - - -def create_bone_weight(scene, mqo, armature_object, objects): - """ - create mikoto bone weight. - """ - anchorMap={} - # setup mikoto anchors - for o in mqo.objects: - if o.name.startswith("anchor"): - for f in o.faces: - name=mqo.materials[f.material_index].name - if name.endswith('[]'): - basename=name[0:-2] - v=o.vertices[f.indices[0]] - if(v.x>0): - # L - name_L=basename+'_L' - if not name_L in anchorMap: - anchorMap[name_L]=MikotoAnchor() - anchorMap[name_L].push(f, o.vertices) - elif(v.x<0): - # R - name_R=basename+'_R' - if not name_R in anchorMap: - anchorMap[name_R]=MikotoAnchor() - anchorMap[name_R].push(f, o.vertices) - else: - print("no side", v) - else: - if not name in anchorMap: - anchorMap[name]=MikotoAnchor() - anchorMap[name].push(f, o.vertices) - - for o in objects: - # add armature modifier - mod=o.modifiers.append(Modifier.Types.ARMATURE) - mod[Modifier.Settings.OBJECT] = armature_object - mod[Modifier.Settings.ENVELOPES] = False - o.makeDisplayList() - # create vertex group + Blender.Window.WaitCursor(0) + Blender.Redraw() + +def progress_start(base): + global progressBar + progressBar=ProgressBar(base) + +def progress_finish(): + global progressBar + progressBar.finish() + +def progress_print(message, progress=0.05): + global progressBar + progressBar.advance(message, progress) + +def progress_set(message, progress): + global progressBar + progressBar.set(message, progress) + + +class scene: + @staticmethod + def update(scene): + scene.update(0) + + +class object: + @staticmethod + def createEmpty(name): + global SCENE + empty=SCENE.objects.new("Empty") + empty.setName(name) + return empty + + @staticmethod + def makeParent(parent, child): + parent.makeParent([child]) + + @staticmethod + def duplicate(o): + new_mesh, new_object=mesh.create(o.name.decode(INTERNAL_ENCODING)) + # not apply modifiers + new_mesh.getFromObject(o.name, 1) + # apply matrix + #o.setMatrix(o.matrixWorld) + return new_mesh, new_object + + @staticmethod + def delete(o): + global SCENE + SCENE.objects.unlink(o) + + @staticmethod + def getData(o): + return o.getData(mesh=True) + + @staticmethod + def select(o): + o.select(True) + + @staticmethod + def activate(o): + global SCENE + o.select(True ) + SCENE.objects.active=o + + @staticmethod + def getActive(): + global SCENE + return SCENE.objects.active + + @staticmethod + def deselectAll(): + for o in bpy.data.scenes.active.objects: + o.select(False) + + @staticmethod + def setLayerMask(o, layers): + mask=0 + for i, enable in enumerate(layers): + if enable!=0: + mask+=(1<0: - mesh.assignVertsToGroup( - name, [i], weight, Mesh.AssignModes.ADD) - hasWeight=True - if not hasWeight: - # debug orphan vertex - print('orphan', mvert) - mesh.update() - -############################################################################### -def createEmptyObject(scene, name): - empty=scene.objects.new("Empty") - empty.setName(name) - return empty - - -def createMqoMaterial(m): - material = Blender.Material.New(m.getName().encode(INTERNAL_ENCODING)) - material.mode |= Blender.Material.Modes.SHADELESS - material.rgbCol = [m.color.r, m.color.g, m.color.b] - material.alpha = m.color.a - material.amb = m.ambient - material.spec = m.specular - material.hard = int(255 * m.power) - return material - - -def createTexture(path): - image = Blender.Image.Load(path.encode(INTERNAL_ENCODING)) - texture = Blender.Texture.New(path.encode(INTERNAL_ENCODING)) - texture.type = Blender.Texture.Types.IMAGE - texture.image = image - return texture, image - - -def materialAddTexture(material, texture): - material.mode = material.mode | Blender.Material.Modes.TEXFACE - material.setTexture(0, texture, Blender.Texture.TexCo.UV) - - -def createMesh(scene, name): - mesh = Blender.Mesh.New() - mesh_object=scene.objects.new(mesh, name.encode(INTERNAL_ENCODING)) - return mesh, mesh_object - - -def objectMakeParent(parent, child): - parent.makeParent([child]) - - -def meshAddMqoGeometry(mesh, o, materials, imageMap, scale): - # add vertices - mesh.verts.extend(Mathutils.Vector(0, 0, 0)) # dummy - mesh.verts.extend([(v.x, -v.z, v.y) for v in o.vertices]) - # add faces - mesh_faces=[] - for face in o.faces: - face_indices=[] - for i in xrange(face.index_count): - face_indices.append(face.getIndex(i)+1) - mesh_faces.append(face_indices) - #new_faces=mesh.faces.extend([face.indices for face in o.faces], - new_faces=mesh.faces.extend(mesh_faces, - #ignoreDups=True, - indexList=True) - mesh.update() - - # gather used materials - materialMap = {} - if new_faces: - for i in new_faces: - if type(i) is int: - materialMap[o.faces[i].material_index]=True - - # blender limits 16 materials per mesh - # separate mesh ? - for i, material_index in enumerate(materialMap.keys()): - if i>=16: - print("over 16 materials!") - break - mesh.materials+=[materials[material_index]] - materialMap[material_index]=i - - # set face params - for i, f in enumerate(o.faces): - if not type(new_faces[i]) is int: - continue - - face=mesh.faces[new_faces[i]] - - uv_array=[] - for i in xrange(f.index_count): - uv_array.append(Blender.Mathutils.Vector( - f.getUV(i).x, - 1.0-f.getUV(i).y) - ) - try: - face.uv=uv_array - except Exception as msg: - #print msg - #print face.index, uv_array - pass - - if f.material_index in materialMap: - face.mat = materialMap[f.material_index] - - face.smooth = 1 - - # rmeove dummy 0 vertex - mesh.verts.delete(0) - - mesh.mode |= Blender.Mesh.Modes.AUTOSMOOTH - mesh.maxSmoothAngle = int(o.smoothing) - mesh.smooth() - mesh.calcNormals() - mesh.flipNormals() - mesh.update() - - # mirror modifier - if o.mirror: - mod=mesh_object.modifiers.append(Blender.Modifier.Types.MIRROR) - -def getTexture(m, dirname): - tex="" - aplane="" - # texture - for texture in m.getTextures(): - if texture and texture.tex and texture.tex.getImage(): - image=texture.tex.getImage() - if not image: - continue - imagePath=Blender.sys.expandpath(image.getFilename()) - if len(dirname)>0 and imagePath.startswith(dirname): - # 相対パスに変換する - imagePath=imagePath[len(dirname)+1:len(imagePath)] - if texture.mtCol>0: - tex=" tex(\"%s\")" % imagePath - elif texture.mtAlpha>0: - aplane=" aplane(\"%s\")" % imagePath - return tex, aplane - -def objectDuplicate(scene, obj): - mesh, dumy=createMesh(scene, obj.name.decode(INTERNAL_ENCODING)) - # not apply modifiers - mesh.getFromObject(obj.name, 1) - # apply matrix - dumy.setMatrix(obj.matrixWorld) - return mesh, dumy - -def faceVertexCount(face): - return len(face.v) - -def faceVertices(face): - # flip - return [v.index for v in reversed(face.v)] - -def meshHasUV(mesh): - return mesh.faceUV - -def faceHasUV(mesh, i, face): - return len(face.uv)>0 - -def faceGetUV(mesh, i, face, count): - # flip - return reversed(face.uv) - -def materialToMqo(m): - return "\"%s\" shader(3) col(%f %f %f %f)" % ( - m.name, m.rgbCol[0], m.rgbCol[1], m.rgbCol[2], m.alpha) - -def faceMaterialIndex(face): - return face.mat - -def objectGetData(o): - return o.getData(mesh=True) - -def objectAddArmatureModifier(o, armature_object): - mod=o.modifiers.append(Blender.Modifier.Types.ARMATURE) - mod[Blender.Modifier.Settings.OBJECT] = armature_object - mod[Blender.Modifier.Settings.ENVELOPES] = False - -def objectSelect(o): - o.select(True) - -def objectGetPose(o): - return o.getPose() - -def poseBoneLimit(n, b): - if n.endswith("_t"): - return - if n.startswith("knee_"): - b.lockYRot=True - b.lockZRot=True - b.limitX=True - b.limitMin=[0, 0, 0] - b.limitMax=[180, 0, 0] - elif n.startswith("ankle_"): - b.lockYRot=True + mesh.insertKey() + block=mesh.key.blocks[-1] + block.name=name.encode(INTERNAL_ENCODING) + return block + + @staticmethod + def hasShapeKey(o): + return o.getData(mesh=True).key + + @staticmethod + def pinShape(o, enable): + o.pinShape=enable + + @staticmethod + def setActivateShapeKey(o, index): + o.activeShape=index + + @staticmethod + def getPose(o): + return o.getPose() + + @staticmethod + def addVertexGroup(o, name): + o.getData(mesh=True).addVertGroup(name) + + @staticmethod + def assignVertexGroup(o, name, index, weight): + o.getData(mesh=True).assignVertsToGroup(name, + [index], weight, Blender.Mesh.AssignModes.ADD) + + @staticmethod + def getVertexGroupNames(o): + return o.getData(mesh=True).getVertGroupNames() + + @staticmethod + def getVertexGroup(o, name): + indices=[] + for index in o.getData(mesh=True).getVertsFromGroup(name): + indices.append(index) + return indices + + +class modifier: + @staticmethod + def addMirror(mesh_object): + return mesh_object.modifiers.append(Blender.Modifier.Types.MIRROR) + + @staticmethod + def addArmature(mesh_object, armature_object): + mod=mesh_object.modifiers.append(Blender.Modifier.Types.ARMATURE) + mod[Blender.Modifier.Settings.OBJECT] = armature_object + mod[Blender.Modifier.Settings.ENVELOPES] = False + + @staticmethod + def hasType(mesh_object, type_name): + for mod in mesh_object.modifiers: + if mod.name.upper()==type_name.upper(): + return True + + @staticmethod + def isType(m, type_name): + return m.name.upper()==type_name.upper() + + @staticmethod + def getArmatureObject(m): + return m[Blender.Modifier.Settings.OBJECT] + + +class shapekey: + @staticmethod + def assign(b, index, pos): + b.data[index]=pos + + @staticmethod + def getByIndex(b, index): + return b.data[index] + + @staticmethod + def get(b): + return b.data + + +class texture: + @staticmethod + def create(path): + image = Blender.Image.Load(path.encode(INTERNAL_ENCODING)) + texture = Blender.Texture.New(path.encode(INTERNAL_ENCODING)) + texture.type = Blender.Texture.Types.IMAGE + texture.image = image + texture.imageFlags|=Blender.Texture.ImageFlags.USEALPHA + return texture, image + + +class material: + @staticmethod + def create(name): + m = Blender.Material.New(name) + return m + + @staticmethod + def get(material_name): + return Blender.Material.Get(material_name) + + @staticmethod + def addTexture(material, texture): + material.mode = material.mode | Blender.Material.Modes.TEXFACE + material.setTexture(0, texture, Blender.Texture.TexCo.UV) + + @staticmethod + def hasTexture(material): + return len(material.getTextures())>0 + + @staticmethod + def eachTexturePath(m, dirname): + for texture in m.getTextures(): + if texture and texture.tex and texture.tex.getImage(): + image=texture.tex.getImage() + if not image: + continue + yield image.getFilename() + + +class mesh: + @staticmethod + def create(name): + global SCENE + m=Blender.Mesh.New() + o=SCENE.objects.new(m, name.encode(INTERNAL_ENCODING)) + return m, o + + @staticmethod + def addGeometry(m, vertices, faces): + m.verts.extend(vertices) + new_faces=m.faces.extend(faces, + #ignoreDups=True, + indexList=True) + m.update() + + @staticmethod + def hasUV(m): + return m.faceUV + + @staticmethod + def useVertexUV(m): + m.vertexUV = 1 + + @staticmethod + def addUV(m): + m.addUVLayer('NewUV') + + @staticmethod + def hasFaceUV(m, i, face): + return len(face.uv)>0 + + @staticmethod + def getFaceUV(m, i, face, count=3): + return face.uv + + @staticmethod + def setFaceUV(m, i, face, uv_array, image): + face.uv=[Mathutils.Vector(uv[0], uv[1]) for uv in uv_array] + if image: + face.image=image + + @staticmethod + def vertsDelete(m, remove_vertices): + m.verts.delete(remove_vertices) + + @staticmethod + def setSmooth(m, smoothing): + m.mode |= Blender.Mesh.Modes.AUTOSMOOTH + m.degr=int(smoothing) + #m.smooth() + + @staticmethod + def recalcNormals(mesh_object): + m=mesh_object.getData(mesh=True) + m.calcNormals() + + @staticmethod + def flipNormals(m): + m.flipNormals() + + @staticmethod + def addMaterial(m, material): + m.materials+=[material] + + +class vertex: + @staticmethod + def setNormal(mvert, normal): + mvert.no=Mathutils.Vector(*normal) + + @staticmethod + def setUv(mvert, uv): + mvert.uvco=uv + + +class face: + @staticmethod + def getVertexCount(face): + return len(face.v) + + @staticmethod + def getVertices(face): + return [v.index for v in face.v] + + @staticmethod + def getIndices(face): + return [face.verts[0].index, face.verts[1].index, face.verts[2].index] + + @staticmethod + def setMaterial(face, material_index): + face.mat=material_index + + @staticmethod + def getMaterialIndex(face): + return face.mat + + @staticmethod + def setNormal(face, normal): + face.no=normal + + @staticmethod + def getNormal(face): + return face.no + + @staticmethod + def setSmooth(face, isSmooth): + face.smooth=1 if isSmooth else 0 + + +class armature: + @staticmethod + def create(): + global SCENE + armature = Blender.Armature.New() + armature_object = SCENE.objects.new(armature) + + # set XRAY + armature_object.drawMode = ( + armature_object.drawMode | Blender.Object.DrawModes.XRAY) + # armature settings + armature.drawType = Blender.Armature.OCTAHEDRON + armature.drawNames=True + armature.envelopes = False + armature.vertexGroups = True + armature.mirrorEdit = True + + return armature, armature_object + + @staticmethod + def makeEditable(armature_object): + # create armature + armature_object.getData().makeEditable() + + @staticmethod + def createIkConstraint(armature_object, p_bone, effector_name, ik): + cSetting = Blender.Constraint.Settings + # IK solver + constraint = p_bone.constraints.append(Blender.Constraint.Type.IKSOLVER) + constraint[cSetting.CHAINLEN]=len(ik.children) + constraint[cSetting.TARGET]=armature_object + constraint[cSetting.USETIP]=False + constraint[cSetting.BONE]=effector_name + # not used. place folder when export. + constraint[cSetting.ROTWEIGHT]=ik.weight + constraint[cSetting.ITERATIONS]=ik.iterations * 10 + return constraint + + @staticmethod + def createBone(armature_object, name): + bone=Blender.Armature.Editbone() + bone.name=name.encode(INTERNAL_ENCODING) + armature_object.bones[name]=bone + return bone + + @staticmethod + def update(armature): + armature.update() + + +class bone: + @staticmethod + def setConnected(bone): + bone.options+=[Blender.Armature.CONNECTED] + + @staticmethod + def isConnected(b): + return Blender.Armature.CONNECTED in b.options + + @staticmethod + def setLayerMask(bone, layers): + mask=0 + for i, enable in enumerate(layers): + if enable!=0: + mask+=(1<