Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWillian Padovani Germano <wpgermano@gmail.com>2005-05-17 11:17:52 +0400
committerWillian Padovani Germano <wpgermano@gmail.com>2005-05-17 11:17:52 +0400
commit859959b49c8122b1e37027cf5009fecd23f5d8c8 (patch)
tree0dbe86f455743795604d88b3b9a351d0d6d1d98e /release
parent7f4ff24462217328a6d0d0b193621949ed5e085a (diff)
BPython:
- fixing bug reported by Paolo Colombo: space handler slinks set for a 3d view were not set when the area got maximized; - Blender.Object: added object.isSB() method to know if an object is a soft body (has ob->soft != NULL). Used in fixfromarmature.py. Scripts: - updates: batch_name_edit (Campbell), fixfromarmature (JMS); - additions: X3D exporter by Bart; Envelope Suite by Jonas Petersen; BVH 2 Armature by Jean-Baptiste Perin; Camera Changer by Regis Montoya (3R); Interactive Console by Campbell (ideasman). - tiny updates in other scripts.
Diffstat (limited to 'release')
-rw-r--r--release/scripts/armature_symetry.py197
-rw-r--r--release/scripts/batch_name_edit.py134
-rw-r--r--release/scripts/bpymodules/BPyNMesh.py48
-rw-r--r--release/scripts/bvh2arm.py693
-rw-r--r--release/scripts/bvh_import.py5
-rw-r--r--release/scripts/camera_changer.py95
-rw-r--r--release/scripts/console.py517
-rw-r--r--release/scripts/envelope_assignment.py234
-rw-r--r--release/scripts/envelope_symmetry.py176
-rw-r--r--release/scripts/fixfromarmature.py74
-rw-r--r--release/scripts/knife.py2
-rw-r--r--release/scripts/save_theme.py6
-rw-r--r--release/scripts/vrml97_export.py2
-rw-r--r--release/scripts/x3d_export.py1045
14 files changed, 3128 insertions, 100 deletions
diff --git a/release/scripts/armature_symetry.py b/release/scripts/armature_symetry.py
new file mode 100644
index 00000000000..be4f109ccce
--- /dev/null
+++ b/release/scripts/armature_symetry.py
@@ -0,0 +1,197 @@
+#!BPY
+
+"""
+Name: 'Armature Symmetry'
+Blender: 234
+Group: 'Animation'
+Tooltip: 'Make an armature symetrical'
+"""
+
+__author__ = "Jonas Petersen"
+__url__ = ("blender", "elysiun", "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 armatures.
+
+With default configuration it will:<br>
+ - Look for bones that have the reference suffix (".L") and
+adjust/create the according opposite bone (suffix ".R");<br>
+ - Center align all bones that _don't_ have the suffix ".X".
+
+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.
+"""
+
+# --------------------------------------------------------------------------
+# "Armature Symmetry" by Jonas Petersen
+# Version 0.9 - 10th November 2004 - first public release
+# --------------------------------------------------------------------------
+#
+# A script for creating perfectly symmetrical armatures.
+#
+# It is available in Object Mode via the menu item:
+#
+# Object -> Scripts -> Armature Symmetry
+#
+# With default configuration it will:
+#
+# - Look for bones that have the reference suffix (".L") and
+# adjust/create the according opposite bone (suffix ".R").
+#
+# - Center align all bones that _don't_ have the suffix ".X"
+#
+# 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.
+
+# CENTER_SUFFIX is the suffix for bones that should (or shouldn't) get
+# center aligned. The default is '.X'.
+CENTER_SUFFIX = '.X'
+
+# CENTER_SUFFIX_MODE:
+#
+# 'include' only bones with the CENTER_SUFFIX appended
+# get center aligned.
+#
+# 'exclude' (default)
+# all bones except those with the CENTER_SUFFIX
+# appended get center aligned.
+#
+#
+# 'off' bones will not get center aligned at all.
+#
+CENTER_SUFFIX_MODE = 'exclude'
+
+# The suffix for the reference and opposite side of the
+# armature. Bone positions of the opposite side will be overwritten by
+# the mirrored values of the reference side.
+# The default is REF_SUFFIX = '.L' and OPP_SUFFIX = '.R'.
+REF_SUFFIX = '.L'
+OPP_SUFFIX = '.R'
+
+# 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
+
+# --------------------------------------------------------------------------
+# END OF CONFIGURATION
+# --------------------------------------------------------------------------
+
+import Blender
+
+def splitName(bone):
+ name = bone.getName()
+ base = name[0:len(name)-ref_suffix_len]
+ rsuff = name[-ref_suffix_len:len(name)]
+ csuff = name[-center_suffix_len:len(name)]
+ return name, base, rsuff, csuff
+
+ref_suffix_len = len(REF_SUFFIX);
+center_suffix_len = len(CENTER_SUFFIX);
+armature_selected = False
+
+obj_list = Blender.Object.GetSelected()
+for obj in obj_list:
+ if obj.getType() == "Armature":
+ armature_selected = True
+ arm = obj.getData()
+ bones = arm.getBones()
+ bonehash = {}
+
+ for bone in bones:
+ bonehash[bone.getName()] = bone
+
+ for bone in bones:
+ name, base, rsuff, csuff = splitName(bone)
+
+ # reference bone?
+ if (rsuff == REF_SUFFIX):
+ oppname = base + OPP_SUFFIX
+
+ # create opposite bone if necessary
+ if not bonehash.has_key(oppname):
+ bonehash[oppname]=Blender.Armature.Bone.New(oppname)
+ parent = bone.getParent()
+ if parent:
+ pname, pbase, prsuff, pcsuff = splitName(parent)
+ if prsuff == REF_SUFFIX:
+ poppname = pbase + OPP_SUFFIX
+ if bonehash.has_key(poppname):
+ bonehash[oppname].setParent(bonehash[poppname])
+ else:
+ bonehash[oppname].setParent(parent)
+ arm.addBone(bonehash[oppname])
+
+ # mirror bone coords
+
+ tail = bone.getTail()
+ tail[MIRROR_AXIS] *= -1;
+ bonehash[oppname].setTail(tail)
+
+ head = bone.getHead()
+ head[MIRROR_AXIS] *= -1;
+ bonehash[oppname].setHead(head)
+
+ roll = -bone.getRoll()
+ bonehash[oppname].setRoll(roll)
+
+ # Write access to ik flag not (yet?) supported in Blender (2.34)
+ #if bone.hasParent():
+ # bonehash[oppname].setIK(not bone.getIK())
+
+ # center bone?
+ elif (rsuff != OPP_SUFFIX) and \
+ (CENTER_SUFFIX_MODE != 'off') and \
+ ((CENTER_SUFFIX_MODE == 'exclude' and csuff != CENTER_SUFFIX) or \
+ (CENTER_SUFFIX_MODE == 'include' and csuff == CENTER_SUFFIX)):
+
+ # center bone coords
+
+ tail = bone.getTail()
+ tail[MIRROR_AXIS] = 0.0;
+ bone.setTail(tail)
+
+ head = bone.getHead()
+ head[MIRROR_AXIS] = 0.0;
+ bone.setHead(head)
+
+ # Setting set roll in python rotates all child bones.
+ # Not so if set via the Transform Properties in Blender.
+ # Bug?
+ bone.setRoll(0.0)
+
+if not armature_selected:
+ Blender.Draw.PupMenu("Armature Symmetry%t|Please select an Armature object!")
diff --git a/release/scripts/batch_name_edit.py b/release/scripts/batch_name_edit.py
index 175d33cb973..75d2294aa68 100644
--- a/release/scripts/batch_name_edit.py
+++ b/release/scripts/batch_name_edit.py
@@ -50,74 +50,82 @@ menu of the 3d View.
from Blender import *
-def new():
- newname = Draw.PupStrInput('Name: ', '', 32)
- if newname == None: return
- for ob in Object.GetSelected():
- ob.name = newname
-
-def replace():
- replace = Draw.PupStrInput('Replace: ', '', 32)
- if replace == None: return
-
- with = Draw.PupStrInput('With: ', '', 32)
- if with == None: return
-
- for ob in Object.GetSelected():
+def main():
+ def new():
+ newname = Draw.PupStrInput('Name: ', '', 32)
+ if newname == None: return
+ Window.WaitCursor(1)
+ for ob in Object.GetSelected():
+ ob.name = newname
- if replace in ob.name:
- chIdx = ob.name.index(replace)
+ def replace():
+ replace = Draw.PupStrInput('Replace: ', '', 32)
+ if replace == None: return
+ with = Draw.PupStrInput('With: ', '', 32)
+ if with == None: return
+ Window.WaitCursor(1)
+ for ob in Object.GetSelected():
+ ob.name = ob.name.replace(replace, with)
- # Remove the offending word and replace it with - 'with'
- ob.name = ob.name[ :chIdx] + with + ob.name[chIdx + len(replace):]
+ # Use pythons replace, its better.
+ '''
+ if replace in ob.name:
+ chIdx = ob.name.index(replace)
+
+ # Remove the offending word and replace it with - 'with'
+ ob.name = ob.name[ :chIdx] + with + ob.name[chIdx + len(replace):]
+ '''
-
-def prefix():
- prefix = Draw.PupStrInput('prefix: ', '', 32)
- if prefix == None: return
- for ob in Object.GetSelected():
- ob.name = prefix + ob.name
-
-
-def suffix():
- suffix = Draw.PupStrInput('Suffix: ', '', 32)
- if suffix == None: return
+ def prefix():
+ prefix = Draw.PupStrInput('prefix: ', '', 32)
+
+ if prefix == None: return
+ Window.WaitCursor(1)
+ for ob in Object.GetSelected():
+ ob.name = prefix + ob.name
- for ob in Object.GetSelected():
- ob.name = ob.name + suffix
-
-def truncate_start():
- truncate = Draw.PupIntInput('Truncate Start: ', 0, 0, 31)
- if truncate != None:
+
+ def suffix():
+ suffix = Draw.PupStrInput('Suffix: ', '', 32)
+ if suffix == None: return
+ Window.WaitCursor(1)
for ob in Object.GetSelected():
- ob.name = ob.name[truncate: ]
-
-def truncate_end():
- truncate = Draw.PupIntInput('Truncate End: ', 0, 0, 31)
- if truncate == None: return
+ ob.name = ob.name + suffix
- for ob in Object.GetSelected():
- ob.name = ob.name[ :-truncate]
-
-
-
-
-name = "Selected Object Names%t|New Name|Replace Text|Add Prefix|Add Suffix|Truncate Start|Truncate End"
-result = Draw.PupMenu(name)
-
-if result == -1:
- pass
-elif result == 1:
- new()
-elif result == 2:
- replace()
-elif result == 3:
- prefix()
-elif result == 4:
- suffix()
-elif result == 5:
- truncate_start()
-elif result == 6:
- truncate_end()
+ def truncate_start():
+ truncate = Draw.PupIntInput('Truncate Start: ', 0, 0, 31)
+ if truncate != None:
+ Window.WaitCursor(1)
+ for ob in Object.GetSelected():
+ ob.name = ob.name[truncate: ]
+
+ def truncate_end():
+ truncate = Draw.PupIntInput('Truncate End: ', 0, 0, 31)
+ if truncate == None: return
+ Window.WaitCursor(1)
+ for ob in Object.GetSelected():
+ ob.name = ob.name[ :-truncate]
+
+
+ name = "Selected Object Names%t|New Name|Replace Text|Add Prefix|Add Suffix|Truncate Start|Truncate End"
+ result = Draw.PupMenu(name)
+
+ if result == -1:
+ pass
+ elif result == 1:
+ new()
+ elif result == 2:
+ replace()
+ elif result == 3:
+ prefix()
+ elif result == 4:
+ suffix()
+ elif result == 5:
+ truncate_start()
+ elif result == 6:
+ truncate_end()
+
+ Window.WaitCursor(0)
+main()
diff --git a/release/scripts/bpymodules/BPyNMesh.py b/release/scripts/bpymodules/BPyNMesh.py
new file mode 100644
index 00000000000..043d8514db9
--- /dev/null
+++ b/release/scripts/bpymodules/BPyNMesh.py
@@ -0,0 +1,48 @@
+# $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/bvh2arm.py b/release/scripts/bvh2arm.py
new file mode 100644
index 00000000000..c8cac3d90cf
--- /dev/null
+++ b/release/scripts/bvh2arm.py
@@ -0,0 +1,693 @@
+#!BPY
+"""
+Name: 'BVH Empties to Armature'
+Blender: 234
+Group: 'Animation'
+Tooltip: 'Create Armature from Empties created by the BVH import script'
+"""
+__author__ = " Jean-Baptiste PERIN (jb_perin(at)yahoo.fr)"
+__url__ = ("blender", "elysiun",
+"BVH 2 ARMATURE, http://www.zoo-logique.org/3D.Blender/index.php3?zoo=dld&rep=zip ",
+"Communicate problems and errors, http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender")
+
+__version__ = "2.0"
+
+__bpydoc__ = """ BVH2ARM.py v2.0
+
+Script for generating armature from BVH empties.
+
+This script generates an armature and makes bones
+follow empties created by the BVH import script.
+
+Usage:<br>
+ - Import a bvh in Blender (File->Import->BVH);<br>
+ - Launch this script (Alt-P);<br>
+ - Set up variables:<br>
+ "hipbonename": the name of the main bone;<br>
+ "startframe": the first frame of your anim;<br>
+ "endframe": the last frame of your anim;<br>
+ "decimation": the frequency (in number of frames) to which the armature is updated;<br>
+ "scale": to size the created armature.
+ - Press "Create Armature".
+"""
+
+#----------------------------------------------
+# (c) Jean-Baptiste PERIN octobre 2004, released under Blender Artistic Licence
+# for the Blender 2.34-2.36 Python Scripts Bundle.
+#----------------------------------------------
+
+
+
+import Blender
+from Blender import Mathutils
+import math
+
+dicEmptiesRestMatrix= {}
+dicEmptiesInvRestMatrix= {}
+dicBoneRestMatrix= {}
+dicBone={}
+dicEmptyChild={}
+dicBoneRestInvEmpRest={}
+dicEmpRestInvBoneRest={}
+restFrame = 1
+
+########################################################################
+#
+# UTILITY FUNCTIONS FOR HANDLING BONES AND EMPTIES
+#
+########################################################################
+
+def names(ob): return ob.getName()
+
+#########
+# Cette fonction renvoie la liste des empties attaches a root
+# in :
+# out : emp_list (List of Object) la liste des objets de type "Empty"
+#########
+def getTree(emp_list, root):
+ empties=getAllEmpties()
+ chlds = getChildren(root, empties)
+ dicEmptyChild[root.getName()]=chlds
+ for ch in chlds:
+ emp_list.append(ch)
+ getTree(emp_list,ch)
+
+#########
+# Cette fonction renvoie la liste des empties attaches a root
+# in :
+# out : emp_list (List of Object) la liste des objets de type "Empty"
+#########
+def getEmpties():
+ global hipbonename
+ emp_list = []
+ root = Blender.Object.Get(hipbonename)
+ emp_list.append(root)
+ getTree(emp_list, root)
+ return emp_list
+
+#########
+# Cette fonction renvoie la liste des empties
+# in :
+# out : emp_list (List of Object) la liste des objets de type "Empty"
+#########
+def getAllEmpties():
+ emp_list = []
+ objs = Blender.Object.Get()
+ for o in objs:
+ if o.getType()=="Empty":
+ emp_list.append(o)
+ return emp_list
+
+#########
+# Cette fonction renvoie la liste des empties
+# in :
+# out : emp_list (List of Object) la liste des objets de type "Empty"
+#########
+def getEmpty(name):
+ p = None
+ objs = Blender.Object.Get()
+ for o in objs:
+ if o.getType()=="Empty" and o.getName()==name:
+ p = o
+ return p
+
+def getChild(emp, emp_list):
+ return dicEmptyChild[emp.getName()]
+
+
+#########
+# Cette fonction fournit la liste des enfants d'un empty
+# in : emp (Object) un empty
+# emp_list (List of Object) la liste des empties
+# out : children (List of Object) la liste des empties enfants de 'empty'
+#########
+def getChildren(emp, emp_list):
+ children = []
+ root_emp = getRootEmpties(emp_list)
+ for em in emp_list:
+ if (em.getName() != emp.getName()) and (em not in root_emp):
+ if (em.getParent().getName() == emp.getName()):
+ children.append(em)
+ return children
+
+
+
+#########
+# Cette fonction renvoie la liste des empties n'ayant pas de parent
+# in : emp_list (List) une liste d'empties
+# out : root (List) le (ou les) empty n'ayant pas de parent
+#########
+def getRootEmpties(emp_list):
+ root = []
+ for em in emp_list:
+ if em.getParent() == None:
+ root.append(em)
+ return root
+
+
+#########
+# Cette fonction renvoie le bone de nom 'name' dans l'armature 'armature'
+# in : armature (Armature) l'armature dans laquelle cherchait le bone
+# name (String) le nom de l'os a chercher
+# out : p (Bone)
+#########
+#def getBone(armature, name):
+# return (dicBone[name])
+ #p = None
+ #bones = armature.getBones()
+ #for i in bones:
+ # if i.getName() == name:
+ # p = i
+ # break
+ #return p
+
+
+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 GetOrCreateIPO(name):
+
+ ipos = Blender.Ipo.Get()
+ if name in map(names,ipos):
+ myipo = Blender.Ipo.Get(name)
+ print name+' exists'
+ else:
+ myipo = Blender.Ipo.New('Object',name)
+ print name+' was created'
+ return myipo
+
+
+def GetOrCreateCurve(ipo, curvename):
+ curves = ipo.getCurves()
+ if curvename in map(names,curves):
+ mycurve = ipo.getCurve(curvename)
+ print curvename+' exists'
+ else:
+ mycurve = ipo.addCurve(curvename)
+ print curvename+' was created'
+ return mycurve
+
+
+
+
+########################################################################
+#
+# FUNCTIONS FOR COMPUTING POSITION AND ROTATION OF BONES
+#
+########################################################################
+
+def computeRootQuat2(empty, bone):
+
+ M1=dicBoneRestInvEmpRest[bone.getName()].rotationPart()
+ M2=dicEmpRestInvBoneRest[bone.getName()].rotationPart()
+ emprot = empty.getMatrix('worldspace').rotationPart()
+ emprot.transpose()
+ mat = M1*emprot*M2
+ mat.transpose()
+ return (mat.toQuat())
+
+ #emprest = dicEmptiesRestMatrix[empty.getName()].rotationPart()
+ #invemprest= dicEmptiesRestMatrix[empty.getName()].rotationPart()
+ ##invemprest= emprest
+ ##invemprest.invert()
+ ##invemprest= dicEmptiesInvRestMatrix[empty.getName()].rotationPart()
+ #emprot = empty.getMatrix('worldspace').rotationPart()
+ #bonerest = dicBoneRestMatrix[bone.getName()].rotationPart()
+ #invbonerest = dicBoneRestMatrix[bone.getName()].rotationPart()
+ #invbonerest.invert()
+ #T2=emprot*invemprest
+ #T2.transpose()
+ #mat = bonerest*invemprest*T2*emprest*invbonerest
+ #mat.transpose()
+ #return (mat.toQuat())
+
+
+
+
+#########
+# Cette fonction
+# in :
+# out :
+#########
+def computeRootPos(empty, bone):
+ vec = computeScaledPos(empty.getMatrix('worldspace').translationPart()) - dicBoneRestMatrix[bone.getName()].translationPart()
+ mat = dicBoneRestMatrix[bone.getName()].rotationPart()
+ vec2 = Mathutils.MatMultVec (mat, vec)
+ return vec2
+
+
+def computeRelativePos(empty,bone):
+ vec = computeScaledPos(empty.getMatrix('worldspace').translationPart()) - dicBoneRestMatrix[bone.getName()].translationPart()
+ rootempty = getEmpty(hipbonename)
+ vec3 = computeScaledPos(rootempty.getMatrix('worldspace').translationPart())
+ mat = dicBoneRestMatrix[bone.getName()].rotationPart()
+ vec2 = Mathutils.MatMultVec (mat, vec-vec3)
+ return vec2
+
+
+ #########
+# Cette fonction
+# in :
+# out :
+#########
+def computeScaledPos(vec):
+ global scalef
+ vec2 = Mathutils.Vector([vec[0]*scalef, vec[1]*scalef, vec[2]*scalef])
+ return vec2
+
+########################################################################
+#
+# FUNCTIONS FOR CREATING AND MOVING ARMATURES
+#
+########################################################################
+
+#########
+# Cette fonction
+# in :
+# out :
+#########
+def createBone (armature, empty, bone, empties):
+ children = getChildren(empty, empties)
+ for ch in children:
+ if len(children) >= 2:
+ bonename = empty.getName()[1:len(empty.getName())]+'_'+ch.getName()[1:len(ch.getName())]
+ else :
+ bonename = empty.getName()[1:len(empty.getName())]
+ b=Blender.Armature.Bone.New(bonename)
+ b.setHead(computeScaledPos(empty.getMatrix('worldspace').translationPart()))
+ b.setTail(computeScaledPos(ch.getMatrix('worldspace').translationPart()))
+ #b.setParent(bone)
+ matrice = empty.getMatrix('worldspace')
+ invmatrice = empty.getMatrix('worldspace')
+ invmatrice.invert()
+ invmatricet=empty.getMatrix('worldspace')
+ invmatricet.invert()
+ invmatricet.transpose()
+ dicEmptiesRestMatrix[empty.getName()] = matrice
+ dicEmptiesInvRestMatrix[empty.getName()] = invmatrice
+ armature.addBone(b)
+ invbonerest=b.getRestMatrix()
+ invbonerest.invert()
+ dicBoneRestMatrix[b.getName()] = b.getRestMatrix()
+ dicBoneRestInvEmpRest[b.getName()]=b.getRestMatrix()*invmatrice*invmatricet
+ dicEmpRestInvBoneRest[b.getName()]=matrice*invbonerest
+ dicBone[b.getName()]=b
+ createBone(armature, ch, b, empties)
+
+#########
+# Cette fonction
+# in :
+# out :
+#########
+def f_createBone (armData, empty, bone, empties):
+ bones = armData.getBones()
+
+ def getBone(bonename):
+ bone = None
+ for b in bones:
+ #print b.getName()
+ if b.getName() == bonename:
+ bone = b
+ return bone
+
+ children = getChildren(empty, empties)
+ for ch in children:
+ if len(children) >= 2:
+ bonename = empty.getName()[1:len(empty.getName())]+'_'+ch.getName()[1:len(ch.getName())]
+ else :
+ bonename = empty.getName()[1:len(empty.getName())]
+ #b=Blender.Armature.Bone.New(bonename)
+ b=getBone(bonename)
+ #b.setHead(empty.getMatrix('worldspace').translationPart())
+ #b.setTail(ch.getMatrix('worldspace').translationPart())
+ #b.setParent(bone)
+ matrice = empty.getMatrix('worldspace')
+ invmatrice = empty.getMatrix('worldspace')
+ invmatrice.invert()
+ invmatricet=empty.getMatrix('worldspace')
+ invmatricet.invert()
+ invmatricet.transpose()
+ dicEmptiesRestMatrix[empty.getName()] = matrice
+ dicEmptiesInvRestMatrix[empty.getName()] = invmatrice
+ #armature.addBone(b)
+ invbonerest=b.getRestMatrix()
+ invbonerest.invert()
+ dicBoneRestMatrix[b.getName()] = b.getRestMatrix()
+ dicBoneRestInvEmpRest[b.getName()]=b.getRestMatrix()*invmatrice*invmatricet
+ dicEmpRestInvBoneRest[b.getName()]=matrice*invbonerest
+ dicBone[b.getName()]=b
+ print "Ajout de ", b.getName()," au dictionnaire"
+ f_createBone(armData, ch, b, empties)
+
+
+#########
+# Cette fonction fabrique une arma
+# in :
+# out :
+#########
+def createArmature (rootEmpty, empties):
+ armData=Blender.Armature.New('monArmature')
+ children = getChildren(rootEmpty, empties)
+ for ch in children:
+ b=Blender.Armature.Bone.New(rootEmpty.getName()[1:len(rootEmpty.getName())] + ch.getName()[1:len(ch.getName())])
+ b.setHead(computeScaledPos(rootEmpty.getMatrix('worldspace').translationPart()))
+ b.setTail(computeScaledPos(ch.getMatrix('worldspace').translationPart()))
+ armData.addBone(b)
+ matrice = ch.getMatrix('worldspace')
+ invmatrice = ch.getMatrix('worldspace')
+ invmatrice.invert()
+ invmatricet=ch.getMatrix('worldspace')
+ invmatricet.invert()
+ invmatricet.transpose()
+ dicEmptiesRestMatrix[rootEmpty.getName()] = matrice
+ dicEmptiesInvRestMatrix[rootEmpty.getName()] = invmatrice
+ invbonerest=b.getRestMatrix()
+ invbonerest.invert()
+ dicBoneRestMatrix[b.getName()] = b.getRestMatrix()
+ dicBoneRestInvEmpRest[b.getName()]=b.getRestMatrix()*invmatrice*invmatricet
+ dicEmpRestInvBoneRest[b.getName()]=matrice*invbonerest
+ dicBone[b.getName()]=b
+ createBone(armData, ch, b, empties)
+ return armData
+
+
+
+#########
+# Cette fonction fabrique une arma
+# in :
+# out :
+#########
+def f_createArmature (rootEmpty, empties, armData):
+ bones = armData.getBones()
+
+ def getBone(bonename):
+ bone = None
+ for b in bones:
+ #print b.getName()
+ if b.getName() == bonename:
+ bone = b
+ return bone
+
+ children = getChildren(rootEmpty, empties)
+ for ch in children:
+ b=getBone(rootEmpty.getName()[1:len(rootEmpty.getName())] + ch.getName()[1:len(ch.getName())])
+ matrice = ch.getMatrix('worldspace')
+ invmatrice = ch.getMatrix('worldspace')
+ invmatrice.invert()
+ invmatricet=ch.getMatrix('worldspace')
+ invmatricet.invert()
+ invmatricet.transpose()
+ dicEmptiesRestMatrix[rootEmpty.getName()] = matrice
+ dicEmptiesInvRestMatrix[rootEmpty.getName()] = invmatrice
+ invbonerest=b.getRestMatrix()
+ invbonerest.invert()
+ dicBoneRestMatrix[b.getName()] = b.getRestMatrix()
+ dicBoneRestInvEmpRest[b.getName()]=b.getRestMatrix()*invmatrice*invmatricet
+ dicEmpRestInvBoneRest[b.getName()]=matrice*invbonerest
+ dicBone[b.getName()]=b
+ print "Ajout de ", b.getName()," au dictionnaire"
+
+ f_createBone(armData, ch, b, empties)
+
+
+
+#########
+# Cette fonction
+# in :
+# out :
+#########
+def moveBones(armature, empty, empties):
+ children = dicEmptyChild[empty.getName()]
+ for ch in children:
+ if len(children) >= 2:
+ bonename = empty.getName()[1:len(empty.getName())]+'_'+ch.getName()[1:len(ch.getName())]
+ else :
+ bonename = empty.getName()[1:len(empty.getName())]
+ bone = dicBone[bonename]
+ #bone.setLoc(computeRootPos(empty,bone))
+ bone.setLoc(computeRelativePos(empty,bone))
+ bone.setQuat(computeRootQuat2(empty,bone))
+ chch = dicEmptyChild[ch.getName()]
+ if len(chch) >= 1:
+ moveBones(armature, ch, empties)
+
+
+#########
+# Cette fonction
+# in :
+# out :
+#########
+def moveArmature (armature, empties):
+ root = Blender.Object.Get(hipbonename)
+ children = dicEmptyChild[hipbonename]
+ for ch in children:
+ b=dicBone[hipbonename[1:len(hipbonename)] + ch.getName()[1:len(ch.getName())]]
+ #b.setLoc(computeRootPos(root, b))
+ b.setLoc([0.0, 0.0, 0.0])
+ b.setQuat(computeRootQuat2(root, b))
+ moveBones(armature, ch, empties)
+
+
+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)
+
+
+########################################################################
+#
+# MAIN PROGRAM
+#
+########################################################################
+
+def RemoveEmpties():
+
+ global endframe, startframe,hipbonename
+
+ lesEmpties = getEmpties()
+ scn = Blender.Scene.getCurrent()
+ #scn.link (armObj)
+ for em in lesEmpties:
+ eraseIPO (em.getName())
+ scn.unlink(em)
+ Blender.Redraw()
+
+
+def Main():
+
+ global endframe, startframe,hipbonename, framedecimation
+
+
+ print "*****START*****"
+
+ Blender.Set("curframe",restFrame)
+
+ ##-----------
+ ## Positionnement des empties
+ ##-----------
+ em0 = Blender.Object.Get(hipbonename)
+
+ Blender.Redraw()
+
+
+
+ ##-----------
+ ## Creation de l'armature et des os
+ ##-----------
+
+ lesEmpties = getEmpties()
+ #print dicEmptyChild
+
+ #armData = createArmature(em0, lesEmpties)
+ objects = Blender.Object.Get()
+ if 'OBArmature' in map(names,objects):
+ armObj = Blender.Object.Get('OBArmature')
+ armData = armObj.getData()
+ print 'OBArmature'+' exists'
+ eraseIPO ('OBArmature')
+ #print armData.getBones()
+ f_createArmature(em0, lesEmpties, armData)
+ else:
+ armData= createArmature(em0, lesEmpties)
+ armObj=Blender.Object.New('Armature', 'OBArmature')
+ armObj.link(armData)
+ scn = Blender.Scene.getCurrent()
+ scn.link (armObj)
+
+ print 'OBArmature'+' was created'
+ #return myobj
+
+ ##-----------
+ ## Creation de l'ipo de l'armature
+ ##-----------
+ lipo = GetOrCreateIPO('BVHIpo')
+ armObj.setIpo(lipo)
+ curvX = GetOrCreateCurve(lipo, 'LocX')
+ curvY = GetOrCreateCurve(lipo, 'LocY')
+ curvZ = GetOrCreateCurve(lipo, 'LocZ')
+
+
+ #armData.drawAxes(1)
+ #armData.drawNames(1)
+
+
+
+ Blender.Redraw()
+
+ ##-----------
+ ## Enregistrement de la position de l'armature
+ ##-----------
+
+ bones = armData.getBones()
+ for bo in bones:
+ bo.setPose([Blender.Armature.Bone.ROT, Blender.Armature.Bone.LOC])
+
+ curvX.addBezier((Blender.Get("curframe"), getEmpty(hipbonename).getMatrix('worldspace').translationPart()[0]*scalef))
+ curvY.addBezier((Blender.Get("curframe"), getEmpty(hipbonename).getMatrix('worldspace').translationPart()[1]*scalef))
+ curvZ.addBezier((Blender.Get("curframe"), getEmpty(hipbonename).getMatrix('worldspace').translationPart()[2]*scalef))
+ curvX.setInterpolation('Linear')
+ curvX.setExtrapolation('Constant')
+ curvY.setInterpolation('Linear')
+ curvY.setExtrapolation('Constant')
+ curvZ.setInterpolation('Linear')
+ curvZ.setExtrapolation('Constant')
+
+ Blender.Redraw()
+
+ Blender.Set("curframe",startframe)
+ while endframe >= Blender.Get("curframe"):
+
+ ##-----------
+ ## Positionnement des os
+ ##-----------
+
+ moveArmature(armData, lesEmpties)
+
+
+ ##-----------
+ ## Enregistrement de la position de l'armature
+ ##-----------
+
+ for bo in bones:
+ bo.setPose([Blender.Armature.Bone.ROT, Blender.Armature.Bone.LOC])
+ curvX.addBezier((Blender.Get("curframe"), (getEmpty(hipbonename).getMatrix('worldspace').translationPart()[0])*scalef))
+ curvY.addBezier((Blender.Get("curframe"), (getEmpty(hipbonename).getMatrix('worldspace').translationPart()[1])*scalef))
+ curvZ.addBezier((Blender.Get("curframe"), (getEmpty(hipbonename).getMatrix('worldspace').translationPart()[2])*scalef))
+
+ ##-----------
+ ## Passage a la frame suivante
+ ##-----------
+ num_frame = Blender.Get("curframe")+framedecimation
+ print num_frame
+ Blender.Set("curframe", num_frame)
+
+ Blender.Set("curframe",startframe)
+ Blender.Redraw()
+
+ print "*****END*****"
+
+
+########################################################################
+#
+# GUI FUNCTIONS AND VARIABLES
+#
+########################################################################
+
+EFrame = Blender.Draw.Create(5)
+IFrame = Blender.Draw.Create(6)
+SFrame2 = Blender.Draw.Create(5)
+HBName = Blender.Draw.Create(0)
+FrameDecimation = Blender.Draw.Create(5)
+ScaleF = Blender.Draw.Create(0)
+
+Msg = ' '
+
+def event (evt, val):
+ if evt == Blender.Draw.ESCKEY:
+ Blender.Draw.Exit()
+ return
+
+def button_event(evt):
+ global EFrame, IFrame, SFrame2, HBName, Msg , FrameDecimation, ScaleF
+ global endframe, startframe, insertionframe, hipbonename, framedecimation , scalef
+ if evt==1:
+ startframe = SFrame2.val
+ insertionframe = IFrame.val
+ endframe = EFrame.val
+ hipbonename = HBName.val
+ framedecimation = FrameDecimation.val
+ scalef= eval(str(ScaleF.val))
+ print "scalef = ", scalef
+ if startframe>=endframe:
+ Msg = 'Start frame must be lower than End frame'
+ Blender.Draw.PupMenu("ERROR: %s" % Msg)
+ else:
+ ob = getEmpty(hipbonename)
+ if (ob!=None):
+ if ob.getParent()!=None:
+ Msg = 'Empty '+hipbonename+ ' is not a root bone.'
+ Blender.Draw.PupMenu("ERROR: %s" % Msg)
+ else:
+ if (0.0 > scalef):
+ Msg = 'Scale factor must be greater than 0'
+ Blender.Draw.PupMenu("ERROR: %s" % Msg)
+ else:
+ #Blender.Draw.Exit()
+ Main()
+ else:
+ Msg = 'Empty '+ hipbonename+ ' not found'
+ Blender.Draw.PupMenu("ERROR: %s" % Msg)
+
+ #Blender.Draw.Redraw(1)
+ elif evt==2:
+ hipbonename = HBName.val
+ ob = getEmpty(hipbonename)
+ if (ob!=None):
+ if ob.getParent()!=None:
+ Msg = 'Empty '+hipbonename+ ' is not a root bone.'
+ Blender.Draw.PupMenu("ERROR: %s" % Msg)
+ else:
+ #Blender.Draw.Exit()
+ RemoveEmpties()
+ else:
+ Msg = 'Empty '+ hipbonename+ ' not found'
+ Blender.Draw.PupMenu("ERROR: %s" % Msg)
+
+ #else:
+ # print "evt = ",evt
+
+def GUI():
+ global EFrame, SFrame2, HBName, Msg , ScaleF, FrameDecimation
+ Blender.BGL.glClearColor(0,0,1,1)
+ Blender.BGL.glClear(Blender.BGL.GL_COLOR_BUFFER_BIT)
+ Blender.BGL.glColor3f(1,1,1)
+ Blender.BGL.glRasterPos2i(20,200)
+ Blender.Draw.Text ("BVH 2 ARMATURE v2.0 by Jean-Baptiste PERIN", 'normal')
+ HBName = Blender.Draw.String("HipBoneName: ", -1, 20, 175, 250, 20, '_Hips', 100)
+ SFrame2 = Blender.Draw.Number("Startframe: ", -1, 20, 150, 250, 20, 1, 1,3000,"")
+ EFrame = Blender.Draw.Number("Endframe: ", -1, 20, 125, 250, 20, Blender.Get("endframe"), 1,3000,"")
+ #IFrame = Blender.Draw.Number("Insertionframe: ", -1, 20, 100, 250, 20, Blender.Get("staframe"), 1,3000,"")
+ FrameDecimation = Blender.Draw.Number("FrameDecimation: ", -1, 20, 75, 250, 20,5, 1,10,'')
+ ScaleF = Blender.Draw.Number("Scale: ", -1, 20, 50, 250, 20, 0.03, 0.0, 10.0, 'Scale Factor')
+ Blender.Draw.Toggle("Create Armature", 1, 20, 10, 100, 20, 0, "Create Armature")
+ #Blender.Draw.Toggle("Remove Empties", 2, 200, 10, 100, 20, 0, "Remove Empties")
+ Blender.BGL.glRasterPos2i(20,40)
+ Blender.Draw.Text (Msg, 'normal')
+
+
+Blender.Draw.Register(GUI, event, button_event)
diff --git a/release/scripts/bvh_import.py b/release/scripts/bvh_import.py
index 8c39d32eb8f..103c0df9969 100644
--- a/release/scripts/bvh_import.py
+++ b/release/scripts/bvh_import.py
@@ -21,8 +21,9 @@ Missing:<br>
Known issues:<br>
Notes:<br>
- Jean-Michel Soler improved importer to support Poser 3.01 files.
-
+ Jean-Michel Soler improved importer to support Poser 3.01 files;<br>
+ Jean-Baptiste Perin wrote a script to create an armature out of the
+Empties created by this importer, it's in the Scripts window -> Scripts -> Animation menu.
"""
# $Id$
diff --git a/release/scripts/camera_changer.py b/release/scripts/camera_changer.py
new file mode 100644
index 00000000000..fe08c6d6338
--- /dev/null
+++ b/release/scripts/camera_changer.py
@@ -0,0 +1,95 @@
+#!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.
+"""
+
+
+# $Id$
+#
+#Script in the same idea that 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
+
+sc=Scene.GetCurrent()
+
+#import du texte
+lestext=Blender.Text.Get()
+Ntexts=[]
+for txt in lestext:
+ Ntexts.append(txt.getName())
+ecrire=0
+
+if 'camera.py' not in Ntexts:
+ ecrire=1
+else :
+ if lestext[Ntexts.index('camera.py')].asLines()[0] != "# camera.py 1.2 link python #":
+ reecrire=Blender.Draw.PupMenu("WARNING: Text camera.py already exists but is outdated%t|Overwrite|Rename old version text")
+ if reecrire == 1:
+ Text.unlink(lestext[Ntexts.index('camera.py')])
+ ecrire=1
+ if reecrire == 2:
+ lestext[Ntexts.index('camera.py')].name="old_camera.txt"
+ ecrire=1
+
+
+
+if ecrire == 1:
+ scripting=Blender.Text.New('camera.py')
+ scripting.write("# camera.py 1.2 link python #\nimport Blender\nfrom Blender import *\nfrom math import *\nimport string\n")
+ scripting.write("sc=Scene.GetCurrent()\n#Changement camera\nlescam=[]\nobjets=Blender.Object.Get()\n")
+ scripting.write("for ob in objets:\n if type(ob.getData())==Blender.Types.CameraType:\n try:")
+ scripting.write("\n lesfram=string.split(ob.name,',')\n for fr in lesfram:\n lescam.append(ob.name)\n lescam.append(int(fr))\n except:\n pass")
+ scripting.write("\nframe = Blender.Get('curframe')\nif frame in lescam:\n nom=lescam.index(frame)\n sc.setCurrentCamera(Blender.Object.Get(lescam[nom-1]))\n")
+
+
+#Linkage
+list=[]
+try:
+ for script in sc.getScriptLinks('FrameChanged'):
+ list.append(script)
+except:
+ pass
+if 'camera.py' not in list:
+ sc.addScriptLink('camera.py','FrameChanged')
+ Blender.Draw.PupMenu("Done! Remember:%t|Name cameras as (a comma separated list of) their activation frame number(s)")
+ Blender.Redraw(-1)
+
diff --git a/release/scripts/console.py b/release/scripts/console.py
new file mode 100644
index 00000000000..1fbf7908c7a
--- /dev/null
+++ b/release/scripts/console.py
@@ -0,0 +1,517 @@
+#!BPY
+
+"""
+Name: 'Interactive Console'
+Blender: 236
+Group: 'System'
+Tooltip: 'Interactive Python Console'
+"""
+__author__ = "Campbell Barton AKA Ideasman"
+__url__ = ["http://members.iinet.net.au/~cpbarton/ideasman/", "blender", "elysiun", "Official Python site, http://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 can 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: Save output;<br>
+ - Arrow keys: command history and cursor;<br>
+ - Ctrl + Tab: auto compleate based on variable names and modules loaded -- multiple choices popup a menu;<br>
+ - Ctrl + Enter: multiline functions -- delays executing code until only Enter is pressed.
+"""
+
+import Blender
+from Blender import *
+import sys as python_sys
+import StringIO
+import types
+
+# Constants
+__DELIMETERS__ = '. ,=+-*/%<>&~][{}():'
+__LINE_HISTORY__ = 200
+__LINE_HEIGHT__ = 14
+__FONT_SIZE__ = "normal"
+
+'''
+# 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
+'''
+
+class cmdLine:
+ # cmd: is the command string, or any other message
+ # 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(cmdLineList, type):
+ if type == 3:
+ typeList = [0,1,2, 3, None] # all
+ else:
+ typeList = [type] # so we can use athe lists 'in' methiod
+
+ newText = Text.New('command_output.py', 1)
+ for myCmd in cmdLineList:
+ if myCmd.type in typeList: # user input
+ newText.write('%s\n' % myCmd.cmd)
+ Draw.PupMenu('%s written' % newText.name)
+
+def insertCmdData(cmdBuffer):
+ textNames = [tex.name for tex in Text.Get()]
+ if textNames:
+ choice = Draw.PupMenu('|'.join(textNames))
+ if choice != -1:
+ text = Text.Get()[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
+def rdir(dirString):
+ global COLLECTED_VAR_NAMES
+ dirStringSplit = dirString.split('.')
+
+ exec('dirList = dir(%s)' % dirString)
+ for dirItem in dirList:
+ if not dirItem.startswith('_'):
+ if dirItem not in COLLECTED_VAR_NAMES.keys():
+ COLLECTED_VAR_NAMES[dirItem] = []
+
+ # Add the string
+ splitD = dirString.split('"')[-2]
+ if splitD not in COLLECTED_VAR_NAMES[dirItem]:
+ COLLECTED_VAR_NAMES[dirItem].append(splitD)
+
+
+
+ # Stops recursice stuff, overlooping
+ if type(dirItem) == types.ClassType or \
+ type(dirItem) == types.ModuleType:
+
+ print dirString, splitD, dirItem
+
+ # Dont loop up dirs for strings ints etc.
+ if d not in dirStringSplit:
+ rdir( '%s.%s' % (dirString, d))
+
+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.
+ for __TMP_VAR_NAME__ in __CONSOLE_VAR_DICT__.keys():
+ exec('%s%s%s%s' % (__TMP_VAR_NAME__,'=__CONSOLE_VAR_DICT__["', __TMP_VAR_NAME__, '"]'))
+ del __TMP_VAR_NAME__
+
+ # 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'))
+
+ # 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 = str(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 cmdBuffer
+ 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, cmdBuffer
+ # Check for the neter kay hit
+ if Window.GetKeyQualifiers() & Window.Qual.CTRL: # HOLDING DOWN SHIFT, GO TO NEXT LINE.
+ cmdBuffer.append(cmdLine(' ', 0, 0))
+ else:
+ # Multiline code will still run with 1 line,
+ multiLineCode = ['if 1:']
+ if cmdBuffer[-1].cmd != ' ':
+ multiLineCode = ['%s%s' % (' ', cmdBuffer[-1].cmd)] # added space for fake if.
+ else:
+ cmdBuffer[-1].type = 1
+ multiLineCode = []
+ cmdBuffer[-1].exe = 1
+ i = 2
+ while cmdBuffer[-i].exe == 0:
+ if cmdBuffer[-i].cmd == ' ':# Tag as an output type so its not used in the key history
+ cmdBuffer[-i].type = 1
+ else: # space added at the start for added if 1: statement
+ multiLineCode.append('%s%s' % (' ', cmdBuffer[-i].cmd) )
+
+ # Mark as executed
+ cmdBuffer[-i].exe = 1
+ i+=1
+
+ # add if to the end, reverse will make it the start.
+ multiLineCode.append('if 1:')
+ multiLineCode.reverse()
+ multiLineCode.append(' pass') # Now this is the end
+
+
+ runUserCode('\n'.join(multiLineCode))
+
+ # Clear the output based on __LINE_HISTORY__
+ if len(cmdBuffer) > __LINE_HISTORY__:
+ cmdBuffer = cmdBuffer[-__LINE_HISTORY__:]
+
+ histIndex = cursor = -1 # Reset cursor and history
+
+ def actionUpKey():
+ global histIndex, cmdBuffer
+ if abs(histIndex)+1 >= len(cmdBuffer):
+ histIndex = -1
+ histIndex -= 1
+ while cmdBuffer[histIndex].type != 0 and abs(histIndex) < len(cmdBuffer):
+ histIndex -= 1
+ if cmdBuffer[histIndex].type == 0: # we found one
+ cmdBuffer[-1].cmd = cmdBuffer[histIndex].cmd
+
+ def actionDownKey():
+ global histIndex, cmdBuffer
+ if histIndex >= -2:
+ histIndex = -len(cmdBuffer)
+ histIndex += 1
+ while cmdBuffer[histIndex].type != 0 and histIndex != -2:
+ histIndex += 1
+ if cmdBuffer[histIndex].type == 0: # we found one
+ cmdBuffer[-1].cmd = cmdBuffer[histIndex].cmd
+
+ def actionRightMouse():
+ 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|Quit')
+ print choice
+ if choice == 1:
+ writeCmdData(cmdBuffer, 0) # type 0 user
+ elif choice == 2:
+ writeCmdData(cmdBuffer, 1) # type 1 user output
+ elif choice == 3:
+ writeCmdData(cmdBuffer, 2) # type 2 errors
+ elif choice == 4:
+ writeCmdData(cmdBuffer, 3) # All
+ elif choice == 6:
+ insertCmdData(cmdBuffer) # All
+ elif choice == 8: # Exit
+ Draw.Exit()
+
+
+ # Auto compleating, quite complex- use recutsice dir for the moment.
+ def actionAutoCompleate(): # Ctrl + Tab
+ 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 __DELIMETERS__:
+ editVar = editVar.split(splitChar)[-1]
+
+ # Now we should have the var by its self
+ if editVar:
+
+ possibilities = []
+
+ print editVar, 'editVar'
+ for __TMP_VAR_NAME__ in RECURSIVE_DIR.keys():
+ if __TMP_VAR_NAME__ == editVar:
+ # print 'ADITVAR IS A VAR'
+ continue
+ elif __TMP_VAR_NAME__.startswith( editVar ):
+ 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))
+
+ menuText = 'Choices (hold shift for whole name)%t|'
+ menuList = []
+ menuListAbs = []
+ possibilities.sort() # make nice :)
+ for __TMP_VAR_NAME__ in possibilities:
+ for usage in RECURSIVE_DIR[__TMP_VAR_NAME__]:
+ # Account for non absolute (variables for eg.)
+ if usage: # not ''
+ menuListAbs.append('%s.%s' % (usage, __TMP_VAR_NAME__)) # Used for names and can be entered when pressing shift.
+ else:
+ menuListAbs.append(__TMP_VAR_NAME__) # Used for names and can be entered when pressing shift.
+
+ menuList.append(__TMP_VAR_NAME__) # Used for non Shift
+
+
+ #choice = Draw.PupMenu('Select Variabe name%t|' + '|'.join(possibilities) )
+ choice = Draw.PupMenu(menuText + '|'.join(menuListAbs))
+ if choice != -1:
+
+ if not Window.GetKeyQualifiers() & Window.Qual.SHIFT: # Only paste in the Short name
+ cmdBuffer[-1].cmd = ('%s%s%s' % (cmdBuffer[-1].cmd[:cursor - len(editVar)], menuList[choice-1], cmdBuffer[-1].cmd[cursor:]))
+ else: # Put in the long name
+ cmdBuffer[-1].cmd = ('%s%s%s' % (cmdBuffer[-1].cmd[:cursor - len(editVar)], menuListAbs[choice-1], cmdBuffer[-1].cmd[cursor:]))
+ else:
+ # print 'NO EDITVAR'
+ return
+
+ # ------------------end------------------#
+
+
+ #if (evt == Draw.ESCKEY and not val):
+ # Draw.Exit()
+ if evt == Draw.MOUSEX: # AVOID TOO MANY REDRAWS.
+ return
+ elif evt == Draw.MOUSEY:
+ return
+
+
+ global cursor
+ global histIndex
+
+ ascii = Blender.event
+
+ #------------------------------------------------------------------------------#
+ # 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):
+ cursor +=1
+ if cursor > -1:
+ cursor = -1
+ elif (evt == Draw.LEFTARROWKEY and val):
+ cursor -=1
+
+ elif (evt == Draw.TABKEY and val):
+ if Window.GetKeyQualifiers() & Window.Qual.CTRL:
+ actionAutoCompleate()
+ else:
+ insCh('\t')
+
+ elif (evt == Draw.BACKSPACEKEY and val): 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 ascii:
+ insCh(chr(ascii))
+ else:
+ return # dont redraw.
+ 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
+
+ # Draw cursor location colour
+ cmd2curWidth = Draw.GetStringWidth(cmdBuffer[-1].cmd[:cursor], __FONT_SIZE__)
+ BGL.glColor3f(0.8, 0.2, 0.2)
+ BGL.glRecti(cmd2curWidth-1,4,cmd2curWidth+1, 20)
+
+ BGL.glColor3f(1,1,1)
+ # Draw the set of cammands to the buffer
+
+ consoleLineIdx = 1
+ wrapLineIndex = 0
+ while consoleLineIdx < len(cmdBuffer) and __CONSOLE_RECT__[3] > consoleLineIdx*__LINE_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: # NEVER WRAP THE USER INPUT
+ BGL.glRasterPos2i(0, (__LINE_HEIGHT__*consoleLineIdx) - 8)
+ Draw.Text(cmdBuffer[-consoleLineIdx].cmd, __FONT_SIZE__)
+
+
+ else: # WRAP?
+ # LINE WRAP
+ if Draw.GetStringWidth(cmdBuffer[-consoleLineIdx].cmd, __FONT_SIZE__) > __CONSOLE_RECT__[2]:
+ wrapLineList = []
+ copyCmd = [cmdBuffer[-consoleLineIdx].cmd, '']
+ while copyCmd != ['','']:
+ while Draw.GetStringWidth(copyCmd[0], __FONT_SIZE__) > __CONSOLE_RECT__[2]:
+ #print copyCmd
+ copyCmd[1] = '%s%s'% (copyCmd[0][-1], copyCmd[1]) # Add the char on the end
+ copyCmd[0] = copyCmd[0][:-1]# remove last chat
+
+ # Now we have copyCmd[0] at a good length we can print it.
+ if copyCmd[0] != '':
+ wrapLineList.append(copyCmd[0])
+
+ copyCmd[0]=''
+ copyCmd = [copyCmd[1], copyCmd[0]]
+
+ # Now we have a list of lines, draw them (OpenGLs reverse ordering requires this odd change)
+ wrapLineList.reverse()
+ for wline in wrapLineList:
+ BGL.glRasterPos2i(0, (__LINE_HEIGHT__*(consoleLineIdx + wrapLineIndex)) - 8)
+ Draw.Text(wline, __FONT_SIZE__)
+ wrapLineIndex += 1
+ wrapLineIndex-=1 # otherwise we get a silly extra line.
+
+ else: # no wrapping.
+
+ BGL.glRasterPos2i(0, (__LINE_HEIGHT__*(consoleLineIdx+wrapLineIndex)) - 8)
+ Draw.Text(cmdBuffer[-consoleLineIdx].cmd, __FONT_SIZE__)
+
+
+ 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
+cmdBuffer = [cmdLine("Welcome to Ideasman's Blender Console", 1, None),\
+ cmdLine(' * Right Click: Save output', 1, None),\
+ cmdLine(' * Arrow Keys: Command history and cursor', 1, None),\
+ cmdLine(' * Ctrl + Tab: Auto compleate based on variable names and modules loaded, multiple choices popup a menu', 1, None),\
+ cmdLine(' * Ctrl + Enter: Multiline functions, delays executing code until only Enter is pressed.', 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.
+console_autoexec = '%s%s' % (Get('datadir'), '/console_autoexec.py')
+if not sys.exists(console_autoexec):
+ # touch the file
+ open(console_autoexec, 'w').close()
+ cmdBuffer.append(cmdLine('...console_autoexec.py not found, making new in scripts data dir', 1, None))
+else:
+ cmdBuffer.append(cmdLine('...Using existing console_autoexec.py in scripts data 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 autoexecToVarList():
+ global __CONSOLE_VAR_DICT__ # write autoexec vars to this.
+
+ # Execute an external py file as if local
+ exec(include(console_autoexec))
+
+ # Write local to global __CONSOLE_VAR_DICT__ for reuse,
+ for __TMP_VAR_NAME__ in dir() + dir(Blender):
+ # Execute the local > global coversion.
+ exec('%s%s' % ('__CONSOLE_VAR_DICT__[__TMP_VAR_NAME__]=', __TMP_VAR_NAME__))
+
+autoexecToVarList() # pass the blender module
+#-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)
+
+main()
diff --git a/release/scripts/envelope_assignment.py b/release/scripts/envelope_assignment.py
new file mode 100644
index 00000000000..9bc4b5a8494
--- /dev/null
+++ b/release/scripts/envelope_assignment.py
@@ -0,0 +1,234 @@
+#!BPY
+
+"""
+Name: 'Envelope Assignment'
+Blender: 234
+Group: 'Animation'
+Tooltip: 'Assigns weights to vertices via envelopes'
+"""
+
+__author__ = "Jonas Petersen"
+__url__ = ("blender", "elysiun", "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 vertex groups from a set of envelopes.
+
+"Envelopes" are Mesh objects with names following this naming convention:
+
+<bone name>:<float value>
+
+Notes:<br>
+ - All existing vertex groups of the target Mesh will be deleted.
+
+Please check the script's homepage and the thread at blender.org (last link button above) for more info.
+"""
+
+# --------------------------------------------------------------------------
+# "Armature Symmetry" by Jonas Petersen
+# Version 0.9 - 10th November 2004 - first public release
+# --------------------------------------------------------------------------
+#
+# A script that creates vertex groups from a set of envelopes.
+#
+# Envelopes are Mesh objects with names that follow the following
+# naming convention (syntax):
+#
+# <bone name>:<float value>
+#
+# All existing vertex groups of the target Mesh will be deleted.
+#
+# 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.
+
+# 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, string
+from Blender import Mathutils
+from Blender.Mathutils import *
+
+def run(target_obj):
+ target_mesh = target_obj.getData()
+
+ num_verts = len(target_mesh.verts)
+ warn_count = 0
+ main_obj_loc = Vector(list(target_obj.getLocation()))
+
+ Blender.Window.EditMode(0)
+
+ def vertGroupExist(group):
+ global vert_group_names;
+ for name in target_mesh.getVertGroupNames():
+ if group == name:
+ return True
+ return False
+
+ def isInside(point, envl_data):
+ for i in range(len(envl_data['normals'])):
+ vec = point - envl_data['points'][i]
+ if DotVecs(envl_data['normals'][i], vec) > 0.0:
+ return False
+ return True
+
+ envls = {}
+
+ Blender.Window.DrawProgressBar(0.0, "Parsing Zones")
+
+ # go through all envelopes and fill the 'envls' dict with points, normals
+ # and weights of the box faces
+ for obj in Blender.Object.Get():
+ if obj.getType() == "Mesh":
+ name = obj.getName()
+ pos = name.find(SEPARATOR)
+ if (pos > -1):
+ mesh = obj.getData()
+ loc = Vector(list(obj.getLocation()))
+
+ bone_name = name[0:pos]
+ try:
+ weight = float(name[pos+1:len(name)])
+ except ValueError:
+ print "WARNING: invalid syntax in envelope name \"%s\" - syntax: \"<bone name>:<float value>\""%(obj.getName())
+ warn_count += 1
+ weight = 0.0
+
+ envl_data = {'points': [], 'normals': [], 'weight': weight}
+ for face in mesh.faces:
+ envl_data['normals'].append(Vector(list(face.normal)))
+ envl_data['points'].append(Vector(list(face.v[0].co)) + loc)
+
+ if not envls.has_key(bone_name):
+ # add as first data set
+ envls[bone_name] = [envl_data]
+ else:
+ # add insert in sorted list of data sets
+ inserted = False
+ for i in range(len(envls[bone_name])):
+ if envl_data['weight'] > envls[bone_name][i]['weight']:
+ envls[bone_name].insert(i, envl_data)
+ inserted = True
+ if not inserted:
+ envls[bone_name].append(envl_data)
+
+ Blender.Window.DrawProgressBar(0.33, "Parsing Vertices")
+
+ assign_count = 0
+ vert_groups = {}
+
+ # go throug all vertices of the target mesh
+ for vert in target_mesh.verts:
+ point = Vector(list(vert.co)) + main_obj_loc
+
+ vert.sel = 1
+ counted = False
+
+ for bone_name in envls.keys():
+ for envl_data in envls[bone_name]:
+
+ if (isInside(point, envl_data)):
+
+ if (not vert_groups.has_key(bone_name)):
+ vert_groups[bone_name] = {}
+
+ if (not vert_groups[bone_name].has_key(envl_data['weight'])):
+ vert_groups[bone_name][envl_data['weight']] = []
+
+ vert_groups[bone_name][envl_data['weight']].append(vert.index)
+
+ vert.sel = 0
+
+ if not counted:
+ assign_count += 1
+ counted = True
+
+ break
+
+
+ Blender.Window.DrawProgressBar(0.66, "Writing Groups")
+
+ vert_group_names = target_mesh.getVertGroupNames()
+
+ # delete all vertices in vertex groups
+ for group in vert_group_names:
+ try:
+ v = target_mesh.getVertsFromGroup(group)
+ except:
+ pass
+ else:
+ # target_mesh.removeVertsFromGroup(group) without second argument doesn't work
+ #print "removing", len(v), "vertices from group \"",group,"\""
+ target_mesh.removeVertsFromGroup(group, v)
+
+ # delete all vertex groups
+ for group in vert_group_names:
+ target_mesh.removeVertGroup(group)
+
+ # create new vertex groups and fill them
+ if 1:
+ for bone_name in vert_groups.keys():
+ # add vertex group
+ target_mesh.addVertGroup(bone_name)
+
+ for weight in vert_groups[bone_name]:
+ print "name: ", bone_name, ": ", weight, "len: ", len(vert_groups[bone_name][weight])
+ index_list = vert_groups[bone_name][weight]
+ target_mesh.assignVertsToGroup(bone_name, index_list, weight, 'replace')
+
+ target_mesh.update(0)
+
+ Blender.Window.DrawProgressBar(1.0, "")
+
+ if assign_count < num_verts:
+ Blender.Window.EditMode(1)
+ print '\a'
+ if warn_count: warn_msg = " There is also %d warning(s) in the console."%(warn_count)
+ else: warn_msg = ""
+ Blender.Draw.PupMenu("Envelope Assignment%%t|%d vertices were not assigned.%s"%(num_verts-assign_count, warn_msg))
+ elif warn_count:
+ print '\a'
+ Blender.Draw.PupMenu("Envelope Assignment%%t|There is %d warning(s) in the console."%(warn_count))
+
+sel_objs = Blender.Object.GetSelected()
+if len(sel_objs) != 1 or sel_objs[0].getType() != "Mesh":
+ print '\a'
+ Blender.Draw.PupMenu("Envelope Assignment%t|Please select 1 Mesh object to assign vertex groups to!")
+else:
+ if string.find(sel_objs[0].getName(), SEPARATOR) > -1:
+ print '\a'
+ Blender.Draw.PupMenu("Envelope Assignment%t|Don't use the command on the envelopes themselves!")
+ else:
+ run(sel_objs[0])
diff --git a/release/scripts/envelope_symmetry.py b/release/scripts/envelope_symmetry.py
new file mode 100644
index 00000000000..5a4f7a31b3b
--- /dev/null
+++ b/release/scripts/envelope_symmetry.py
@@ -0,0 +1,176 @@
+#!BPY
+
+"""
+Name: 'Envelope Symmetry'
+Blender: 234
+Group: 'Animation'
+Tooltip: 'Make envelope symetrical'
+"""
+
+__author__ = "Jonas Petersen"
+__url__ = ("blender", "elysiun", "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):
+ objs = Blender.Object.Get()
+ for obj in objs:
+ if obj.getType() == "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 == mesh_name:
+ return obj
+ return False
+
+SUFFIX_LEN = len(REF_SUFFIX);
+
+Blender.Window.EditMode(0)
+
+count = 0
+objs = Blender.Object.Get()
+for obj in objs:
+ if obj.getType() != 'Mesh':
+ continue
+
+ count += 1
+ name = obj.getName()
+ 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 range(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 = Blender.NMesh.GetRaw(obj.getData().name)
+ 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/fixfromarmature.py b/release/scripts/fixfromarmature.py
index 9e11702c0be..a9fea501b87 100644
--- a/release/scripts/fixfromarmature.py
+++ b/release/scripts/fixfromarmature.py
@@ -1,20 +1,20 @@
#!BPY
""" Registration info for Blender menus: <- these words are ignored
-Name: 'Fix From Armature'
-Blender: 232
+Name: 'Fix From Everything'
+Blender: 236
Group: 'Mesh'
-Tip: 'Fix armature deformation'
+Tip: 'Fix armature/lattice/RVK/curve deform and taper/soft body deformation (without bake)'
"""
__author__ = "Jean-Michel Soler (jms)"
__url__ = ("blender", "elysiun",
"Script's homepage, http://jmsoler.free.fr/util/blenderfile/py/fixfromarmature.py",
"Communicate problems and errors, http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender")
-__version__ = "10/2004"
+__version__ = "05/2005"
__bpydoc__ = """\
-This script creates a copy of the active mesh with armature deformation fixed.
+This script creates a copy of the active mesh with deformations fixed.
Usage:
@@ -24,7 +24,7 @@ Select the mesh and run this script. A fixed copy of it will be created.
# $Id$
#
#----------------------------------------------
-# jm soler 05/2004 : 'FixfromArmature'
+# jm soler 05/2004-->04/2005 : 'FixfromArmature'
#----------------------------------------------
# Official Page :
# http://jmsoler.free.fr/util/blenderfile/py/fixfromarmature.py
@@ -65,36 +65,50 @@ Select the mesh and run this script. A fixed copy of it will be created.
import Blender
+def fix_mesh(nomdelobjet):
+ Mesh=Blender.NMesh.GetRawFromObject(nomdelobjet)
+ Obis = Blender.Object.New ('Mesh')
+ Obis.link(Mesh)
+ Obis.setMatrix(Ozero.getMatrix())
+ scene = Blender.Scene.getCurrent()
+ scene.link (Obis)
+
+ Mesh2=Obis.getData()
+ Mesh1=Ozero.getData()
+
+ if len(Mesh2.verts)==len(Mesh1.verts):
+ for VertGroupName in Mesh1.getVertGroupNames():
+ VertexList = Mesh1.getVertsFromGroup(VertGroupName, True)
+ Mesh2.addVertGroup(VertGroupName)
+ for Vertex in VertexList:
+ Mesh2.assignVertsToGroup(VertGroupName, [Vertex[0]], Vertex[1], 'add')
+ else:
+ for vgroupname in Mesh1.getVertGroupNames():
+ Mesh2.addVertGroup(vgroupname)
+ Mesh2.update()
+
+
Ozero=Blender.Object.GetSelected()[0]
errormsg = ''
+
if not Ozero:
- errormsg = "no mesh object selected"
+ errormsg = "no mesh object selected"
elif Ozero.getType() != "Mesh":
- errormsg = "selected (active) object must be a mesh"
+ errormsg = "selected (active) object must be a mesh"
if errormsg:
- Blender.Draw.PupMenu("ERROR: %s" % errormsg)
+ Blender.Draw.PupMenu("ERROR: %s" % errormsg)
else:
- nomdelobjet=Ozero.getName()
- Mesh=Blender.NMesh.GetRawFromObject(nomdelobjet)
- Obis = Blender.Object.New ('Mesh')
- Obis.link(Mesh)
- Obis.setMatrix(Ozero.getMatrix())
- scene = Blender.Scene.getCurrent()
- scene.link (Obis)
-
- Mesh2=Obis.getData()
- Mesh1=Ozero.getData()
-
- if len(Mesh2.verts)==len(Mesh1.verts):
- for VertGroupName in Mesh1.getVertGroupNames():
- VertexList = Mesh1.getVertsFromGroup(VertGroupName, True)
- Mesh2.addVertGroup(VertGroupName)
- for Vertex in VertexList:
- Mesh2.assignVertsToGroup(VertGroupName, [Vertex[0]], Vertex[1], 'add')
- else:
- for vgroupname in Ozero.getVertGroupNames():
- Mesh2.addVertGroup(vgroupname)
- Mesh2.update()
+ fix = 1
+ curframe = Blender.Get('curframe')
+ if Ozero.isSB() and curframe != 1:
+ softbodies=Blender.Draw.PupMenu("Soft Body: play anim up to the current frame to fix it?%t|Yes%x1|No %x2|Cancel %x3")
+ if softbodies==3:
+ fix = 0
+ elif softbodies==1:
+ for f in range(1, curframe + 1):
+ Blender.Set('curframe',f)
+ if fix: fix_mesh(Ozero.getName())
+
diff --git a/release/scripts/knife.py b/release/scripts/knife.py
index c58c8b4dada..017b81de393 100644
--- a/release/scripts/knife.py
+++ b/release/scripts/knife.py
@@ -1,7 +1,7 @@
#!BPY
"""
-Name: 'Blender Knife Tool'
+Name: 'Knife Tool'
Blender: 232
Group: 'Object'
Tooltip: 'Cut selected mesh(es) along an active plane w/o creating doubles'
diff --git a/release/scripts/save_theme.py b/release/scripts/save_theme.py
index a79de94f4ea..ba0b9bbcf8f 100644
--- a/release/scripts/save_theme.py
+++ b/release/scripts/save_theme.py
@@ -9,7 +9,7 @@ Tooltip: 'Save current theme as a bpython script'
__author__ = "Willian P. Germano"
__url__ = ("blender", "elysiun")
-__version__ = "1.1 2005/13/01"
+__version__ = "1.2 2005/05/17"
__bpydoc__ = """\
This script saves the current Theme in Blender as a Blender Python script.
@@ -63,7 +63,7 @@ default_fname = default_fname.replace(' ','_')
def write_theme(filename):
"Write the current theme as a bpython script"
- if filename.find('.py', -3) <= 0: filename += '.py'
+ if not filename.endswith('.py'): filename += '.py'
fout = file(filename, "w")
@@ -77,7 +77,7 @@ def write_theme(filename):
# \"\"\"
__%s__ = "????"
-__%s__ = "1.0"
+__%s__ = "1.2"
__%s__ = ["blender"]
__%s__ = \"\"\"\\
You can edit this section to write something about your script that can
diff --git a/release/scripts/vrml97_export.py b/release/scripts/vrml97_export.py
index 7fb036f9997..478fbf901ad 100644
--- a/release/scripts/vrml97_export.py
+++ b/release/scripts/vrml97_export.py
@@ -5,7 +5,7 @@ Blender: 235
Group: 'Export'
Submenu: 'All Objects...' all
Submenu: 'Selected Objects...' selected
-Tooltip: 'Export to VRML97 file format (.wrl)'
+Tooltip: 'Export to VRML97 (VRML2) file format (.wrl)'
"""
__author__ = ("Rick Kimball", "Ken Miller", "Steve Matthews", "Bart")
diff --git a/release/scripts/x3d_export.py b/release/scripts/x3d_export.py
new file mode 100644
index 00000000000..1f869d08464
--- /dev/null
+++ b/release/scripts/x3d_export.py
@@ -0,0 +1,1045 @@
+#!BPY
+""" Registration info for Blender menus:
+Name: 'X3D Extensible 3D (.x3d)...'
+Blender: 235
+Group: 'Export'
+Submenu: 'All Objects...' all
+Submenu: 'Selected Objects...' selected
+Tooltip: 'Export to Extensible 3D file format (.x3d)'
+"""
+
+__author__ = ("Bart")
+__url__ = ["Author's (Bart) homepage, http://www.neeneenee.de/vrml",
+"Complete online documentation, http://www.neeneenee.de/blender/x3d/exporting_web3d.html"]
+__version__ = "2005/05/10"
+
+
+
+__bpydoc__ = """\
+This script exports to X3D file 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 *****
+#
+# Copyright (C) 2003,2004: 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 *****
+#
+
+####################################
+# Library dependancies
+####################################
+
+import Blender
+from Blender import Object, NMesh, Lamp, Draw, BGL, Image, Text
+from Blender.Scene import Render
+from os.path import exists, join
+pytinst = 1
+import math, sys, datetime
+
+####################################
+# Global Variables
+####################################
+
+scene = Blender.Scene.getCurrent()
+world = Blender.World.Get()
+worldmat = Blender.Texture.Get()
+filename = Blender.Get('filename')
+_safeOverwrite = True
+radD=math.pi/180.0
+ARG=''
+
+def rad2deg(v):
+ return round(v*180.0/math.pi,4)
+
+def deg2rad(v):
+ return (v*math.pi)/180.0;
+
+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.writingcolor = 0
+ self.writingtexture = 0
+ self.writingcoords = 0
+ self.wire = 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 = open(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",
+ "GeoLocation","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):
+ 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" % filename)
+ 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.50 (2005/05/10)\" />\n")
+ self.file.write("</head>\n")
+ self.file.write("<Scene>\n")
+
+ def writeInline(self):
+ inlines = Blender.Scene.Get()
+ allinlines = len(inlines)
+ if scene != inlines[0]:
+ return
+ else:
+ for i in range(allinlines):
+ nameinline=inlines[i].getName()
+ 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 range(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 range(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 range(nalllines):
+ self.writeIndented(alllines[j] + "\n")
+ self.writeIndented("\n")
+
+ def writeViewpoint(self, thisObj):
+ context = scene.getRenderingContext()
+ ratio = float(context.imageSizeY())/float(context.imageSizeX())
+ lens = (360* (math.atan(ratio *16 / thisObj.data.getLens()) / 3.141593))*(3.141593/180)
+ if lens > 3.14:
+ lens = 3.14
+ # get the camera location, subtract 90 degress from X to orient like X3D does
+ loc = self.rotatePointForVRML(thisObj.loc)
+ rot = [thisObj.RotX - 1.57, thisObj.RotY, thisObj.RotZ]
+ 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(thisObj.name)))
+ self.file.write("description=\"%s\" " % (thisObj.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):
+ if len(world) > 0:
+ mtype = world[0].getMistype()
+ mparam = world[0].getMist()
+ grd = world[0].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):
+ allObj = []
+ allObj = scene.getChildren()
+ headlight = "TRUE"
+ vislimit = 0.0
+ for thisObj in allObj:
+ objType=thisObj.getType()
+ if objType == "Camera":
+ vislimit = thisObj.data.getClipEnd()
+ elif objType == "Lamp":
+ headlight = "FALSE"
+ self.file.write("<NavigationInfo headlight=\"%s\" " % headlight)
+ self.file.write("visibilityLimit=\"%s\" " % (round(vislimit,self.cp)))
+ self.file.write("type=\"EXAMINE, ANY\" avatarSize=\"0.25, 1.75, 0.75\" />\n\n")
+
+ def writeSpotLight(self, object, lamp):
+ safeName = self.cleanStr(object.name)
+ if len(world) > 0:
+ ambi = world[0].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.5,1.0)
+ beamWidth=deg2rad(lamp.spotSize)*.37;
+ cutOffAngle=beamWidth*1.3
+
+ (dx,dy,dz)=self.computeDirection(object)
+ # note -dx seems to equal om[3][0]
+ # note -dz seems to equal om[3][1]
+ # note dy seems to equal om[3][2]
+ om = object.getMatrix()
+
+ location=self.rotVertex(om, (0,0,0));
+ 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, object, lamp):
+ safeName = self.cleanStr(object.name)
+ if len(world) > 0:
+ ambi = world[0].getAmb()
+ ambientIntensity = ((float(ambi[0] + ambi[1] + ambi[2]))/3)/2.5
+ else:
+ ambi = 0
+ ambientIntensity = 0
+
+ intensity=min(lamp.energy/1.5, 1.0)
+ (dx,dy,dz)=self.computeDirection(object)
+ 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, object, lamp):
+ safeName = self.cleanStr(object.name)
+ if len(world) > 0:
+ ambi = world[0].getAmb()
+ ambientIntensity = ((float(ambi[0] + ambi[1] + ambi[2]))/3)/2.5
+ else:
+ ambi = 0
+ ambientIntensity = 0
+ om = object.getMatrix()
+ location=self.rotVertex(om, (0,0,0));
+ intensity=min(lamp.energy/1.5,1.0)
+ radius = lamp.dist
+ 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(intensity,self.cp)))
+ self.file.write("radius=\"%s\" " % radius )
+ self.file.write("location=\"%s %s %s\" />\n\n" % (round(location[0],3), round(location[1],3), round(location[2],3)))
+
+ def writeNode(self, thisObj):
+ objectname=str(thisObj.getName())
+ if objectname in self.namesStandard:
+ return
+ else:
+ (dx,dy,dz)=self.computeDirection(thisObj)
+ om = thisObj.getMatrix()
+ location=self.rotVertex(om, (0,0,0));
+ self.writeIndented("<%s\n" % objectname,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 createDef(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 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, object, normals = 0):
+
+ imageMap={} # set of used images
+ sided={} # 'one':cnt , 'two':cnt
+ vColors={} # 'multi':1
+ meshName = self.cleanStr(object.name)
+ mesh=object.getData()
+ meshME = self.cleanStr(mesh.name)
+ for face in mesh.faces:
+ if face.mode & Blender.NMesh.FaceModes['HALO'] and self.halonode == 0:
+ self.writeIndented("<Billboard axisOfRotation=\"0 0 0\">\n",1)
+ self.halonode = 1
+ elif face.mode & Blender.NMesh.FaceModes['BILLBOARD'] and self.billnode == 0:
+ self.writeIndented("<Billboard axisOfRotation=\"0 1 0\">\n",1)
+ self.billnode = 1
+ elif face.mode & Blender.NMesh.FaceModes['OBCOL'] and self.matonly == 0:
+ self.matonly = 1
+ elif face.mode & Blender.NMesh.FaceModes['SHAREDCOL'] and self.share == 0:
+ self.share = 1
+ elif face.mode & Blender.NMesh.FaceModes['TILES'] and self.tilenode == 0:
+ self.tilenode = 1
+ elif not face.mode & Blender.NMesh.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
+ om = object.getMatrix();
+ location=self.rotVertex(om, (0,0,0));
+ self.writeIndented("<Transform translation=\"%s %s %s\">\n" % (round(location[0],3), round(location[1],3), round(location[2],3)),1)
+ self.writeIndented("<Shape DEF=\"%s\">\n" % meshName,1)
+
+ maters=mesh.materials
+ hasImageTexture=0
+ issmooth=0
+
+ if len(maters) > 0 or mesh.hasFaceUV():
+ self.writeIndented("<Appearance>\n", 1)
+
+ # right now this script can only handle a single material per mesh.
+ if len(maters) >= 1:
+ mat=Blender.Material.Get(maters[0].name)
+ self.writeMaterial(mat, self.cleanStr(maters[0].name,''))
+ if len(maters) > 1:
+ print "Warning: mesh named %s has multiple materials" % meshName
+ print "Warning: only one material per object handled"
+ else:
+ self.writeIndented("<material NULL />\n")
+
+ #-- textures
+ if mesh.hasFaceUV():
+ for face in mesh.faces:
+ if (hasImageTexture == 0) and (face.image):
+ self.writeImageTexture(face.image.name)
+ 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
+
+ # check if object is wireframe only
+ if object.drawType == Blender.Object.DrawTypes.WIRE:
+ # user selected WIRE=2 on the Drawtype=Wire on (F9) Edit page
+ ifStyle="IndexedLineSet"
+ self.wire = 1
+ else:
+ # 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 object.drawType != Blender.Object.DrawTypes.WIRE:
+ if bTwoSided == 1:
+ self.file.write("solid=\"false\" ")
+ else:
+ self.file.write("solid=\"true\" ")
+
+ for face in mesh.faces:
+ if face.smooth:
+ issmooth=1
+ if issmooth==1 and self.wire == 0:
+ creaseAngle=(mesh.getMaxSmoothAngle())*radD
+ self.file.write("creaseAngle=\"%s\" " % (round(creaseAngle,self.cp)))
+
+ #--- output vertexColors
+ if self.share == 1 and self.matonly == 0:
+ self.writeVertexColors(mesh)
+ if object.drawType != Blender.Object.DrawTypes.WIRE:
+ #--- output textureCoordinates if UV texture used
+ if mesh.hasFaceUV():
+ if self.matonly == 1 and self.share == 1:
+ self.writeFaceColors(mesh)
+ elif hasImageTexture == 1:
+ self.writeTextureCoordinates(mesh)
+ #--- output coordinates
+ self.writeCoordinates(object, mesh, meshName)
+
+ self.writingcoords = 1
+ self.writingtexture = 1
+ self.writingcolor = 1
+ self.writeCoordinates(object, mesh, meshName)
+
+ if object.drawType != Blender.Object.DrawTypes.WIRE:
+ #--- output textureCoordinates if UV texture used
+ if mesh.hasFaceUV():
+ if hasImageTexture == 1:
+ self.writeTextureCoordinates(mesh)
+ elif self.matonly == 1 and self.share == 1:
+ self.writeFaceColors(mesh)
+ #--- output vertexColors
+ if self.share == 1 and self.matonly == 0:
+ self.writeVertexColors(mesh)
+ self.matonly = 0
+ self.share = 0
+ self.wire = 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, object, mesh, meshName):
+ meshVertexList = mesh.verts
+
+ # create vertex list and pre rotate -90 degrees X for VRML
+ mm=object.getMatrix()
+ location=self.rotVertex(mm, (0,0,0));
+ if self.writingcoords == 0:
+ self.file.write("coordIndex=\"")
+ coordIndexList=[]
+ for face in mesh.faces:
+ cordStr=""
+ for i in range(len(face)):
+ indx=meshVertexList.index(face[i])
+ cordStr = cordStr + "%s " % indx
+ self.file.write(cordStr + "-1, ")
+ self.file.write("\">\n")
+ else:
+ #-- vertices
+ self.writeIndented("<Coordinate DEF=\"%s%s\" \n" % ("coord_",meshName), 1)
+ self.file.write("\t\t\t\tpoint=\"")
+ for vertex in meshVertexList:
+ v=self.rotVertex(mm, vertex);
+ self.file.write("%s %s %s, " % (round((v[0]-location[0]),self.vp), round((v[1]-location[1]),self.vp), round((v[2]-location[2]),self.vp)))
+ self.file.write("\" />")
+ self.writeIndented("\n", -1)
+
+ def writeTextureCoordinates(self, mesh):
+ texCoordList=[]
+ texIndexList=[]
+ j=0
+
+ for face in mesh.faces:
+ for i in range(len(face)):
+ texIndexList.append(j)
+ texCoordList.append(face.uv[i])
+ j=j+1
+ texIndexList.append(-1)
+ if self.writingtexture == 0:
+ self.file.write("\n\t\t\ttexCoordIndex=\"")
+ texIndxStr=""
+ for i in range(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 range(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 writeVertexColors(self, mesh):
+ if self.writingcolor == 0:
+ self.file.write("colorPerVertex=\"false\" ")
+ else:
+ self.writeIndented("<Color color=\"", 1)
+ for i in range(len(mesh.verts)):
+ c=self.getVertexColorByIndx(mesh,i)
+ if self.verbose > 2:
+ print "Debug: vertex[%d].col r=%d g=%d b=%d" % (i, 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):
+ # 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/2
+ diffuseR, diffuseG, diffuseB = mat.rgbCol[0], mat.rgbCol[1],mat.rgbCol[2]
+ if len(world) > 0:
+ ambi = world[0].getAmb()
+ ambi0, ambi1, ambi2 = ambi[0], ambi[1], ambi[2]
+ else:
+ ambi = 0
+ ambi0, ambi1, ambi2 = 0, 0, 0
+ emisR, emisG, emisB = (diffuseR*mat.emit+ambi0)/4, (diffuseG*mat.emit+ambi1)/4, (diffuseB*mat.emit+ambi2)/4
+
+ shininess = mat.hard/255.0
+ specR = (mat.specCol[0]+0.001)/(1.05/(mat.getSpec()+0.001))
+ specG = (mat.specCol[1]+0.001)/(1.05/(mat.getSpec()+0.001))
+ specB = (mat.specCol[2]+0.001)/(1.05/(mat.getSpec()+0.001))
+ transp = 1-mat.alpha
+
+ 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, name):
+ 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):
+ if len(world) > 0:
+ worldname = world[0].getName()
+ else:
+ return
+ blending = world[0].getSkytype()
+ grd = world[0].getHor()
+ grd0, grd1, grd2 = grd[0], grd[1], grd[2]
+ sky = world[0].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.createDef(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(worldmat)
+ for i in range(alltexture):
+ namemat = worldmat[i].getName()
+ pic = worldmat[i].getImage()
+ if (namemat == "back") and (pic != None):
+ self.file.write("\n\tbackUrl=\"%s\" " % str(pic.getName()))
+ elif (namemat == "bottom") and (pic != None):
+ self.writeIndented("bottomUrl=\"%s\" " % str(pic.getName()))
+ elif (namemat == "front") and (pic != None):
+ self.writeIndented("frontUrl=\"%s\" " % str(pic.getName()))
+ elif (namemat == "left") and (pic != None):
+ self.writeIndented("leftUrl=\"%s\" " % str(pic.getName()))
+ elif (namemat == "right") and (pic != None):
+ self.writeIndented("rightUrl=\"%s\" " % str(pic.getName()))
+ elif (namemat == "top") and (pic != None):
+ self.writeIndented("topUrl=\"%s\" " % str(pic.getName()))
+ self.writeIndented("/>\n\n")
+
+##########################################################
+# export routine
+##########################################################
+
+ def export(self, scene, world, worldmat):
+ print "Info: starting X3D export to " + self.filename + "..."
+ self.writeHeader()
+ self.writeScript()
+ self.writeNavigationInfo(scene)
+ self.writeBackground()
+ self.writeFog()
+ self.proto = 0
+ allObj = []
+ if ARG == 'selected':
+ allObj = Blender.Object.GetSelected()
+ else:
+ allObj = scene.getChildren()
+ self.writeInline()
+ for thisObj in allObj:
+ try:
+ objType=thisObj.getType()
+ objName=thisObj.getName()
+ self.matonly = 0
+ if objType == "Camera":
+ self.writeViewpoint(thisObj)
+ elif objType == "Mesh":
+ self.writeIndexedFaceSet(thisObj, normals = 0)
+ elif objType == "Lamp":
+ lmpName=Lamp.Get(thisObj.data.getName())
+ lmpType=lmpName.getType()
+ if lmpType == Lamp.Types.Lamp:
+ self.writePointLight(thisObj, lmpName)
+ elif lmpType == Lamp.Types.Spot:
+ self.writeSpotLight(thisObj, lmpName)
+ elif lmpType == Lamp.Types.Sun:
+ self.writeDirectionalLight(thisObj, lmpName)
+ else:
+ self.writeDirectionalLight(thisObj, lmpName)
+ elif objType == "Empty" and objName != "Empty":
+ self.writeNode(thisObj)
+ else:
+ #print "Info: Ignoring [%s], object type [%s] not handle yet" % (object.name,object.getType())
+ print ""
+ except AttributeError:
+ print "Error: Unable to get type info for %s" % thisObj.getName()
+ if ARG != 'selected':
+ self.writeScript()
+ self.file.write("\n</Scene>\n</X3D>")
+ 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
+
+ for face in mesh.faces:
+ sidename='';
+ if (face.mode & NMesh.FaceModes.TWOSIDE) == NMesh.FaceModes.TWOSIDE:
+ sidename='two'
+ else:
+ sidename='one'
+
+ if not vColors.has_key('multi'):
+ for face in mesh.faces:
+ if face.col:
+ c=face.col[0]
+ if c.r != 255 and c.g != 255 and c.b !=255:
+ vColors['multi']=1
+
+ if sided.has_key(sidename):
+ sided[sidename]+=1
+ else:
+ sided[sidename]=1
+
+ if face.image:
+ faceName="%s_%s" % (face.image.name, sidename);
+
+ if imageMap.has_key(faceName):
+ imageMap[faceName].append(face)
+ else:
+ imageMap[faceName]=[face.image.name,sidename,face]
+
+ if self.verbose > 2:
+ for faceName in imageMap.keys():
+ ifs=imageMap[faceName]
+ print "Debug: faceName=%s image=%s, solid=%s facecnt=%d" % \
+ (faceName, ifs[0], ifs[1], len(ifs)-2)
+
+ return len(imageMap.keys())
+
+ def faceToString(self,face):
+
+ print "Debug: face.flag=0x%x (bitflags)" % face.flag
+ if face.flag & NMesh.FaceFlags.SELECT == NMesh.FaceFlags.SELECT:
+ print "Debug: face.flag.SELECT=true"
+
+ print "Debug: face.mode=0x%x (bitflags)" % face.mode
+ if (face.mode & NMesh.FaceModes.TWOSIDE) == NMesh.FaceModes.TWOSIDE:
+ print "Debug: face.mode twosided"
+
+ print "Debug: face.transp=0x%x (enum)" % face.transp
+ if face.transp == NMesh.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):
+ for face in mesh.faces:
+ j=0
+ for vertex in face.v:
+ if vertex.index == indx:
+ c=face.col[j]
+ j=j+1
+ return c
+
+ def meshToString(self,mesh):
+ print "Debug: mesh.hasVertexUV=%d" % mesh.hasVertexUV()
+ print "Debug: mesh.hasFaceUV=%d" % mesh.hasFaceUV()
+ 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, object):
+ x,y,z=(0,-1.0,0) # point down
+ ax,ay,az = (object.RotX,object.RotZ,object.RotY)
+
+ # 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
+
+ def rotVertex(self, mm, v):
+ lx,ly,lz=v[0],v[1],v[2]
+ gx=(mm[0][0]*lx + mm[1][0]*ly + mm[2][0]*lz) + mm[3][0]
+ gy=((mm[0][2]*lx + mm[1][2]*ly+ mm[2][2]*lz) + mm[3][2])
+ gz=-((mm[0][1]*lx + mm[1][1]*ly + mm[2][1]*lz) + mm[3][1])
+ rotatedv=[gx,gy,gz]
+ return rotatedv
+
+ # 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 select_file(filename):
+ if pytinst == 1:
+ if exists(filename) and _safeOverwrite:
+ result = Draw.PupMenu("File Already Exists, Overwrite?%t|Yes%x1|No%x0")
+ if(result != 1):
+ return
+
+ if not filename.endswith('.x3d'): filename += '.x3d'
+ wrlexport=VRML2Export(filename)
+ wrlexport.export(scene, world, worldmat)
+
+def createWRLPath():
+ filename = Blender.Get('filename')
+ #print filename
+
+ if filename.find('.') != -1:
+ filename = filename.split('.')[0]
+ filename += ".x3d"
+ #print filename
+
+ return filename
+
+#########################################################
+# main routine
+#########################################################
+
+try:
+ ARG = __script__['arg'] # user selected argument
+except:
+ print "older version"
+
+if Blender.Get('version') < 235:
+ print "Warning: X3D export failed, wrong blender version!"
+ print " You aren't running blender version 2.35 or greater"
+ print " download a newer version from http://blender3d.org/"
+else:
+ Blender.Window.FileSelector(select_file,"Export X3D",createWRLPath())