- removed 2.4x release/scripts

- moved release/io and release/ui into release/scripts/io, ui
- updated scons, cmake, make

When porting 2.4x scripts back, use a command like this so as not to loose the commit history...
 
 svn cp https://svn.blender.org/svnroot/bf-blender/branches/blender2.4/release/scripts/raw_import.py release/scripts/io/import_raw.py
This commit is contained in:
2009-09-28 03:19:52 +00:00
parent 0cbc87b428
commit 2d797f35d8
229 changed files with 7 additions and 94278 deletions

View File

@@ -476,8 +476,8 @@ if env['OURPLATFORM']!='darwin':
dotblenderinstall.append(env.Install(dir=td, source=srcfile))
if env['WITH_BF_PYTHON']:
#-- .blender/scripts, .blender/ui, .blender/io
scriptpaths=['release/scripts', 'release/ui', 'release/io']
#-- .blender/scripts
scriptpaths=['release/scripts']
for scriptpath in scriptpaths:
for dp, dn, df in os.walk(scriptpath):
if '.svn' in dn:

View File

@@ -153,9 +153,6 @@ endif
@echo "----> Copy python infrastructure"
@[ ! -d scripts ] || cp -r scripts $(CONFDIR)/scripts
@echo "----> Copy python UI files"
@[ ! -d ui ] || cp -r ui $(CONFDIR)/ui
ifeq ($(OS),darwin)
@echo "----> Copy python modules"

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,125 +0,0 @@
#!BPY
""" Registration info for Blender menus: <- these words are ignored
Name: 'Axis Orientation Copy'
Blender: 242
Group: 'Object'
Tip: 'Copy local axis orientation of active object to all selected meshes (changes mesh data)'
"""
__author__ = "A Vanpoucke (xand)"
__url__ = ("blenderartists.org", "www.blender.org",
"French Blender support forum, http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender")
__version__ = "2 17/12/05"
__bpydoc__ = """\
This script copies the axis orientation -- X, Y and Z rotations -- of the
active object to all selected meshes.
It's useful to align the orientations of all meshes of a structure, a human
skeleton, for example.
Usage:
Select all mesh objects that need to have their orientations changed
(reminder: keep SHIFT pressed after the first, to add each new one to the
selection), then select the object whose orientation will be copied from and
finally run this script to update the angles.
Notes:<br>
This script changes mesh data: the vertices are transformed.<br>
Before copying the orientation to each object, the script stores its
transformation matrix. Then the angles are copied and after that the object's
vertices are transformed "back" so that they still have the same positions as
before. In other words, the rotations are updated, but you won't notice that
just from looking at the objects.<br>
Checking their X, Y and Z rotation values with "Transform Properties" in
the 3D View's Object menu shows the angles are now the same of the active
object. Or simply look at the transform manipulator handles in local transform
orientation.
"""
# $Id$
#
#----------------------------------------------
# A Vanpoucke (xand)
#from the previous script realignaxis
#----------------------------------------------
# Communiquer les problemes et erreurs sur:
# http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender
# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
# Copyright (C) 2003, 2004: A Vanpoucke
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
from Blender import *
from Blender import Mathutils
from Blender.Mathutils import *
import BPyMessages
def realusers(data):
users = data.users
if data.fakeUser: users -= 1
return users
def main():
scn_obs= Scene.GetCurrent().objects
ob_act = scn_obs.active
scn_obs = scn_obs.context
if not ob_act:
BPyMessages.Error_NoActive()
obs = [(ob, ob.getData(mesh=1)) for ob in scn_obs if ob != ob_act]
for ob, me in obs:
if ob.type != 'Mesh':
Draw.PupMenu("Error%t|Selection must be made up of mesh objects only")
return
if realusers(me) != 1:
Draw.PupMenu("Error%t|Meshes must be single user")
return
if len(obs) < 1:
Draw.PupMenu("Error: you must select at least 2 objects")
return
result = Draw.PupMenu("Copy axis orientation from: " + ob_act.name + " ?%t|OK")
if result == -1:
return
for ob_target, me_target in obs:
if ob_act.rot != ob_target.rot:
rot_target = ob_target.matrixWorld.rotationPart().toEuler().toMatrix()
rot_source = ob_act.matrixWorld.rotationPart().toEuler().toMatrix()
rot_source_inv = rot_source.copy().invert()
tx_mat = rot_target * rot_source_inv
tx_mat.resize4x4()
me_target.transform(tx_mat)
ob_target.rot=ob_act.rot
if __name__ == '__main__':
main()

File diff suppressed because it is too large Load Diff

View File

@@ -1,238 +0,0 @@
#!BPY
""" Registration info for Blender menus:
Name: 'DirectX(.x)...'
Blender: 244
Group: 'Import'
Tip: 'Import from DirectX text file format format.'
"""
# DirectXImporter.py version 1.2
# Copyright (C) 2005 Arben OMARI -- omariarben@everyday.com
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# This script import meshes from DirectX text file format
# Grab the latest version here :www.omariben.too.it
import bpy
import Blender
from Blender import Mesh,Object,Material,Texture,Image,Draw
class xImport:
def __init__(self, filename):
global my_path
self.file = open(filename, "r")
my_path = Blender.sys.dirname(filename)
#
self.lines = [l_split for l in self.file.readlines() for l_split in (' '.join(l.split()),) if l_split]
def Import(self):
lines = self.lines
print "importing into Blender ..."
scene = bpy.data.scenes.active
mesh_indicies = {} # the index of each 'Mesh' is used as the key for those meshes indicies
context_indicies = None # will raise an error if used!
#Get the line of Texture Coords
nr_uv_ind = 0
#Get Materials
nr_fac_mat = 0
i = -1
mat_list = []
tex_list = []
mesh_line_indicies = []
for j, line in enumerate(lines):
l = line.strip()
words = line.split()
if words[0] == "Material" :
#context_indicies["Material"] = j
self.loadMaterials(j, mat_list, tex_list)
elif words[0] == "MeshTextureCoords" :
context_indicies["MeshTextureCoords"] = j
#nr_uv_ind = j
elif words[0] == "MeshMaterialList" :
context_indicies["MeshMaterialList"] = j+2
#nr_fac_mat = j + 2
elif words[0] == "Mesh": # Avoid a second loop
context_indicies = mesh_indicies[j] = {'MeshTextureCoords':0, 'MeshMaterialList':0}
for mesh_index, value in mesh_indicies.iteritems():
mesh = Mesh.New()
self.loadVertices(mesh_index, mesh, value['MeshTextureCoords'], value['MeshMaterialList'], tex_list)
mesh.materials = mat_list[:16]
if value['MeshMaterialList']:
self.loadMeshMaterials(value['MeshMaterialList'], mesh)
scene.objects.new(mesh)
self.file.close()
print "... finished"
#------------------------------------------------------------------------------
# CREATE THE MESH
#------------------------------------------------------------------------------
def loadVertices(self, nr_vr_ind, mesh, nr_uv, nr_fac_mat, tex_list):
v_ind = nr_vr_ind + 1
lin = self.lines[v_ind]
if lin :
lin_c = self.CleanLine(lin)
nr_vert = int((lin_c.split()[0]))
else :
v_ind = nr_vr_ind + 2
lin = self.lines[v_ind]
lin_c = self.CleanLine(lin)
nr_vert = int((lin_c.split()[0]))
#--------------------------------------------------
nr_fac_li = v_ind + nr_vert +1
lin_f = self.lines[nr_fac_li]
if lin_f :
lin_fc = self.CleanLine(lin_f)
nr_face = int((lin_fc.split()[0]))
else :
nr_fac_li = v_ind + nr_vert +1
lin_f = self.lines[nr_fac_li]
lin_fc = self.CleanLine(lin_f)
nr_face = int((lin_fc.split()[0]))
#Get Coordinates
verts_list = [(0,0,0)] # WARNING - DUMMY VERT - solves EEKADOODLE ERROR
for l in xrange(v_ind + 1, (v_ind + nr_vert +1)):
line_v = self.lines[l]
lin_v = self.CleanLine(line_v)
words = lin_v.split()
if len(words)==3:
verts_list.append((float(words[0]),float(words[1]),float(words[2])))
mesh.verts.extend(verts_list)
del verts_list
face_list = []
#Make Faces
i = 0
mesh_verts = mesh.verts
for f in xrange(nr_fac_li + 1, (nr_fac_li + nr_face + 1)):
i += 1
line_f = self.lines[f]
lin_f = self.CleanLine(line_f)
# +1 for dummy vert only!
words = lin_f.split()
if len(words) == 5:
face_list.append((1+int(words[1]), 1+int(words[2]), 1+int(words[3]), 1+int(words[4])))
elif len(words) == 4:
face_list.append((1+int(words[1]), 1+int(words[2]), 1+int(words[3])))
mesh.faces.extend(face_list)
del face_list
if nr_uv :
mesh.faceUV = True
for f in mesh.faces:
fuv = f.uv
for ii, v in enumerate(f):
# _u, _v = self.CleanLine(self.lines[nr_uv + 2 + v.index]).split()
# Use a dummy vert
_u, _v = self.CleanLine(self.lines[nr_uv + 1 + v.index]).split()
fuv[ii].x = float(_u)
fuv[ii].y = float(_v)
if nr_fac_mat :
fac_line = self.lines[nr_fac_mat + i]
fixed_fac = self.CleanLine(fac_line)
w_tex = int(fixed_fac.split()[0])
f.image = tex_list[w_tex]
# remove dummy vert
mesh.verts.delete([0,])
def CleanLine(self,line):
return line.replace(\
";", " ").replace(\
'"', ' ').replace(\
"{", " ").replace(\
"}", " ").replace(\
",", " ").replace(\
"'", " ")
#------------------------------------------------------------------
# CREATE MATERIALS
#------------------------------------------------------------------
def loadMaterials(self, nr_mat, mat_list, tex_list):
def load_image(name):
try:
return Image.Load(Blender.sys.join(my_path,name))
except:
return None
mat = bpy.data.materials.new()
line = self.lines[nr_mat + 1]
fixed_line = self.CleanLine(line)
words = fixed_line.split()
mat.rgbCol = [float(words[0]),float(words[1]),float(words[2])]
mat.setAlpha(float(words[3]))
mat_list.append(mat)
l = self.lines[nr_mat + 5]
fix_3_line = self.CleanLine(l)
tex_n = fix_3_line.split()
if tex_n and tex_n[0] == "TextureFilename" :
if len(tex_n) > 1:
tex_list.append(load_image(tex_n[1]))
if len(tex_n) <= 1 :
l_succ = self.lines[nr_mat + 6]
fix_3_succ = self.CleanLine(l_succ)
tex_n_succ = fix_3_succ.split()
tex_list.append(load_image(tex_n_succ[0]))
else :
tex_list.append(None) # no texture for this index
return mat_list, tex_list
#------------------------------------------------------------------
# SET MATERIALS
#------------------------------------------------------------------
def loadMeshMaterials(self, nr_fc_mat, mesh):
for face in mesh.faces:
nr_fc_mat += 1
line = self.lines[nr_fc_mat]
fixed_line = self.CleanLine(line)
wrd = fixed_line.split()
mat_idx = int(wrd[0])
face.mat = mat_idx
#------------------------------------------------------------------
# MAIN
#------------------------------------------------------------------
def my_callback(filename):
if not filename.lower().endswith('.x'): print "Not an .x file"
ximport = xImport(filename)
ximport.Import()
arg = __script__['arg']
if __name__ == '__main__':
Blender.Window.FileSelector(my_callback, "Import DirectX", "*.x")
#my_callback('/fe/x/directxterrain.x')
#my_callback('/fe/x/Male_Normal_MAX.X')
#my_callback('/fe/x/male_ms3d.x')

View File

@@ -1,523 +0,0 @@
#!BPY
"""
Name: 'ID Property Browser'
Blender: 242
Group: 'Help'
Tooltip: 'Browse ID properties'
"""
__author__ = "Joe Eagar"
__version__ = "0.3.108"
__email__ = "joeedh@gmail.com"
__bpydoc__ = """\
Allows browsing, creating and editing of ID Properties
for various ID block types such as mesh, scene, object,
etc.
"""
# --------------------------------------------------------------------------
# ID Property Browser.
# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
from Blender import *
from Blender.BGL import *
from Blender.Types import IDGroupType, IDArrayType
import Blender
def IsInRectWH(mx, my, x, y, wid, hgt):
if mx >= x and mx <= x + wid:
if my >= y and my <= y + hgt:
return 1
return 0
Button_Back = 1
Button_New = 2
Button_MatMenu = 3
Button_TypeMenu = 4
ButStart = 55
IDP_String = 0
IDP_Int = 1
IDP_Float = 2
IDP_Array = 5
IDP_Group = 6
ButDelStart = 255
#max limit for string input button
strmax = 100
State_Normal = 0
State_InArray = 1
#IDTypeModules entries are of form [module, active_object_index, module_name]
IDTypeModules = [[Scene, 0, "Scenes"], [Object, 0, "Objects"], [Mesh, 0, "Meshes"]]
IDTypeModules += [[Material, 0, "Materials"], [Texture, 0, "Textures"]]
IDTypeModules += [[Image, 0, "Images"]]
class IDArrayBrowser:
array = 0
parentbrowser = 0
buts = 0
def __init__(self):
self.buts = []
def Draw(self):
pb = self.parentbrowser
x = pb.x
y = pb.y
width = pb.width
height = pb.height
pad = pb.pad
itemhgt = pb.itemhgt
cellwid = 65
y = y + height - itemhgt - pad
Draw.PushButton("Back", Button_Back, x, y, 40, 20)
y -= itemhgt + pad
self.buts = []
Draw.BeginAlign()
for i in xrange(len(self.array)):
st = ""
if type(self.array[0]) == float:
st = "%.5f" % self.array[i]
else: st = str(self.array[i])
b = Draw.String("", ButStart+i, x, y, cellwid, itemhgt, st, 30)
self.buts.append(b)
x += cellwid + pad
if x + cellwid + pad > width:
x = 0
y -= itemhgt + pad
Draw.EndAlign()
def Button(self, bval):
if bval == Button_Back:
self.parentbrowser.state = State_Normal
self.parentbrowser.array = 0
self.buts = []
Draw.Draw()
self.array = 0
elif bval >= ButStart:
i = bval - ButStart
st = self.buts[i].val
n = 0
if type(self.array[0]) == float:
try:
n = int(st)
except:
return
elif type(self.array[0]) == int:
try:
n = float(st)
except:
return
self.array[i] = n
Draw.Draw()
def Evt(self, evt, val):
if evt == Draw.ESCKEY:
Draw.Exit()
class IDPropertyBrowser:
width = 0
height = 0
x = 0
y = 0
scrollx = 0
scrolly = 0
itemhgt = 22
pad = 2
group = 0
parents = 0 #list stack of parent groups
active_item = -1
mousecursor = 0
_i = 0
buts = []
state = 0
array = 0
prop = 0
IDList = 0
idindex = 0
idblock = 0
type = 0 # attach buildin type() method to class
# since oddly it's not available to button
# callbacks! EEK! :(
def __init__(self, idgroup, mat, x, y, wid, hgt):
self.group = idgroup
self.prop = idgroup
self.x = x
self.y = y
self.width = wid
self.height = hgt
self.mousecursor = [0, 0]
self.parents = []
self.idblock = mat
self.type = type
def DrawBox(self, glmode, x, y, width, height):
glBegin(glmode)
glVertex2f(x, y)
glVertex2f(x+width, y)
glVertex2f(x+width, y+height)
glVertex2f(x, y+height)
glEnd()
def Draw(self):
global IDTypeModules
#first draw outlining box :)
glColor3f(0, 0, 0)
self.DrawBox(GL_LINE_LOOP, self.x, self.y, self.width, self.height)
itemhgt = self.itemhgt
pad = self.pad
x = self.x
y = self.y + self.height - itemhgt - pad
if self.state == State_InArray:
self.array.Draw()
return
plist = []
self.buts = []
for p in self.group.iteritems():
plist.append(p)
#-------do top buttons----------#
Draw.BeginAlign()
Draw.PushButton("New", Button_New, x, y, 40, 20)
x += 40 + pad
#do the menu button for all materials
st = ""
blocks = IDTypeModules[self.IDList][0].Get()
i = 1
mi = 0
for m in blocks:
if m.name == self.idblock.name:
mi = i
st += m.name + " %x" + str(i) + "|"
i += 1
self.menubut = Draw.Menu(st, Button_MatMenu, x, y, 100, 20, mi)
x += 100 + pad
st = ""
i = 0
for e in IDTypeModules:
st += e[2] + " %x" + str(i+1) + "|"
i += 1
cur = self.IDList + 1
self.idmenu = Draw.Menu(st, Button_TypeMenu, x, y, 100, 20, cur)
x = self.x
y -= self.itemhgt + self.pad
Draw.EndAlign()
#-----------do property items---------#
i = 0
while y > self.y - 20 - pad and i < len(plist):
k = plist[i][0]
p = plist[i][1]
if i == self.active_item:
glColor3f(0.5, 0.4, 0.3)
self.DrawBox(GL_POLYGON, x+pad, y, self.width-pad*2, itemhgt)
glColor3f(0, 0, 0)
self.DrawBox(GL_LINE_LOOP, x+pad, y, self.width-pad*2, itemhgt)
glRasterPos2f(x+pad*2, y+5)
Draw.Text(str(k)) #str(self.mousecursor) + " " + str(self.active_item)) #p.name)
tlen = Draw.GetStringWidth(str(k))
type_p = type(p)
if type_p == str:
b = Draw.String("", ButStart+i, x+pad*5+tlen, y, 200, itemhgt, p, strmax)
self.buts.append(b)
elif type_p in [int, float]:
#only do precision to 5 points on floats
st = ""
if type_p == float:
st = "%.5f" % p
else: st = str(p)
b = Draw.String("", ButStart+i, x+pad*5+tlen, y, 75, itemhgt, st, strmax)
self.buts.append(b)
else:
glRasterPos2f(x+pad*2 +tlen+10, y+5)
if type_p == Types.IDArrayType:
Draw.Text('(array, click to edit)')
elif type_p == Types.IDGroupType:
Draw.Text('(group, click to edit)')
self.buts.append(None)
Draw.PushButton("Del", ButDelStart+i, x+self.width-35, y, 30, 20)
i += 1
y -= self.itemhgt + self.pad
if len(self.parents) != 0:
Draw.PushButton("Back", Button_Back, x, y, 40, 20)
x = x + 40 + pad
def SetActive(self):
m = self.mousecursor
itemhgt = self.itemhgt
pad = self.pad
x = self.x + pad
y = self.y + self.height - itemhgt - pad - itemhgt
plist = []
for p in self.group.iteritems():
plist.append(p)
self.active_item = -1
i = 0
while y > self.y and i < len(plist):
p = plist[i]
if IsInRectWH(m[0], m[1], x, y, self.width-pad, itemhgt):
self.active_item = i
i += 1
y -= self.itemhgt + self.pad
def EventIn(self, evt, val):
if self.state == State_InArray:
self.array.Evt(evt, val)
if evt == Draw.ESCKEY:
Draw.Exit()
if evt == Draw.MOUSEX or evt == Draw.MOUSEY:
size = Buffer(GL_FLOAT, 4)
glGetFloatv(GL_SCISSOR_BOX, size)
if evt == Draw.MOUSEX:
self.mousecursor[0] = val - size[0]
else:
self.mousecursor[1] = val - size[1]
del size
self.SetActive()
self._i += 1
if self._i == 5:
Draw.Draw()
self._i = 0
if evt == Draw.LEFTMOUSE and val == 1:
plist = list(self.group.iteritems())
a = self.active_item
if a >= 0 and a < len(plist):
p = plist[a]
basictypes = [IDGroupType, float, str, int]
if type(p[1]) == IDGroupType:
self.parents.append(self.group)
self.group = p[1]
self.active_item = -1
Draw.Draw()
elif type(p[1]) == IDArrayType:
self.array = IDArrayBrowser()
self.array.array = p[1]
self.array.parentbrowser = self
self.state = State_InArray
Draw.Draw()
if evt == Draw.TKEY and val == 1:
try:
self.prop['float'] = 0.0
self.prop['int'] = 1
self.prop['string'] = "hi!"
self.prop['float array'] = [0, 0, 1.0, 0]
self.prop['int array'] = [0, 0, 0, 0]
self.prop.data['a subgroup'] = {"int": 0, "float": 0.0, "anothergroup": {"a": 0.0, "intarr": [0, 0, 0, 0]}}
Draw.Draw()
except:
Draw.PupMenu("Can only do T once per block, the test names are already taken!")
def Button(self, bval):
global IDTypeModules
if self.state == State_InArray:
self.array.Button(bval)
return
if bval == Button_MatMenu:
global IDTypeModules
val = self.idindex = self.menubut.val - 1
i = self.IDList
block = IDTypeModules[i][0].Get()[val]
self.idblock = block
self.prop = block.properties
self.group = self.prop
self.active_item = -1
self.parents = []
Draw.Draw()
if bval == Button_TypeMenu:
i = IDTypeModules[self.idmenu.val-1]
if len(i[0].Get()) == 0:
Draw.PupMenu("Error%t|There are no " + i[2] + "!")
return
IDTypeModules[self.IDList][1] = self.idindex
self.IDList = self.idmenu.val-1
val = self.idindex = IDTypeModules[self.IDList][1]
i = self.IDList
block = IDTypeModules[i][0].Get()[val]
self.idblock = block
self.prop = block.properties
self.group = self.prop
self.active_item = -1
self.parents = []
Draw.Draw()
if bval >= ButDelStart:
plist = [p for p in self.group]
prop = plist[bval - ButDelStart]
del self.group[prop]
Draw.Draw()
elif bval >= ButStart:
plist = list(self.group.iteritems())
prop = plist[bval - ButStart]
print prop
if self.type(prop[1]) == str:
self.group[prop[0]] = self.buts[bval - ButStart].val
elif self.type(prop[1]) == int:
i = self.buts[bval - ButStart].val
try:
i = int(i)
self.group[prop[0]] = i
except:
Draw.Draw()
return
Draw.Draw()
elif self.type(prop[1]) == float:
f = self.buts[bval - ButStart].val
try:
f = float(f)
self.group[prop[0]] = f
except:
Draw.Draw()
return
Draw.Draw()
elif bval == Button_Back:
self.group = self.parents[len(self.parents)-1]
self.parents.pop(len(self.parents)-1)
Draw.Draw()
elif bval == Button_New:
name = Draw.Create("untitled")
stype = Draw.Create(0)
gtype = Draw.Create(0)
ftype = Draw.Create(0)
itype = Draw.Create(0)
atype = Draw.Create(0)
block = []
block.append(("Name: ", name, 0, 30, "Click to type in the name of the new ID property"))
block.append("Type")
block.append(("String", stype))
block.append(("Subgroup", gtype))
block.append(("Float", ftype))
block.append(("Int", itype))
block.append(("Array", atype))
retval = Blender.Draw.PupBlock("New IDProperty", block)
if retval == 0: return
name = name.val
i = 1
stop = 0
while stop == 0:
stop = 1
for p in self.group:
if p == name:
d = name.rfind(".")
if d != -1:
name = name[:d]
name = name + "." + str(i).zfill(3)
i += 1
stop = 0
type = "String"
if stype.val:
self.group[name] = ""
elif gtype.val:
self.group[name] = {}
elif ftype.val:
self.group[name] = 0.0
elif itype.val:
self.group[name] = 0 #newProperty("Int", name, 0)
elif atype.val:
arrfloat = Draw.Create(1)
arrint = Draw.Create(0)
arrlen = Draw.Create(3)
block = []
block.append("Type")
block.append(("Float", arrfloat, "Make a float array"))
block.append(("Int", arrint, "Make an integer array"))
block.append(("Len", arrlen, 2, 200))
if Blender.Draw.PupBlock("Array Properties", block):
if arrfloat.val:
tmpl = 0.0
elif arrint.val:
tmpl = 0
else:
return
self.group[name] = [tmpl] * arrlen.val
def Go(self):
Draw.Register(self.Draw, self.EventIn, self.Button)
scenes = Scene.Get()
size = Window.GetAreaSize()
browser = IDPropertyBrowser(scenes[0].properties, scenes[0], 2, 2, size[0], size[1])
browser.Go()
#a = prop.newProperty("String", "hwello!", "bleh")
#b = prop.newProperty("Group", "subgroup")
#for p in prop:
#print p.name

View File

@@ -1,828 +0,0 @@
#!BPY
""" Registration info for Blender menus:
Name: 'AC3D (.ac)...'
Blender: 243
Group: 'Export'
Tip: 'Export selected meshes to AC3D (.ac) format'
"""
__author__ = "Willian P. Germano"
__url__ = ("blender", "blenderartists.org", "AC3D's homepage, http://www.ac3d.org",
"PLib 3d gaming lib, http://plib.sf.net")
__version__ = "2.44 2007-05-05"
__bpydoc__ = """\
This script exports selected Blender meshes to AC3D's .ac file format.
AC3D is a simple commercial 3d modeller also built with OpenGL.
The .ac file format is an easy to parse text format well supported,
for example, by the PLib 3d gaming library (AC3D 3.x).
Supported:<br>
UV-textured meshes with hierarchy (grouping) information.
Missing:<br>
The 'url' tag, specific to AC3D. It is easy to add by hand to the exported
file, if needed.
Known issues:<br>
The ambient and emit data we can retrieve from Blender are single values,
that this script copies to R, G, B, giving shades of gray.<br>
Loose edges (lines) receive the first material found in the mesh, if any, or a default white material.<br>
In AC3D 4 "compatibility mode":<br>
- shininess of materials is taken from the shader specularity value in Blender, mapped from [0.0, 2.0] to [0, 128];<br>
- crease angle is exported, but in Blender it is limited to [1, 80], since there are other more powerful ways to control surface smoothing. In AC3D 4.0 crease's range is [0.0, 180.0];
Config Options:<br>
toggle:<br>
- AC3D 4 mode: unset it to export without the 'crease' tag that was
introduced with AC3D 4.0 and with the old material handling;<br>
- global coords: transform all vertices of all meshes to global coordinates;<br>
- skip data: set it if you don't want mesh names (ME:, not OB: field)
to be exported as strings for AC's "data" tags (19 chars max);<br>
- rgb mirror color can be exported as ambient and/or emissive if needed,
since Blender handles these differently;<br>
- default mat: a default (white) material is added if some mesh was
left without mats -- it's better to always add your own materials;<br>
- no split: don't split meshes (see above);<br>
- set texture dir: override the actual textures path with a given default
path (or simply export the texture names, without dir info, if the path is
empty);<br>
- per face 1 or 2 sided: override the "Double Sided" button that defines this behavior per whole mesh in favor of the UV Face Select mode "twosided" per face atribute;<br>
- only selected: only consider selected objects when looking for meshes
to export (read notes below about tokens, too);<br>
strings:<br>
- export dir: default dir to export to;<br>
- texture dir: override textures path with this path if 'set texture dir'
toggle is "on".
Notes:<br>
This version updates:<br>
- modified meshes are correctly exported, no need to apply the modifiers in Blender;<br>
- correctly export each used material, be it assigned to the object or to its mesh data;<br>
- exporting lines (edges) is again supported; color comes from first material found in the mesh, if any, or a default white one.<br>
- there's a new option to choose between exporting meshes with transformed (global) coordinates or local ones;<br>
Multiple textures per mesh are supported (mesh gets split);<br>
Parents are exported as a group containing both the parent and its children;<br>
Start mesh object names (OB: field) with "!" or "#" if you don't want them to be exported;<br>
Start mesh object names (OB: field) with "=" or "$" to prevent them from being split (meshes with multiple textures or both textured and non textured faces are split unless this trick is used or the "no split" option is set.
"""
# $Id$
#
# --------------------------------------------------------------------------
# AC3DExport version 2.44
# Program versions: Blender 2.42+ and AC3Db files (means version 0xb)
# new: updated for new Blender version and Mesh module; supports lines (edges) again;
# option to export vertices transformed to global coordinates or not; now the modified
# (by existing mesh modifiers) mesh is exported; materials are properly exported, no
# matter if each of them is linked to the mesh or to the object. New (2.43.1): loose
# edges use color of first material found in the mesh, if any.
# --------------------------------------------------------------------------
# Thanks: Steve Baker for discussions and inspiration; for testing, bug
# reports, suggestions, patches: David Megginson, Filippo di Natale,
# Franz Melchior, Campbell Barton, Josh Babcock, Ralf Gerlich, Stewart Andreason.
# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
# Copyright (C) 2004-2007: Willian P. Germano, wgermano _at_ ig.com.br
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# --------------------------------------------------------------------------
import Blender
from Blender import Object, Mesh, Material, Image, Mathutils, Registry
from Blender import sys as bsys
# Globals
REPORT_DATA = {
'main': [],
'errors': [],
'warns': [],
'nosplit': [],
'noexport': []
}
TOKENS_DONT_EXPORT = ['!', '#']
TOKENS_DONT_SPLIT = ['=', '$']
MATIDX_ERROR = 0
# flags:
LOOSE = Mesh.EdgeFlags['LOOSE']
FACE_TWOSIDED = Mesh.FaceModes['TWOSIDE']
MESH_TWOSIDED = Mesh.Modes['TWOSIDED']
REG_KEY = 'ac3d_export'
# config options:
GLOBAL_COORDS = True
SKIP_DATA = False
MIRCOL_AS_AMB = False
MIRCOL_AS_EMIS = False
ADD_DEFAULT_MAT = True
SET_TEX_DIR = True
TEX_DIR = ''
AC3D_4 = True # export crease value, compatible with AC3D 4 loaders
NO_SPLIT = False
ONLY_SELECTED = True
EXPORT_DIR = ''
PER_FACE_1_OR_2_SIDED = True
tooltips = {
'GLOBAL_COORDS': "transform all vertices of all meshes to global coordinates",
'SKIP_DATA': "don't export mesh names as data fields",
'MIRCOL_AS_AMB': "export mirror color as ambient color",
'MIRCOL_AS_EMIS': "export mirror color as emissive color",
'ADD_DEFAULT_MAT': "always add a default white material",
'SET_TEX_DIR': "don't export default texture paths (edit also \"tex dir\")",
'EXPORT_DIR': "default / last folder used to export .ac files to",
'TEX_DIR': "(see \"set tex dir\") dir to prepend to all exported texture names (leave empty for no dir)",
'AC3D_4': "compatibility mode, adds 'crease' tag and slightly better material support",
'NO_SPLIT': "don't split meshes with multiple textures (or both textured and non textured polygons)",
'ONLY_SELECTED': "export only selected objects",
'PER_FACE_1_OR_2_SIDED': "override \"Double Sided\" button in favor of per face \"twosided\" attribute (UV Face Select mode)"
}
def update_RegistryInfo():
d = {}
d['SKIP_DATA'] = SKIP_DATA
d['MIRCOL_AS_AMB'] = MIRCOL_AS_AMB
d['MIRCOL_AS_EMIS'] = MIRCOL_AS_EMIS
d['ADD_DEFAULT_MAT'] = ADD_DEFAULT_MAT
d['SET_TEX_DIR'] = SET_TEX_DIR
d['TEX_DIR'] = TEX_DIR
d['AC3D_4'] = AC3D_4
d['NO_SPLIT'] = NO_SPLIT
d['EXPORT_DIR'] = EXPORT_DIR
d['ONLY_SELECTED'] = ONLY_SELECTED
d['PER_FACE_1_OR_2_SIDED'] = PER_FACE_1_OR_2_SIDED
d['tooltips'] = tooltips
d['GLOBAL_COORDS'] = GLOBAL_COORDS
Registry.SetKey(REG_KEY, d, True)
# Looking for a saved key in Blender.Registry dict:
rd = Registry.GetKey(REG_KEY, True)
if rd:
try:
AC3D_4 = rd['AC3D_4']
SKIP_DATA = rd['SKIP_DATA']
MIRCOL_AS_AMB = rd['MIRCOL_AS_AMB']
MIRCOL_AS_EMIS = rd['MIRCOL_AS_EMIS']
ADD_DEFAULT_MAT = rd['ADD_DEFAULT_MAT']
SET_TEX_DIR = rd['SET_TEX_DIR']
TEX_DIR = rd['TEX_DIR']
EXPORT_DIR = rd['EXPORT_DIR']
ONLY_SELECTED = rd['ONLY_SELECTED']
NO_SPLIT = rd['NO_SPLIT']
PER_FACE_1_OR_2_SIDED = rd['PER_FACE_1_OR_2_SIDED']
GLOBAL_COORDS = rd['GLOBAL_COORDS']
except KeyError: update_RegistryInfo()
else:
update_RegistryInfo()
VERBOSE = True
CONFIRM_OVERWRITE = True
# check General scripts config key for default behaviors
rd = Registry.GetKey('General', True)
if rd:
try:
VERBOSE = rd['verbose']
CONFIRM_OVERWRITE = rd['confirm_overwrite']
except: pass
# The default material to be used when necessary (see ADD_DEFAULT_MAT)
DEFAULT_MAT = \
'MATERIAL "DefaultWhite" rgb 1 1 1 amb 1 1 1 emis 0 0 0 \
spec 0.5 0.5 0.5 shi 64 trans 0'
# This transformation aligns Blender and AC3D coordinate systems:
BLEND_TO_AC3D_MATRIX = Mathutils.Matrix([1,0,0,0], [0,0,-1,0], [0,1,0,0], [0,0,0,1])
def Round_s(f):
"Round to default precision and turn value to a string"
r = round(f,6) # precision set to 10e-06
if r == int(r):
return str(int(r))
else:
return str(r)
def transform_verts(verts, m):
vecs = []
for v in verts:
x, y, z = v.co
vec = Mathutils.Vector([x, y, z, 1])
vecs.append(vec*m)
return vecs
def get_loose_edges(mesh):
loose = LOOSE
return [e for e in mesh.edges if e.flag & loose]
# ---
# meshes with more than one texture assigned
# are split and saved as these foomeshes
class FooMesh:
class FooVert:
def __init__(self, v):
self.v = v
self.index = 0
class FooFace:
def __init__(self, foomesh, f):
self.f = f
foov = foomesh.FooVert
self.v = [foov(f.v[0]), foov(f.v[1])]
len_fv = len(f.v)
if len_fv > 2 and f.v[2]:
self.v.append(foov(f.v[2]))
if len_fv > 3 and f.v[3]: self.v.append(foov(f.v[3]))
def __getattr__(self, attr):
if attr == 'v': return self.v
return getattr(self.f, attr)
def __len__(self):
return len(self.f)
def __init__(self, tex, faces, mesh):
self.name = mesh.name
self.mesh = mesh
self.looseEdges = []
self.faceUV = mesh.faceUV
self.degr = mesh.degr
vidxs = [0]*len(mesh.verts)
foofaces = []
for f in faces:
foofaces.append(self.FooFace(self, f))
for v in f.v:
if v: vidxs[v.index] = 1
i = 0
fooverts = []
for v in mesh.verts:
if vidxs[v.index]:
fooverts.append(v)
vidxs[v.index] = i
i += 1
for f in foofaces:
for v in f.v:
if v: v.index = vidxs[v.v.index]
self.faces = foofaces
self.verts = fooverts
class AC3DExport: # the ac3d exporter part
def __init__(self, scene_objects, file):
global ARG, SKIP_DATA, ADD_DEFAULT_MAT, DEFAULT_MAT
header = 'AC3Db'
self.file = file
self.buf = ''
self.mbuf = []
self.mlist = []
world_kids = 0
parents_list = self.parents_list = []
kids_dict = self.kids_dict = {}
objs = []
exp_objs = self.exp_objs = []
tree = {}
file.write(header+'\n')
objs = \
[o for o in scene_objects if o.type in ['Mesh', 'Empty']]
# create a tree from parents to children objects
for obj in objs[:]:
parent = obj.parent
lineage = [obj]
while parent:
parents_list.append(parent.name)
obj = parent
parent = parent.getParent()
lineage.insert(0, obj)
d = tree
for i in xrange(len(lineage)):
lname = lineage[i].getType()[:2] + lineage[i].name
if lname not in d.keys():
d[lname] = {}
d = d[lname]
# traverse the tree to get an ordered list of names of objects to export
self.traverse_dict(tree)
world_kids = len(tree.keys())
# get list of objects to export, start writing the .ac file
objlist = [Object.Get(name) for name in exp_objs]
meshlist = [o for o in objlist if o.type == 'Mesh']
# create a temporary mesh to hold actual (modified) mesh data
TMP_mesh = Mesh.New('tmp_for_ac_export')
# write materials
self.MATERIALS(meshlist, TMP_mesh)
mbuf = self.mbuf
if not mbuf or ADD_DEFAULT_MAT:
mbuf.insert(0, "%s\n" % DEFAULT_MAT)
mbuf = "".join(mbuf)
file.write(mbuf)
file.write('OBJECT world\nkids %s\n' % world_kids)
# write the objects
for obj in objlist:
self.obj = obj
objtype = obj.type
objname = obj.name
kidsnum = kids_dict[objname]
# A parent plus its children are exported as a group.
# If the parent is a mesh, its rot and loc are exported as the
# group rot and loc and the mesh (w/o rot and loc) is added to the group.
if kidsnum:
self.OBJECT('group')
self.name(objname)
if objtype == 'Mesh':
kidsnum += 1
if not GLOBAL_COORDS:
localmatrix = obj.getMatrix('localspace')
if not obj.getParent():
localmatrix *= BLEND_TO_AC3D_MATRIX
self.rot(localmatrix.rotationPart())
self.loc(localmatrix.translationPart())
self.kids(kidsnum)
if objtype == 'Mesh':
mesh = TMP_mesh # temporary mesh to hold actual (modified) mesh data
mesh.getFromObject(objname)
self.mesh = mesh
if mesh.faceUV:
meshes = self.split_mesh(mesh)
else:
meshes = [mesh]
if len(meshes) > 1:
if NO_SPLIT or self.dont_split(objname):
self.export_mesh(mesh, ob)
REPORT_DATA['nosplit'].append(objname)
else:
self.OBJECT('group')
self.name(objname)
self.kids(len(meshes))
counter = 0
for me in meshes:
self.export_mesh(me, obj,
name = '%s_%s' % (obj.name, counter), foomesh = True)
self.kids()
counter += 1
else:
self.export_mesh(mesh, obj)
self.kids()
def traverse_dict(self, d):
kids_dict = self.kids_dict
exp_objs = self.exp_objs
keys = d.keys()
keys.sort() # sort for predictable output
keys.reverse()
for k in keys:
objname = k[2:]
klen = len(d[k])
kids_dict[objname] = klen
if self.dont_export(objname):
d.pop(k)
parent = Object.Get(objname).getParent()
if parent: kids_dict[parent.name] -= 1
REPORT_DATA['noexport'].append(objname)
continue
if klen:
self.traverse_dict(d[k])
exp_objs.insert(0, objname)
else:
if k.find('Em', 0) == 0: # Empty w/o children
d.pop(k)
parent = Object.Get(objname).getParent()
if parent: kids_dict[parent.name] -= 1
else:
exp_objs.insert(0, objname)
def dont_export(self, name): # if name starts with '!' or '#'
length = len(name)
if length >= 1:
if name[0] in TOKENS_DONT_EXPORT: # '!' or '#' doubled (escaped): export
if length > 1 and name[1] == name[0]:
return 0
return 1
def dont_split(self, name): # if name starts with '=' or '$'
length = len(name)
if length >= 1:
if name[0] in TOKENS_DONT_SPLIT: # '=' or '$' doubled (escaped): split
if length > 1 and name[1] == name[0]:
return 0
return 1
def split_mesh(self, mesh):
tex_dict = {0:[]}
for f in mesh.faces:
if f.image:
if not f.image.name in tex_dict: tex_dict[f.image.name] = []
tex_dict[f.image.name].append(f)
else: tex_dict[0].append(f)
keys = tex_dict.keys()
len_keys = len(keys)
if not tex_dict[0]:
len_keys -= 1
tex_dict.pop(0)
keys.remove(0)
elif len_keys > 1:
lines = []
anyimgkey = [k for k in keys if k != 0][0]
for f in tex_dict[0]:
if len(f.v) < 3:
lines.append(f)
if len(tex_dict[0]) == len(lines):
for l in lines:
tex_dict[anyimgkey].append(l)
len_keys -= 1
tex_dict.pop(0)
if len_keys > 1:
foo_meshes = []
for k in keys:
faces = tex_dict[k]
foo_meshes.append(FooMesh(k, faces, mesh))
foo_meshes[0].edges = get_loose_edges(mesh)
return foo_meshes
return [mesh]
def export_mesh(self, mesh, obj, name = None, foomesh = False):
file = self.file
self.OBJECT('poly')
if not name: name = obj.name
self.name(name)
if not SKIP_DATA:
meshname = obj.getData(name_only = True)
self.data(len(meshname), meshname)
if mesh.faceUV:
texline = self.texture(mesh.faces)
if texline: file.write(texline)
if AC3D_4:
self.crease(mesh.degr)
# If exporting using local coordinates, children object coordinates should not be
# transformed to ac3d's coordinate system, since that will be accounted for in
# their topmost parents (the parents w/o parents) transformations.
if not GLOBAL_COORDS:
# We hold parents in a list, so they also don't get transformed,
# because for each parent we create an ac3d group to hold both the
# parent and its children.
if obj.name not in self.parents_list:
localmatrix = obj.getMatrix('localspace')
if not obj.getParent():
localmatrix *= BLEND_TO_AC3D_MATRIX
self.rot(localmatrix.rotationPart())
self.loc(localmatrix.translationPart())
matrix = None
else:
matrix = obj.getMatrix() * BLEND_TO_AC3D_MATRIX
self.numvert(mesh.verts, matrix)
self.numsurf(mesh, foomesh)
def MATERIALS(self, meshlist, me):
for meobj in meshlist:
me.getFromObject(meobj)
mats = me.materials
mbuf = []
mlist = self.mlist
for m in mats:
if not m: continue
name = m.name
if name not in mlist:
mlist.append(name)
M = Material.Get(name)
material = 'MATERIAL "%s"' % name
mirCol = "%s %s %s" % (Round_s(M.mirCol[0]), Round_s(M.mirCol[1]),
Round_s(M.mirCol[2]))
rgb = "rgb %s %s %s" % (Round_s(M.R), Round_s(M.G), Round_s(M.B))
ambval = Round_s(M.amb)
amb = "amb %s %s %s" % (ambval, ambval, ambval)
spec = "spec %s %s %s" % (Round_s(M.specCol[0]),
Round_s(M.specCol[1]), Round_s(M.specCol[2]))
if AC3D_4:
emit = Round_s(M.emit)
emis = "emis %s %s %s" % (emit, emit, emit)
shival = int(M.spec * 64)
else:
emis = "emis 0 0 0"
shival = 72
shi = "shi %s" % shival
trans = "trans %s" % (Round_s(1 - M.alpha))
if MIRCOL_AS_AMB:
amb = "amb %s" % mirCol
if MIRCOL_AS_EMIS:
emis = "emis %s" % mirCol
mbuf.append("%s %s %s %s %s %s %s\n" \
% (material, rgb, amb, emis, spec, shi, trans))
self.mlist = mlist
self.mbuf.append("".join(mbuf))
def OBJECT(self, type):
self.file.write('OBJECT %s\n' % type)
def name(self, name):
if name[0] in TOKENS_DONT_EXPORT or name[0] in TOKENS_DONT_SPLIT:
if len(name) > 1: name = name[1:]
self.file.write('name "%s"\n' % name)
def kids(self, num = 0):
self.file.write('kids %s\n' % num)
def data(self, num, str):
self.file.write('data %s\n%s\n' % (num, str))
def texture(self, faces):
tex = ""
for f in faces:
if f.image:
tex = f.image.name
break
if tex:
image = Image.Get(tex)
texfname = image.filename
if SET_TEX_DIR:
texfname = bsys.basename(texfname)
if TEX_DIR:
texfname = bsys.join(TEX_DIR, texfname)
buf = 'texture "%s"\n' % texfname
xrep = image.xrep
yrep = image.yrep
buf += 'texrep %s %s\n' % (xrep, yrep)
self.file.write(buf)
def rot(self, matrix):
rot = ''
not_I = 0 # not identity
matstr = []
for i in [0, 1, 2]:
r = map(Round_s, matrix[i])
not_I += (r[0] != '0')+(r[1] != '0')+(r[2] != '0')
not_I -= (r[i] == '1')
for j in [0, 1, 2]:
matstr.append(' %s' % r[j])
if not_I: # no need to write identity
self.file.write('rot%s\n' % "".join(matstr))
def loc(self, loc):
loc = map(Round_s, loc)
if loc != ['0', '0', '0']: # no need to write default
self.file.write('loc %s %s %s\n' % (loc[0], loc[1], loc[2]))
def crease(self, crease):
self.file.write('crease %f\n' % crease)
def numvert(self, verts, matrix):
file = self.file
nvstr = []
nvstr.append("numvert %s\n" % len(verts))
if matrix:
verts = transform_verts(verts, matrix)
for v in verts:
v = map (Round_s, v)
nvstr.append("%s %s %s\n" % (v[0], v[1], v[2]))
else:
for v in verts:
v = map(Round_s, v.co)
nvstr.append("%s %s %s\n" % (v[0], v[1], v[2]))
file.write("".join(nvstr))
def numsurf(self, mesh, foomesh = False):
global MATIDX_ERROR
# local vars are faster and so better in tight loops
lc_ADD_DEFAULT_MAT = ADD_DEFAULT_MAT
lc_MATIDX_ERROR = MATIDX_ERROR
lc_PER_FACE_1_OR_2_SIDED = PER_FACE_1_OR_2_SIDED
lc_FACE_TWOSIDED = FACE_TWOSIDED
lc_MESH_TWOSIDED = MESH_TWOSIDED
faces = mesh.faces
hasFaceUV = mesh.faceUV
if foomesh:
looseEdges = mesh.looseEdges
else:
looseEdges = get_loose_edges(mesh)
file = self.file
file.write("numsurf %s\n" % (len(faces) + len(looseEdges)))
if not foomesh: verts = list(self.mesh.verts)
materials = self.mesh.materials
mlist = self.mlist
matidx_error_reported = False
objmats = []
for omat in materials:
if omat: objmats.append(omat.name)
else: objmats.append(None)
for f in faces:
if not objmats:
m_idx = 0
elif objmats[f.mat] in mlist:
m_idx = mlist.index(objmats[f.mat])
else:
if not lc_MATIDX_ERROR:
rdat = REPORT_DATA['warns']
rdat.append("Object %s" % self.obj.name)
rdat.append("has at least one material *index* assigned but not")
rdat.append("defined (not linked to an existing material).")
rdat.append("Result: some faces may be exported with a wrong color.")
rdat.append("You can assign materials in the Edit Buttons window (F9).")
elif not matidx_error_reported:
midxmsg = "- Same for object %s." % self.obj.name
REPORT_DATA['warns'].append(midxmsg)
lc_MATIDX_ERROR += 1
matidx_error_reported = True
m_idx = 0
if lc_ADD_DEFAULT_MAT: m_idx -= 1
refs = len(f)
flaglow = 0 # polygon
if lc_PER_FACE_1_OR_2_SIDED and hasFaceUV: # per face attribute
two_side = f.mode & lc_FACE_TWOSIDED
else: # global, for the whole mesh
two_side = self.mesh.mode & lc_MESH_TWOSIDED
two_side = (two_side > 0) << 1
flaghigh = f.smooth | two_side
surfstr = "SURF 0x%d%d\n" % (flaghigh, flaglow)
if lc_ADD_DEFAULT_MAT and objmats: m_idx += 1
matstr = "mat %s\n" % m_idx
refstr = "refs %s\n" % refs
u, v, vi = 0, 0, 0
fvstr = []
if foomesh:
for vert in f.v:
fvstr.append(str(vert.index))
if hasFaceUV:
u = f.uv[vi][0]
v = f.uv[vi][1]
vi += 1
fvstr.append(" %s %s\n" % (u, v))
else:
for vert in f.v:
fvstr.append(str(verts.index(vert)))
if hasFaceUV:
u = f.uv[vi][0]
v = f.uv[vi][1]
vi += 1
fvstr.append(" %s %s\n" % (u, v))
fvstr = "".join(fvstr)
file.write("%s%s%s%s" % (surfstr, matstr, refstr, fvstr))
# material for loose edges
edges_mat = 0 # default to first material
for omat in objmats: # but look for a material from this mesh
if omat in mlist:
edges_mat = mlist.index(omat)
if lc_ADD_DEFAULT_MAT: edges_mat += 1
break
for e in looseEdges:
fvstr = []
#flaglow = 2 # 1 = closed line, 2 = line
#flaghigh = 0
#surfstr = "SURF 0x%d%d\n" % (flaghigh, flaglow)
surfstr = "SURF 0x02\n"
fvstr.append("%d 0 0\n" % verts.index(e.v1))
fvstr.append("%d 0 0\n" % verts.index(e.v2))
fvstr = "".join(fvstr)
matstr = "mat %d\n" % edges_mat # for now, use first material
refstr = "refs 2\n" # 2 verts
file.write("%s%s%s%s" % (surfstr, matstr, refstr, fvstr))
MATIDX_ERROR = lc_MATIDX_ERROR
# End of Class AC3DExport
from Blender.Window import FileSelector
def report_data():
global VERBOSE
if not VERBOSE: return
d = REPORT_DATA
msgs = {
'0main': '%s\nExporting meshes to AC3D format' % str(19*'-'),
'1warns': 'Warnings',
'2errors': 'Errors',
'3nosplit': 'Not split (because name starts with "=" or "$")',
'4noexport': 'Not exported (because name starts with "!" or "#")'
}
if NO_SPLIT:
l = msgs['3nosplit']
l = "%s (because OPTION NO_SPLIT is set)" % l.split('(')[0]
msgs['3nosplit'] = l
keys = msgs.keys()
keys.sort()
for k in keys:
msgk = msgs[k]
msg = '\n'.join(d[k[1:]])
if msg:
print '\n-%s:' % msgk
print msg
# File Selector callback:
def fs_callback(filename):
global EXPORT_DIR, OBJS, CONFIRM_OVERWRITE, VERBOSE
if not filename.endswith('.ac'): filename = '%s.ac' % filename
if bsys.exists(filename) and CONFIRM_OVERWRITE:
if Blender.Draw.PupMenu('OVERWRITE?%t|File exists') != 1:
return
Blender.Window.WaitCursor(1)
starttime = bsys.time()
export_dir = bsys.dirname(filename)
if export_dir != EXPORT_DIR:
EXPORT_DIR = export_dir
update_RegistryInfo()
try:
file = open(filename, 'w')
except IOError, (errno, strerror):
error = "IOError #%s: %s" % (errno, strerror)
REPORT_DATA['errors'].append("Saving failed - %s." % error)
error_msg = "Couldn't save file!%%t|%s" % error
Blender.Draw.PupMenu(error_msg)
return
try:
test = AC3DExport(OBJS, file)
except:
file.close()
raise
else:
file.close()
endtime = bsys.time() - starttime
REPORT_DATA['main'].append("Done. Saved to: %s" % filename)
REPORT_DATA['main'].append("Data exported in %.3f seconds." % endtime)
if VERBOSE: report_data()
Blender.Window.WaitCursor(0)
# -- End of definitions
scn = Blender.Scene.GetCurrent()
if ONLY_SELECTED:
OBJS = list(scn.objects.context)
else:
OBJS = list(scn.objects)
if not OBJS:
Blender.Draw.PupMenu('ERROR: no objects selected')
else:
fname = bsys.makename(ext=".ac")
if EXPORT_DIR:
fname = bsys.join(EXPORT_DIR, bsys.basename(fname))
FileSelector(fs_callback, "Export AC3D", fname)

View File

@@ -1,783 +0,0 @@
#!BPY
""" Registration info for Blender menus:
Name: 'AC3D (.ac)...'
Blender: 243
Group: 'Import'
Tip: 'Import an AC3D (.ac) file.'
"""
__author__ = "Willian P. Germano"
__url__ = ("blender", "blenderartists.org", "AC3D's homepage, http://www.ac3d.org",
"PLib 3d gaming lib, http://plib.sf.net")
__version__ = "2.48.1 2009-01-11"
__bpydoc__ = """\
This script imports AC3D models into Blender.
AC3D is a simple and affordable commercial 3d modeller also built with OpenGL.
The .ac file format is an easy to parse text format well supported,
for example, by the PLib 3d gaming library.
Supported:<br>
UV-textured meshes with hierarchy (grouping) information.
Missing:<br>
The url tag is irrelevant for Blender.
Known issues:<br>
- Some objects may be imported with wrong normals due to wrong information in the model itself. This can be noticed by strange shading, like darker than expected parts in the model. To fix this, select the mesh with wrong normals, enter edit mode and tell Blender to recalculate the normals, either to make them point outside (the usual case) or inside.<br>
Config Options:<br>
- display transp (toggle): if "on", objects that have materials with alpha < 1.0 are shown with translucency (transparency) in the 3D View.<br>
- subdiv (toggle): if "on", ac3d objects meant to be subdivided receive a SUBSURF modifier in Blender.<br>
- emis as mircol: store the emissive rgb color from AC3D as mirror color in Blender -- this is a hack to preserve the values and be able to export them using the equivalent option in the exporter.<br>
- textures dir (string): if non blank, when imported texture paths are
wrong in the .ac file, Blender will also look for them at this dir.
Notes:<br>
- When looking for assigned textures, Blender tries in order: the actual
paths from the .ac file, the .ac file's dir and the default textures dir path
users can configure (see config options above).
"""
# $Id$
#
# --------------------------------------------------------------------------
# AC3DImport version 2.43.1 Feb 21, 2007
# Program versions: Blender 2.43 and AC3Db files (means version 0xb)
# changed: better triangulation of ngons, more fixes to support bad .ac files,
# option to display transp mats in 3d view, support "subdiv" tag (via SUBSURF modifier)
# --------------------------------------------------------------------------
# Thanks: Melchior Franz for extensive bug testing and reporting, making this
# version cope much better with old or bad .ac files, among other improvements;
# Stewart Andreason for reporting a serious crash; Francesco Brisa for the
# emis as mircol functionality (w/ patch).
# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
# Copyright (C) 2004-2009: Willian P. Germano, wgermano _at_ ig.com.br
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
from math import radians
import Blender
from Blender import Scene, Object, Mesh, Lamp, Registry, sys as bsys, Window, Image, Material, Modifier
from Blender.sys import dirsep
from Blender.Mathutils import Vector, Matrix, Euler
from Blender.Geometry import PolyFill
# Default folder for AC3D textures, to override wrong paths, change to your
# liking or leave as "":
TEXTURES_DIR = ""
DISPLAY_TRANSP = True
SUBDIV = True
EMIS_AS_MIRCOL = False
tooltips = {
'DISPLAY_TRANSP': 'Turn transparency on in the 3d View for objects using materials with alpha < 1.0.',
'SUBDIV': 'Apply a SUBSURF modifier to objects meant to appear subdivided.',
'TEXTURES_DIR': 'Additional folder to look for missing textures.',
'EMIS_AS_MIRCOL': 'Store emis color as mirror color in Blender.'
}
def update_registry():
global TEXTURES_DIR, DISPLAY_TRANSP, EMIS_AS_MIRCOL
rd = dict([('tooltips', tooltips), ('TEXTURES_DIR', TEXTURES_DIR), ('DISPLAY_TRANSP', DISPLAY_TRANSP), ('SUBDIV', SUBDIV), ('EMIS_AS_MIRCOL', EMIS_AS_MIRCOL)])
Registry.SetKey('ac3d_import', rd, True)
rd = Registry.GetKey('ac3d_import', True)
if rd:
if 'GROUP' in rd:
update_registry()
try:
TEXTURES_DIR = rd['TEXTURES_DIR']
DISPLAY_TRANSP = rd['DISPLAY_TRANSP']
SUBDIV = rd['SUBDIV']
EMIS_AS_MIRCOL = rd['EMIS_AS_MIRCOL']
except:
update_registry()
else: update_registry()
if TEXTURES_DIR:
oldtexdir = TEXTURES_DIR
if dirsep == '/': TEXTURES_DIR = TEXTURES_DIR.replace('\\', '/')
if TEXTURES_DIR[-1] != dirsep: TEXTURES_DIR = "%s%s" % (TEXTURES_DIR, dirsep)
if oldtexdir != TEXTURES_DIR: update_registry()
VERBOSE = True
rd = Registry.GetKey('General', True)
if rd:
if rd.has_key('verbose'):
VERBOSE = rd['verbose']
errmsg = ""
# Matrix to align ac3d's coordinate system with Blender's one,
# it's a -90 degrees rotation around the x axis:
AC_TO_BLEND_MATRIX = Matrix([1, 0, 0], [0, 0, 1], [0, -1, 0])
AC_WORLD = 0
AC_GROUP = 1
AC_POLY = 2
AC_LIGHT = 3
AC_OB_TYPES = {
'world': AC_WORLD,
'group': AC_GROUP,
'poly': AC_POLY,
'light': AC_LIGHT
}
AC_OB_BAD_TYPES_LIST = [] # to hold references to unknown (wrong) ob types
def inform(msg):
global VERBOSE
if VERBOSE: print msg
def euler_in_radians(eul):
"Used while there's a bug in the BPY API"
eul.x = radians(eul.x)
eul.y = radians(eul.y)
eul.z = radians(eul.z)
return eul
class Obj:
def __init__(self, type):
self.type = type
self.dad = None
self.name = ''
self.data = ''
self.tex = ''
self.texrep = [1,1]
self.texoff = None
self.loc = []
self.rot = []
self.size = []
self.crease = 30
self.subdiv = 0
self.vlist = []
self.flist_cfg = []
self.flist_v = []
self.flist_uv = []
self.elist = []
self.matlist = []
self.kids = 0
self.bl_obj = None # the actual Blender object created from this data
class AC3DImport:
def __init__(self, filename):
global errmsg
self.scene = Scene.GetCurrent()
self.i = 0
errmsg = ''
self.importdir = bsys.dirname(filename)
try:
file = open(filename, 'r')
except IOError, (errno, strerror):
errmsg = "IOError #%s: %s" % (errno, strerror)
Blender.Draw.PupMenu('ERROR: %s' % errmsg)
inform(errmsg)
return None
header = file.read(5)
header, version = header[:4], header[-1]
if header != 'AC3D':
file.close()
errmsg = 'AC3D header not found (invalid file)'
Blender.Draw.PupMenu('ERROR: %s' % errmsg)
inform(errmsg)
return None
elif version != 'b':
inform('AC3D file version 0x%s.' % version)
inform('This importer is for version 0xb, so it may fail.')
self.token = {'OBJECT': self.parse_obj,
'numvert': self.parse_vert,
'numsurf': self.parse_surf,
'name': self.parse_name,
'data': self.parse_data,
'kids': self.parse_kids,
'loc': self.parse_loc,
'rot': self.parse_rot,
'MATERIAL': self.parse_mat,
'texture': self.parse_tex,
'texrep': self.parse_texrep,
'texoff': self.parse_texoff,
'subdiv': self.parse_subdiv,
'crease': self.parse_crease}
self.objlist = []
self.mlist = []
self.kidsnumlist = []
self.dad = None
self.lines = file.readlines()
self.lines.append('')
self.parse_file()
file.close()
self.testAC3DImport()
def parse_obj(self, value):
kidsnumlist = self.kidsnumlist
if kidsnumlist:
while not kidsnumlist[-1]:
kidsnumlist.pop()
if kidsnumlist:
self.dad = self.dad.dad
else:
inform('Ignoring unexpected data at end of file.')
return -1 # bad file with more objects than reported
kidsnumlist[-1] -= 1
if value in AC_OB_TYPES:
new = Obj(AC_OB_TYPES[value])
else:
if value not in AC_OB_BAD_TYPES_LIST:
AC_OB_BAD_TYPES_LIST.append(value)
inform('Unexpected object type keyword: "%s". Assuming it is of type: "poly".' % value)
new = Obj(AC_OB_TYPES['poly'])
new.dad = self.dad
new.name = value
self.objlist.append(new)
def parse_kids(self, value):
kids = int(value)
if kids:
self.kidsnumlist.append(kids)
self.dad = self.objlist[-1]
self.objlist[-1].kids = kids
def parse_name(self, value):
name = value.split('"')[1]
self.objlist[-1].name = name
def parse_data(self, value):
data = self.lines[self.i].strip()
self.objlist[-1].data = data
def parse_tex(self, value):
line = self.lines[self.i - 1] # parse again to properly get paths with spaces
texture = line.split('"')[1]
self.objlist[-1].tex = texture
def parse_texrep(self, trash):
trep = self.lines[self.i - 1]
trep = trep.split()
trep = [float(trep[1]), float(trep[2])]
self.objlist[-1].texrep = trep
self.objlist[-1].texoff = [0, 0]
def parse_texoff(self, trash):
toff = self.lines[self.i - 1]
toff = toff.split()
toff = [float(toff[1]), float(toff[2])]
self.objlist[-1].texoff = toff
def parse_mat(self, value):
i = self.i - 1
lines = self.lines
line = lines[i].split()
mat_name = ''
mat_col = mat_amb = mat_emit = mat_spec_col = mat_mir_col = [0,0,0]
mat_alpha = 1
mat_spec = 1.0
while line[0] == 'MATERIAL':
mat_name = line[1].split('"')[1]
mat_col = map(float,[line[3],line[4],line[5]])
v = map(float,[line[7],line[8],line[9]])
mat_amb = (v[0]+v[1]+v[2]) / 3.0
v = map(float,[line[11],line[12],line[13]])
mat_emit = (v[0]+v[1]+v[2]) / 3.0
if EMIS_AS_MIRCOL:
mat_emit = 0
mat_mir_col = map(float,[line[11],line[12],line[13]])
mat_spec_col = map(float,[line[15],line[16],line[17]])
mat_spec = float(line[19]) / 64.0
mat_alpha = float(line[-1])
mat_alpha = 1 - mat_alpha
self.mlist.append([mat_name, mat_col, mat_amb, mat_emit, mat_spec_col, mat_spec, mat_mir_col, mat_alpha])
i += 1
line = lines[i].split()
self.i = i
def parse_rot(self, trash):
i = self.i - 1
ob = self.objlist[-1]
rot = self.lines[i].split(' ', 1)[1]
rot = map(float, rot.split())
matrix = Matrix(rot[:3], rot[3:6], rot[6:])
ob.rot = matrix
size = matrix.scalePart() # vector
ob.size = size
def parse_loc(self, trash):
i = self.i - 1
loc = self.lines[i].split(' ', 1)[1]
loc = map(float, loc.split())
self.objlist[-1].loc = Vector(loc)
def parse_crease(self, value):
# AC3D: range is [0.0, 180.0]; Blender: [1, 80]
value = float(value)
self.objlist[-1].crease = int(value)
def parse_subdiv(self, value):
self.objlist[-1].subdiv = int(value)
def parse_vert(self, value):
i = self.i
lines = self.lines
obj = self.objlist[-1]
vlist = obj.vlist
n = int(value)
while n:
line = lines[i].split()
line = map(float, line)
vlist.append(line)
n -= 1
i += 1
if vlist: # prepend a vertex at 1st position to deal with vindex 0 issues
vlist.insert(0, line)
self.i = i
def parse_surf(self, value):
i = self.i
is_smooth = 0
double_sided = 0
lines = self.lines
obj = self.objlist[-1]
vlist = obj.vlist
matlist = obj.matlist
numsurf = int(value)
NUMSURF = numsurf
badface_notpoly = badface_multirefs = 0
while numsurf:
flags = lines[i].split()[1][2:]
if len(flags) > 1:
flaghigh = int(flags[0])
flaglow = int(flags[1])
else:
flaghigh = 0
flaglow = int(flags[0])
is_smooth = flaghigh & 1
twoside = flaghigh & 2
nextline = lines[i+1].split()
if nextline[0] != 'mat': # the "mat" line may be missing (found in one buggy .ac file)
matid = 0
if not matid in matlist: matlist.append(matid)
i += 2
else:
matid = int(nextline[1])
if not matid in matlist: matlist.append(matid)
nextline = lines[i+2].split()
i += 3
refs = int(nextline[1])
face = []
faces = []
edges = []
fuv = []
fuvs = []
rfs = refs
while rfs:
line = lines[i].split()
v = int(line[0]) + 1 # + 1 to avoid vindex == 0
uv = [float(line[1]), float(line[2])]
face.append(v)
fuv.append(Vector(uv))
rfs -= 1
i += 1
if flaglow: # it's a line or closed line, not a polygon
while len(face) >= 2:
cut = face[:2]
edges.append(cut)
face = face[1:]
if flaglow == 1 and edges: # closed line
face = [edges[-1][-1], edges[0][0]]
edges.append(face)
else: # polygon
# check for bad face, that references same vertex more than once
lenface = len(face)
if lenface < 3:
# less than 3 vertices, not a face
badface_notpoly += 1
elif sum(map(face.count, face)) != lenface:
# multiple references to the same vertex
badface_multirefs += 1
else: # ok, seems fine
if len(face) > 4: # ngon, triangulate it
polyline = []
for vi in face:
polyline.append(Vector(vlist[vi]))
tris = PolyFill([polyline])
for t in tris:
tri = [face[t[0]], face[t[1]], face[t[2]]]
triuvs = [fuv[t[0]], fuv[t[1]], fuv[t[2]]]
faces.append(tri)
fuvs.append(triuvs)
else: # tri or quad
faces.append(face)
fuvs.append(fuv)
obj.flist_cfg.extend([[matid, is_smooth, twoside]] * len(faces))
obj.flist_v.extend(faces)
obj.flist_uv.extend(fuvs)
obj.elist.extend(edges) # loose edges
numsurf -= 1
if badface_notpoly or badface_multirefs:
inform('Object "%s" - ignoring bad faces:' % obj.name)
if badface_notpoly:
inform('\t%d face(s) with less than 3 vertices.' % badface_notpoly)
if badface_multirefs:
inform('\t%d face(s) with multiple references to a same vertex.' % badface_multirefs)
self.i = i
def parse_file(self):
i = 1
lines = self.lines
line = lines[i].split()
while line:
kw = ''
for k in self.token.keys():
if line[0] == k:
kw = k
break
i += 1
if kw:
self.i = i
result = self.token[kw](line[1])
if result:
break # bad .ac file, stop parsing
i = self.i
line = lines[i].split()
# for each group of meshes we try to find one that can be used as
# parent of the group in Blender.
# If not found, we can use an Empty as parent.
def found_parent(self, groupname, olist):
l = [o for o in olist if o.type == AC_POLY \
and not o.kids and not o.rot and not o.loc]
if l:
for o in l:
if o.name == groupname:
return o
#return l[0]
return None
def build_hierarchy(self):
blmatrix = AC_TO_BLEND_MATRIX
olist = self.objlist[1:]
olist.reverse()
scene = self.scene
newlist = []
for o in olist:
kids = o.kids
if kids:
children = newlist[-kids:]
newlist = newlist[:-kids]
if o.type == AC_GROUP:
parent = self.found_parent(o.name, children)
if parent:
children.remove(parent)
o.bl_obj = parent.bl_obj
else: # not found, use an empty
empty = scene.objects.new('Empty', o.name)
o.bl_obj = empty
bl_children = [c.bl_obj for c in children if c.bl_obj != None]
o.bl_obj.makeParent(bl_children, 0, 1)
for child in children:
blob = child.bl_obj
if not blob: continue
if child.rot:
eul = euler_in_radians(child.rot.toEuler())
blob.setEuler(eul)
if child.size:
blob.size = child.size
if not child.loc:
child.loc = Vector(0.0, 0.0, 0.0)
blob.setLocation(child.loc)
newlist.append(o)
for o in newlist: # newlist now only has objs w/o parents
blob = o.bl_obj
if not blob:
continue
if o.size:
o.bl_obj.size = o.size
if not o.rot:
blob.setEuler([1.5707963267948966, 0, 0])
else:
matrix = o.rot * blmatrix
eul = euler_in_radians(matrix.toEuler())
blob.setEuler(eul)
if o.loc:
o.loc *= blmatrix
else:
o.loc = Vector(0.0, 0.0, 0.0)
blob.setLocation(o.loc) # forces DAG update, so we do it even for 0, 0, 0
# XXX important: until we fix the BPy API so it doesn't increase user count
# when wrapping a Blender object, this piece of code is needed for proper
# object (+ obdata) deletion in Blender:
for o in self.objlist:
if o.bl_obj:
o.bl_obj = None
def testAC3DImport(self):
FACE_TWOSIDE = Mesh.FaceModes['TWOSIDE']
FACE_TEX = Mesh.FaceModes['TEX']
MESH_AUTOSMOOTH = Mesh.Modes['AUTOSMOOTH']
MAT_MODE_ZTRANSP = Material.Modes['ZTRANSP']
MAT_MODE_TRANSPSHADOW = Material.Modes['TRANSPSHADOW']
scene = self.scene
bl_images = {} # loaded texture images
missing_textures = [] # textures we couldn't find
objlist = self.objlist[1:] # skip 'world'
bmat = []
has_transp_mats = False
for mat in self.mlist:
name = mat[0]
m = Material.New(name)
m.rgbCol = (mat[1][0], mat[1][1], mat[1][2])
m.amb = mat[2]
m.emit = mat[3]
m.specCol = (mat[4][0], mat[4][1], mat[4][2])
m.spec = mat[5]
m.mirCol = (mat[6][0], mat[6][1], mat[6][2])
m.alpha = mat[7]
if m.alpha < 1.0:
m.mode |= MAT_MODE_ZTRANSP
has_transp_mats = True
bmat.append(m)
if has_transp_mats:
for mat in bmat:
mat.mode |= MAT_MODE_TRANSPSHADOW
obj_idx = 0 # index of current obj in loop
for obj in objlist:
if obj.type == AC_GROUP:
continue
elif obj.type == AC_LIGHT:
light = Lamp.New('Lamp')
object = scene.objects.new(light, obj.name)
#object.select(True)
obj.bl_obj = object
if obj.data:
light.name = obj.data
continue
# type AC_POLY:
# old .ac files used empty meshes as groups, convert to a real ac group
if not obj.vlist and obj.kids:
obj.type = AC_GROUP
continue
mesh = Mesh.New()
object = scene.objects.new(mesh, obj.name)
#object.select(True)
obj.bl_obj = object
if obj.data: mesh.name = obj.data
mesh.degr = obj.crease # will auto clamp to [1, 80]
if not obj.vlist: # no vertices? nothing more to do
continue
mesh.verts.extend(obj.vlist)
objmat_indices = []
for mat in bmat:
if bmat.index(mat) in obj.matlist:
objmat_indices.append(bmat.index(mat))
mesh.materials += [mat]
if DISPLAY_TRANSP and mat.alpha < 1.0:
object.transp = True
for e in obj.elist:
mesh.edges.extend(e)
if obj.flist_v:
mesh.faces.extend(obj.flist_v)
facesnum = len(mesh.faces)
if facesnum == 0: # shouldn't happen, of course
continue
mesh.faceUV = True
# checking if the .ac file had duplicate faces (Blender ignores them)
if facesnum != len(obj.flist_v):
# it has, ugh. Let's clean the uv list:
lenfl = len(obj.flist_v)
flist = obj.flist_v
uvlist = obj.flist_uv
cfglist = obj.flist_cfg
for f in flist:
f.sort()
fi = lenfl
while fi > 0: # remove data related to duplicates
fi -= 1
if flist[fi] in flist[:fi]:
uvlist.pop(fi)
cfglist.pop(fi)
img = None
if obj.tex != '':
if obj.tex in bl_images.keys():
img = bl_images[obj.tex]
elif obj.tex not in missing_textures:
texfname = None
objtex = obj.tex
baseimgname = bsys.basename(objtex)
if bsys.exists(objtex) == 1:
texfname = objtex
elif bsys.exists(bsys.join(self.importdir, objtex)):
texfname = bsys.join(self.importdir, objtex)
else:
if baseimgname.find('\\') > 0:
baseimgname = bsys.basename(objtex.replace('\\','/'))
objtex = bsys.join(self.importdir, baseimgname)
if bsys.exists(objtex) == 1:
texfname = objtex
else:
objtex = bsys.join(TEXTURES_DIR, baseimgname)
if bsys.exists(objtex):
texfname = objtex
if texfname:
try:
img = Image.Load(texfname)
# Commented because it's unnecessary:
#img.xrep = int(obj.texrep[0])
#img.yrep = int(obj.texrep[1])
if img:
bl_images[obj.tex] = img
except:
inform("Couldn't load texture: %s" % baseimgname)
else:
missing_textures.append(obj.tex)
inform("Couldn't find texture: %s" % baseimgname)
for i in range(facesnum):
f = obj.flist_cfg[i]
fmat = f[0]
is_smooth = f[1]
twoside = f[2]
bface = mesh.faces[i]
bface.smooth = is_smooth
if twoside: bface.mode |= FACE_TWOSIDE
if img:
bface.mode |= FACE_TEX
bface.image = img
bface.mat = objmat_indices.index(fmat)
fuv = obj.flist_uv[i]
if obj.texoff:
uoff = obj.texoff[0]
voff = obj.texoff[1]
urep = obj.texrep[0]
vrep = obj.texrep[1]
for uv in fuv:
uv[0] *= urep
uv[1] *= vrep
uv[0] += uoff
uv[1] += voff
mesh.faces[i].uv = fuv
# finally, delete the 1st vertex we added to prevent vindices == 0
mesh.verts.delete(0)
mesh.calcNormals()
mesh.mode = MESH_AUTOSMOOTH
# subdiv: create SUBSURF modifier in Blender
if SUBDIV and obj.subdiv > 0:
subdiv = obj.subdiv
subdiv_render = subdiv
# just to be safe:
if subdiv_render > 6: subdiv_render = 6
if subdiv > 3: subdiv = 3
modif = object.modifiers.append(Modifier.Types.SUBSURF)
modif[Modifier.Settings.LEVELS] = subdiv
modif[Modifier.Settings.RENDLEVELS] = subdiv_render
obj_idx += 1
self.build_hierarchy()
scene.update()
# End of class AC3DImport
def filesel_callback(filename):
inform("\nTrying to import AC3D model(s) from:\n%s ..." % filename)
Window.WaitCursor(1)
starttime = bsys.time()
test = AC3DImport(filename)
Window.WaitCursor(0)
endtime = bsys.time() - starttime
inform('Done! Data imported in %.3f seconds.\n' % endtime)
Window.EditMode(0)
Window.FileSelector(filesel_callback, "Import AC3D", "*.ac")

View File

@@ -1,13 +0,0 @@
#!BPY
"""
Name: 'Empty mesh'
Blender: 243
Group: 'AddMesh'
"""
import BPyAddMesh
import Blender
def main():
BPyAddMesh.add_mesh_simple('EmptyMesh', [], [], [])
main()

View File

@@ -1,69 +0,0 @@
#!BPY
"""
Name: 'Torus'
Blender: 243
Group: 'AddMesh'
"""
import BPyAddMesh
import Blender
try: from math import cos, sin, pi
except: math = None
def add_torus(PREF_MAJOR_RAD, PREF_MINOR_RAD, PREF_MAJOR_SEG, PREF_MINOR_SEG):
Vector = Blender.Mathutils.Vector
RotationMatrix = Blender.Mathutils.RotationMatrix
verts = []
faces = []
i1 = 0
tot_verts = PREF_MAJOR_SEG * PREF_MINOR_SEG
for major_index in xrange(PREF_MAJOR_SEG):
verts_tmp = []
mtx = RotationMatrix( 360 * float(major_index)/PREF_MAJOR_SEG, 3, 'z' )
for minor_index in xrange(PREF_MINOR_SEG):
angle = 2*pi*minor_index/PREF_MINOR_SEG
verts.append( Vector(PREF_MAJOR_RAD+(cos(angle)*PREF_MINOR_RAD), 0, (sin(angle)*PREF_MINOR_RAD)) * mtx )
if minor_index+1==PREF_MINOR_SEG:
i2 = (major_index)*PREF_MINOR_SEG
i3 = i1 + PREF_MINOR_SEG
i4 = i2 + PREF_MINOR_SEG
else:
i2 = i1 + 1
i3 = i1 + PREF_MINOR_SEG
i4 = i3 + 1
if i2>=tot_verts: i2 = i2-tot_verts
if i3>=tot_verts: i3 = i3-tot_verts
if i4>=tot_verts: i4 = i4-tot_verts
faces.append( (i3,i4,i2,i1) )
i1+=1
return verts, faces
def main():
Draw = Blender.Draw
PREF_MAJOR_RAD = Draw.Create(1.0)
PREF_MINOR_RAD = Draw.Create(0.25)
PREF_MAJOR_SEG = Draw.Create(48)
PREF_MINOR_SEG = Draw.Create(16)
if not Draw.PupBlock('Add Torus', [\
('Major Radius:', PREF_MAJOR_RAD, 0.01, 100, 'Radius for the main ring of the torus'),\
('Minor Radius:', PREF_MINOR_RAD, 0.01, 100, 'Radius for the minor ring of the torus setting the thickness of the ring'),\
('Major Segments:', PREF_MAJOR_SEG, 3, 256, 'Number of segments for the main ring of the torus'),\
('Minor Segments:', PREF_MINOR_SEG, 3, 256, 'Number of segments for the minor ring of the torus'),\
]):
return
verts, faces = add_torus(PREF_MAJOR_RAD.val, PREF_MINOR_RAD.val, PREF_MAJOR_SEG.val, PREF_MINOR_SEG.val)
BPyAddMesh.add_mesh_simple('Torus', verts, [], faces)
if cos and sin and pi:
main()
else:
Blender.Draw.PupMenu("Error%t|This script requires a full python installation")

View File

@@ -1,792 +0,0 @@
#!BPY
"""
Name: 'Bake Constraints'
Blender: 246
Group: 'Animation'
Tooltip: 'Bake a Constrained object/rig to IPOs'
Fillename: 'Bake_Constraint.py'
"""
__author__ = "Roger Wickes (rogerwickes(at)yahoo.com)"
__script__ = "Animation Bake Constraints"
__version__ = "0.7"
__url__ = ["Communicate problems and errors, http://www.blenderartists.com/forum/private.php?do=newpm to PapaSmurf"]
__email__= ["Roger Wickes, rogerwickes@yahoo.com", "scripts"]
__bpydoc__ = """\
bake_constraints
This script bakes the real-world LocRot of an object (the net effect of any constraints -
(Copy, Limit, Track, Follow, - that affect Location, Rotation)
(usually one constrained to match another's location and/or Tracked to another)
and creates a clone with a set of Ipo Curves named Ipo<objname>
These curves control a non-constrained object and thus make it mimic the constrained object
Actions can be then be edited without the need for the drivers/constraining objects
Developed for use with MoCap data, where a bone is constrained to point at an empty
moving through space and time. This records the actual locrot of the armature
so that the motion can be edited, reoriented, scaled, and used as NLA Actions
see also wiki Scripts/Manual/ Tutorial/Motion Capture <br>
Usage: <br>
- Select the reference Object(s) you want to bake <br>
- Set the frame range to bake in the Anim Panel <br>
- Set the test code (if you want a self-test) in the RT field in the Anim Panel <br>
-- Set RT:1 to create a test armature <br>
-- Set RT: up to 100 for more debug messages and status updates <br>
<br>
- Run the script <br>
- The clone copy of the object is created and it has an IPO curve assigned to it. <br>
- The clone shadows the object by an offset locrot (see usrDelta) <br>
- That Object has Ipo Location and Rotation curves that make the clone mimic the movement <br>
of the selected object, but without using constraints. <br>
- If the object was an Armature, the clone's bones move identically in relation to the <br>
original armature, and an Action is created that drives the bone movements. <br>
Version History:
0.1: bakes Loc Rot for a constrained object
0.2: bakes Loc and Rot for the bones within Armature object
0.3: UI for setting options
0.3.1 add manual to script library
0.4: bake multiple objects
0.5: root bone worldspace rotation
0.6: re-integration with BPyArmature
0.7: bakes parents and leaves clones selected
License, Copyright, and Attribution:
by Roger WICKES May 2008, released under Blender Artistic Licence to Public Domain
feel free to add to any Blender Python Scripts Bundle.
Thanks to Jean-Baptiste PERIN, IdeasMan42 (Campbell Barton), Basil_Fawlty/Cage_drei (Andrew Cruse)
much lifted/learned from blender.org/documentation/245PytonDoc and wiki
some modules based on c3D_Import.py, PoseLib16.py and IPO/Armature code examples e.g. camera jitter
Pseudocode:
Initialize
If at least one object is selected
For each selected object,
create a cloned object
remove any constraints on the clone
create or reset an ipo curve named like the object
for each frame
set the clone's locrot key based on the reference object
if it's an armature,
create an action (which is an Ipo for each bone)
for each frame of the animation
for each bone in the armature
set the key
Else you're a smurf
Test Conditions and Regressions:
1. (v0.1) Non-armatures (the cube), with ipo curve and constraints at the object level
2. armatures, with ipo curve and constraints at the object level
3. armatures, with bones that have ipo curves and constraints
4. objects without parents, children with unselected parents, select children first.
Naming conventions:
arm = a specific objec type armature
bone = bones that make up the skeleton of an armature
ob = object, an instance of an object type
ebone = edit bone, a bone in edit mode
pbone = pose bone, a posed bone in an object
tst = testing, self-test routines
usr = user-entered or designated stuff
"""
########################################
import Blender
from Blender import *
from Blender.Mathutils import *
import struct
import string
import bpy
import BPyMessages
import BPyArmature
# reload(BPyArmature)
from BPyArmature import getBakedPoseData
Vector= Blender.Mathutils.Vector
Euler= Blender.Mathutils.Euler
Matrix= Blender.Mathutils.Matrix #invert() function at least
RotationMatrix = Blender.Mathutils.RotationMatrix
TranslationMatrix= Blender.Mathutils.TranslationMatrix
Quaternion = Blender.Mathutils.Quaternion
Vector = Blender.Mathutils.Vector
POSE_XFORM= [Blender.Object.Pose.LOC, Blender.Object.Pose.ROT]
#=================
# Global Variables
#=================
# set senstitivity for displaying debug/console messages. 0=none, 100=max
# then call debug(num,string) to conditionally display status/info in console window
MODE=Blender.Get('rt') #execution mode: 0=run normal, 1=make test armature
DEBUG=Blender.Get('rt') #how much detail on internal processing for user to see. range 0-100
BATCH=False #called from command line? is someone there? Would you like some cake?
#there are two coordinate systems, the real, or absolute 3D space,
# and the local relative to a parent.
COORDINATE_SYSTEMS = ['local','real']
COORD_LOCAL = 0
COORD_REAL = 1
# User Settings - Change these options manually or via GUI (future TODO)
usrCoord = COORD_REAL # what the user wants
usrParent = False # True=clone keeps original parent, False = clone's parent is the clone of the original parent (if cloned)
usrFreeze = 2 #2=yes, 0=no. Freezes shadow object in place at current frame as origin
# delta is amount to offset/change from the reference object. future set in a ui, so technically not a constant
usrDelta = [10,10,0,0,0,0] #order specific - Loc xyz Rot xyz
usrACTION = True # Offset baked Action frames to start at frame 1
CURFRAME = 'curframe' #keyword to use when getting the frame number that the scene is presently on
ARMATURE = 'Armature' #en anglais
BONE_SPACES = ['ARMATURESPACE','BONESPACE']
# 'ARMATURESPACE' - this matrix of the bone in relation to the armature
# 'BONESPACE' - the matrix of the bone in relation to itself
#Ipo curves created are prefixed with a name, like Ipo_ or Bake_ followed by the object/bone name
#bakedArmName = "b." #used for both the armature class and object instance
usrObjectNamePrefix= ""
#ipoBoneNamePrefix = ""
# for example, if on entry an armature named Man was selected, and the object prefix was "a."
# on exit an armature and an IPO curve named a.Man exists for the object as a whole
# if that armature had bones (spine, neck, arm) and the bone prefix was "a."
# the bones and IPO curves will be (a.spine, a.neck, a.arm)
R2D = 18/3.141592653589793 # radian to grad
BLENDER_VERSION = Blender.Get('version')
# Gets the current scene, there can be many scenes in 1 blend file.
scn = Blender.Scene.GetCurrent()
#=================
# Methods
#=================
########################################
def debug(num,msg): #use log4j or just console here.
if DEBUG >= num:
if BATCH == False:
print 'debug: '[:num/10+7]+msg
#TODO: else write out to file (runs faster if it doesnt have to display details)
return
########################################
def error(str):
debug(0,'ERROR: '+str)
if BATCH == False:
Draw.PupMenu('ERROR%t|'+str)
return
########################################
def getRenderInfo():
context=scn.getRenderingContext()
staframe = context.startFrame()
endframe = context.endFrame()
if endframe<staframe: endframe=staframe
curframe = Blender.Get(CURFRAME)
debug(90,'Scene is on frame %i and frame range is %i to %i' % (curframe,staframe,endframe))
return (staframe,endframe,curframe)
########################################
def sortObjects(obs): #returns a list of objects sorted based on parent dependency
obClones= []
while len(obClones) < len(obs):
for ob in obs:
if not ob in obClones:
par= ob.getParent()
#if no parent, or the parent is not scheduled to be cloned
if par==None:
obClones.append(ob) # add the independent
elif par not in obs: # parent will not be cloned
obClones.append(ob) # add the child
elif par in obClones: # is it on the list?
obClones.append(ob) # add the child
# parent may be a child, so it will be caught next time thru
debug(100,'clone object order: \n%s' % obClones)
return obClones # ordered list of (ob, par) tuples
########################################
def sortBones(xbones): #returns a sorted list of bones that should be added,sorted based on parent dependency
# while there are bones to add,
# look thru the list of bones we need to add
# if we have not already added this bone
# if it does not have a parent
# add it
# else, it has a parent
# if we already added it's parent
# add it now.
# else #we need to keep cycling and catch its parent
# else it is a root bone
# add it
# else skip it, it's already in there
# endfor
# endwhile
xboneNames=[]
for xbone in xbones: xboneNames.append(xbone.name)
debug (80,'reference bone order: \n%s' % xboneNames)
eboneNames=[]
while len(eboneNames) < len(xboneNames):
for xbone in xbones:
if not xbone.name in eboneNames:
if not xbone.parent:
eboneNames.append(xbone.name)
else:
if xbone.parent.name in eboneNames:
eboneNames.append(xbone.name)
#else skip it
#endif
#else prego
#endfor
#endwhile
debug (80,'clone bone order: \n%s' % eboneNames)
return eboneNames
########################################
def dupliArmature(ob): #makes a copy in current scn of the armature used by ob and its bones
ob_mat = ob.matrixWorld
ob_data = ob.getData()
debug(49,'Reference object uses %s' % ob_data)
arm_ob = Armature.Get(ob_data.name) #the armature used by the passed object
arm = Blender.Armature.New()
debug(20,'Cloning Armature %s to create %s' % (arm_ob.name, arm.name))
arm.drawType = Armature.STICK #set the draw type
arm.makeEditable() #enter editmode
# for each bone in the object's armature,
xbones=ob.data.bones.values()
usrSpace = 0 #0=armature, 1=local
space=[BONE_SPACES[usrSpace]][0]
#we have to make a list of bones, then figure out our parents, then add to the arm
#when creating a child, we cannot link to a parent if it does not yet exist in our armature
ebones = [] #list of the bones I want to create for my arm
eboneNames = sortBones(xbones)
i=0
# error('bones sorted. continue?')
for abone in eboneNames: #set all editable attributes to fully define the bone.
for bone in xbones:
if bone.name == abone: break # get the reference bone
ebone = Armature.Editbone() #throw me a bone, bone-man!
ebones.append(ebone) #you're on my list, buddy
ebone.name = bone.name
ebone.headRadius = bone.headRadius
ebone.tailRadius = bone.tailRadius
ebone.weight = bone.weight
ebone.options = bone.options
ebone.head = bone.head[space] #dictionary lookups
ebone.tail = bone.tail[space]
ebone.matrix = bone.matrix[space]
ebone.roll = bone.roll[space]
debug(30,'Generating new %s as child of %s' % (bone,bone.parent))
if bone.hasParent():
# parent=bone.parent.name
# debug(100,'looking for %s' % parent)
# for parbone in xbones: if parbone.name == parent: break # get the parent bone
# ebone.parent = arm.bones[ebones[j].name]
ebone.parent = arm.bones[bone.parent.name]
# else:
# ebone.parent = None
debug(30,'Generating new editbone %s as child of %s' % (ebone,ebone.parent))
arm.bones[ebone.name] = ebone # i would have expected an append or add function, but this works
debug (100,'arm.bones: \n%s' % arm.bones)
debug (20,'Cloned %i bones now in armature %s' %(len(arm.bones),arm.name))
myob = scn.objects.new(arm) #interestingly, object must be created before
arm.update() #armature can be saved
debug(40,'dupArm finished %s instanced as object %s' % (arm.name,myob.getName()))
print ob.matrix
print myob.matrix
return myob
########################################
def scrub(): # scrubs to startframe
staFrame,endFrame,curFrame = getRenderInfo()
# eye-candy, go from current to start, fwd or back
if not BATCH:
debug(100, "Positioning to start...")
frameinc=(staFrame-curFrame)/10
if abs(frameinc) >= 1:
for i in range(10):
curFrame+=frameinc
Blender.Set(CURFRAME,curFrame) # computes the constrained location of the 'real' objects
Blender.Redraw()
Blender.Set(CURFRAME, staFrame)
return
########################################
def bakeBones(ref_ob,arm_ob): #copy pose from ref_ob to arm_ob
scrub()
staFrame,endFrame,curFrame = getRenderInfo()
act = getBakedPoseData(ref_ob, staFrame, endFrame, ACTION_BAKE = True, ACTION_BAKE_FIRST_FRAME = usrACTION) # bake the pose positions of the reference ob to the armature ob
arm_ob.action = act
scrub()
# user comprehension feature - change action name and channel ipo names to match the names of the bone they drive
debug (80,'Renaming each action ipo to match the bone they pose')
act.name = arm_ob.name
arm_channels = act.getAllChannelIpos()
pose= arm_ob.getPose()
pbones= pose.bones.values() #we want the bones themselves, not the dictionary lookup
for pbone in pbones:
debug (100,'Channel listing for %s: %s' % (pbone.name,arm_channels[pbone.name] ))
ipo=arm_channels[pbone.name]
ipo.name = pbone.name # since bone names are unique within an armature, the pose names can be the same since they are within an Action
return
########################################
def getOrCreateCurve(ipo, curvename):
"""
Retrieve or create a Blender Ipo Curve named C{curvename} in the C{ipo} Ipo
Either an ipo curve named C{curvename} exists before the call then this curve is returned,
Or such a curve doesn't exist before the call .. then it is created into the c{ipo} Ipo and returned
"""
try:
mycurve = ipo.getCurve(curvename)
if mycurve != None:
pass
else:
mycurve = ipo.addCurve(curvename)
except:
mycurve = ipo.addCurve(curvename)
return mycurve
########################################
def eraseCurve(ipo,numCurves):
debug(90,'Erasing %i curves for %' % (numCurves,ipo.GetName()))
for i in range(numCurves):
nbBezPoints= ipo.getNBezPoints(i)
for j in range(nbBezPoints):
ipo.delBezPoint(i)
return
########################################
def resetIPO(ipo):
debug(60,'Resetting ipo curve named %s' %ipo.name)
numCurves = ipo.getNcurves() #like LocX, LocY, etc
if numCurves > 0:
eraseCurve(ipo, numCurves) #erase data if one exists
return
########################################
def resetIPOs(ob): #resets all IPO curvess assocated with an object and its bones
debug(30,'Resetting any ipo curves linked to %s' %ob.getName())
ipo = ob.getIpo() #may be None
ipoName = ipo.getName() #name of the IPO that guides/controls this object
debug(70,'Object IPO is %s' %ipoName)
try:
ipo = Ipo.Get(ipoName)
except:
ipo = Ipo.New('Object', ipoName)
resetIPO(ipo)
if ob.getType() == ARMATURE:
arm_data=ob.getData()
bones=arm_data.bones.values()
for bone in bones:
#for each bone: get the name and check for a Pose IPO
debug(10,'Processing '+ bone.name)
return
########################################
def parse(string,delim):
index = string.find(delim) # -1 if not found, else pointer to delim
if index+1: return string[:index]
return string
########################################
def newIpo(ipoName): #add a new Ipo object to the Blender scene
ipo=Blender.Ipo.New('Object',ipoName)
ipo.addCurve('LocX')
ipo.addCurve('LocY')
ipo.addCurve('LocZ')
ipo.addCurve('RotX')
ipo.addCurve('RotY')
ipo.addCurve('RotZ')
return ipo
########################################
def makeUpaName(type,name): #i know this exists in Blender somewhere...
debug(90,'Making up a new %s name using %s as a basis.' % (type,name))
name = (parse(name,'.'))
if type == 'Ipo':
ipoName = name # maybe we get lucky today
ext = 0
extlen = 3 # 3 digit extensions, like hello.002
success = False
while not(success):
try:
debug(100,'Trying %s' % ipoName)
ipo = Ipo.Get(ipoName)
#that one exists if we get here. add on extension and keep trying
ext +=1
if ext>=10**extlen: extlen +=1 # go to more digits if 999 not found
ipoName = '%s.%s' % (name, str(ext).zfill(extlen))
except: # could not find it
success = True
name=ipoName
else:
debug (0,'FATAL ERROR: I dont know how to make up a new %s name based on %s' % (type,ob))
return None
return name
########################################
def createIpo(ob): #create an Ipo and curves and link them to this object
#first, we have to create a unique name
#try first with just the name of the object to keep things simple.
ipoName = makeUpaName('Ipo',ob.getName()) # make up a name for a new Ipo based on the object name
debug(20,'Ipo and LocRot curves called %s' % ipoName)
ipo=newIpo(ipoName)
ob.setIpo(ipo) #link them
return ipo
########################################
def getLocLocal(ob):
key = [
ob.LocX,
ob.LocY,
ob.LocZ,
ob.RotX*R2D, #get the curves in this order
ob.RotY*R2D,
ob.RotZ*R2D
]
return key
########################################
def getLocReal(ob):
obMatrix = ob.matrixWorld #Thank you IdeasMan42
loc = obMatrix.translationPart()
rot = obMatrix.toEuler()
key = [
loc.x,
loc.y,
loc.z,
rot.x/10,
rot.y/10,
rot.z/10
]
return key
########################################
def getLocRot(ob,space):
if space in xrange(len(COORDINATE_SYSTEMS)):
if space == COORD_LOCAL:
key = getLocLocal(ob)
return key
elif space == COORD_REAL:
key = getLocReal(ob)
return key
else: #hey, programmers make mistakes too.
debug(0,'Fatal Error: getLoc called with %i' % space)
return
########################################
def getCurves(ipo):
ipos = [
ipo[Ipo.OB_LOCX],
ipo[Ipo.OB_LOCY],
ipo[Ipo.OB_LOCZ],
ipo[Ipo.OB_ROTX], #get the curves in this order
ipo[Ipo.OB_ROTY],
ipo[Ipo.OB_ROTZ]
]
return ipos
########################################
def addPoint(time,keyLocRot,ipos):
if BLENDER_VERSION < 245:
debug(0,'WARNING: addPoint uses BezTriple')
for i in range(len(ipos)):
point = BezTriple.New() #this was new with Blender 2.45 API
point.pt = (time, keyLocRot[i])
point.handleTypes = [1,1]
ipos[i].append(point)
return ipos
########################################
def bakeFrames(ob,myipo): #bakes an object in a scene, returning the IPO containing the curves
myipoName = myipo.getName()
debug(20,'Baking frames for scene %s object %s to ipo %s' % (scn.getName(),ob.getName(),myipoName))
ipos = getCurves(myipo)
#TODO: Gui setup idea: myOffset
# reset action to start at frame 1 or at location
myOffset=0 #=1-staframe
#loop through frames in the animation. Often, there is rollup and the mocap starts late
staframe,endframe,curframe = getRenderInfo()
for frame in range(staframe, endframe+1):
debug(80,'Baking Frame %i' % frame)
#tell Blender to advace to frame
Blender.Set(CURFRAME,frame) # computes the constrained location of the 'real' objects
if not BATCH: Blender.Redraw() # no secrets, let user see what we are doing
#using the constrained Loc Rot of the object, set the location of the unconstrained clone. Yea! Clones are FreeMen
key = getLocRot(ob,usrCoord) #a key is a set of specifed exact channel values (LocRotScale) for a certain frame
key = [a+b for a,b in zip(key, usrDelta)] #offset to the new location
myframe= frame+myOffset
Blender.Set(CURFRAME,myframe)
time = Blender.Get('curtime') #for BezTriple
ipos = addPoint(time,key,ipos) #add this data at this time to the ipos
debug(100,'%s %i %.3f %.2f %.2f %.2f %.2f %.2f %.2f' % (myipoName, myframe, time, key[0], key[1], key[2], key[3], key[4], key[5]))
# eye-candy - smoothly rewind the animation, showing now how the clone match moves
if endframe-staframe <400 and not BATCH:
for frame in range (endframe,staframe,-1): #rewind
Blender.Set(CURFRAME,frame) # computes the constrained location of the 'real' objects
Blender.Redraw()
Blender.Set(CURFRAME,staframe)
Blender.Redraw()
return ipos
########################################
def duplicateLinked(ob):
obType = ob.type
debug(10,'Duplicating %s Object named %s' % (obType,ob.getName()))
scn.objects.selected = [ob]
## rdw: simplified by just duplicating armature. kept code as reference for creating armatures
## disadvantage is that you cant have clone as stick and original as octahedron
## since they share the same Armature. User can click Make Single User button.
## if obType == ARMATURE: #build a copy from scratch
## myob= dupliArmature(ob)
## else:
Blender.Object.Duplicate() # Duplicate linked, including pose constraints.
myobs = Object.GetSelected() #duplicate is top on the list
myob = myobs[0]
if usrParent == False:
myob.clrParent(usrFreeze)
debug(20,'=myob= was created as %s' % myob.getName())
return myob
########################################
def removeConstraints(ob):
for const in ob.constraints:
debug(90,'removed %s => %s' % (ob.name, const))
ob.constraints.remove(const)
return
########################################
def removeConstraintsOb(ob): # from object or armature
debug(40,'Removing constraints from '+ob.getName())
if BLENDER_VERSION > 241: #constraints module not available before 242
removeConstraints(ob)
if ob.getType() == ARMATURE:
pose = ob.getPose()
for pbone in pose.bones.values():
#bone = pose.bones[bonename]
removeConstraints(pbone)
#should also check if it is a deflector?
return
########################################
def deLinkOb(type,ob): #remove linkages
if type == 'Ipo':
success = ob.clearIpo() #true=there was one
if success: debug(80,'deLinked Ipo curve to %s' % ob.getName())
return
########################################
def bakeObject(ob): #bakes the core object locrot and assigns the Ipo to a Clone
if ob != None:
# Clone the object - duplicate it, clean the clone, and create an ipo curve for the clone
myob = duplicateLinked(ob) #clone it
myob.setName(usrObjectNamePrefix + ob.getName())
removeConstraintsOb(myob) #my object is a free man
deLinkOb('Ipo',myob) #kids, it's not nice to share. you've been lied to
if ob.getType() != ARMATURE: # baking armatures is based on bones, not object
myipo = createIpo(myob) #create own IPO and curves for the clone object
ipos = bakeFrames(ob,myipo) #bake the locrot for this obj for the scene frames
return myob
########################################
def bake(ob,par): #bakes an object of any type, linking it to parent
debug(0,'Baking %s object %s' % (ob.getType(), ob))
clone = bakeObject(ob) #creates and bakes the object motion
if par!= None:
par.makeParent([clone])
debug(20,"assigned object to parent %s" % par)
if ob.getType() == ARMATURE:
## error('Object baked. Continue with bones?')
bakeBones(ob,clone) #go into the bones and copy from -> to in frame range
#future idea: bakeMesh (net result of Shapekeys, Softbody, Cloth, Fluidsim,...)
return clone
########################################
def tstCreateArm(): #create a test armature in scene
# rip-off from http://www.blender.org/documentation/245PythonDoc/Pose-module.html - thank you!
debug(0,'Making Test Armature')
# New Armature
arm_data= Armature.New('myArmature')
print arm_data
arm_ob = scn.objects.new(arm_data)
arm_data.makeEditable()
# Add 4 bones
ebones = [Armature.Editbone(), Armature.Editbone(), Armature.Editbone(), Armature.Editbone()]
# Name the editbones
ebones[0].name = 'Bone.001'
ebones[1].name = 'Bone.002'
ebones[2].name = 'Bone.003'
ebones[3].name = 'Bone.004'
# Assign the editbones to the armature
for eb in ebones:
arm_data.bones[eb.name]= eb
# Set the locations of the bones
ebones[0].head= Mathutils.Vector(0,0,0)
ebones[0].tail= Mathutils.Vector(0,0,1) #tip
ebones[1].head= Mathutils.Vector(0,0,1)
ebones[1].tail= Mathutils.Vector(0,0,2)
ebones[2].head= Mathutils.Vector(0,0,2)
ebones[2].tail= Mathutils.Vector(0,0,3)
ebones[3].head= Mathutils.Vector(0,0,3)
ebones[3].tail= Mathutils.Vector(0,0,4)
ebones[1].parent= ebones[0]
ebones[2].parent= ebones[1]
ebones[3].parent= ebones[2]
arm_data.update()
# Done with editing the armature
# Assign the pose animation
arm_pose = arm_ob.getPose()
act = arm_ob.getAction()
if not act: # Add a pose action if we dont have one
act = Armature.NLA.NewAction()
act.setActive(arm_ob)
xbones=arm_ob.data.bones.values()
pbones = arm_pose.bones.values()
frame = 1
for pbone in pbones: # set bones to no rotation
pbone.quat[:] = 1.000,0.000,0.000,0.0000
pbone.insertKey(arm_ob, frame, Object.Pose.ROT)
# Set a different rotation at frame 25
pbones[0].quat[:] = 1.000,0.1000,0.2000,0.20000
pbones[1].quat[:] = 1.000,0.6000,0.5000,0.40000
pbones[2].quat[:] = 1.000,0.1000,0.3000,0.40000
pbones[3].quat[:] = 1.000,-0.2000,-0.3000,0.30000
frame = 25
for i in xrange(4):
pbones[i].insertKey(arm_ob, frame, Object.Pose.ROT)
pbones[0].quat[:] = 1.000,0.000,0.000,0.0000
pbones[1].quat[:] = 1.000,0.000,0.000,0.0000
pbones[2].quat[:] = 1.000,0.000,0.000,0.0000
pbones[3].quat[:] = 1.000,0.000,0.000,0.0000
frame = 50
for pbone in pbones: # set bones to no rotation
pbone.quat[:] = 1.000,0.000,0.000,0.0000
pbone.insertKey(arm_ob, frame, Object.Pose.ROT)
return arm_ob
########################################
def tstMoveOb(ob): # makes a simple LocRot animation of object in the scene
anim = [
#Loc Rot/10
#
( 0,0,0, 0, 0, 0), #frame 1 origin
( 1,0,0, 0, 0, 0), #frame 2
( 1,1,0, 0, 0, 0),
( 1,1,1, 0, 0, 0),
( 1,1,1,4.5, 0, 0),
( 1,1,1,4.5,4.5, 0),
( 1,1,1,4.5,4.5,4.5)
]
space = COORD_LOCAL
ipo = createIpo(ob) #create an Ipo and curves for this object
ipos = getCurves(ipo)
# span this motion over the currently set anim range
# to set points, i need time but do not know how it is computed, so will have to advance the animation
staframe,endframe,curframe = getRenderInfo()
frame = staframe #x position of new ipo datapoint. set to staframe if you want a match
frameDelta=(endframe-staframe)/(len(anim)) #accomplish the animation in frame range
for key in anim: #effectively does a getLocRot()
#tell Blender to advace to frame
Blender.Set('curframe',frame) # computes the constrained location of the 'real' objects
time = Blender.Get('curtime')
ipos = addPoint(time,key,ipos) #add this data at this time to the ipos
debug(100,'%s %i %.3f %.2f %.2f %.2f %.2f %.2f %.2f' % (ipo.name, frame, time, key[0], key[1], key[2], key[3], key[4], key[5]))
frame += frameDelta
Blender.Set(CURFRAME,curframe) # reset back to where we started
return
#=================
# Program Template
#=================
########################################
def main():
# return code set via rt button in Blender Buttons Scene Context Anim panel
if MODE == 1: #create test armature #1
ob = tstCreateArm() # make test arm and select it
tstMoveOb(ob)
scn.objects.selected = [ob]
obs= Blender.Object.GetSelected() #scn.objects.selected
obs= sortObjects(obs)
debug(0,'Baking %i objects' % len(obs))
if len(obs) >= 1: # user might have multiple objects selected
i= 0
clones=[] # my clone army
for ob in obs:
par= ob.getParent()
if not usrParent:
if par in obs:
par= clones[obs.index(par)]
clones.append(bake(ob,par))
scn.objects.selected = clones
else:
error('Please select at least one object')
return
########################################
def benchmark(): # This lets you benchmark (time) the script's running duration
Window.WaitCursor(1)
t = sys.time()
debug(60,'%s began at %.0f' %(__script__,sys.time()))
# Run the function on the active scene
in_editmode = Window.EditMode()
if in_editmode: Window.EditMode(0)
main()
if in_editmode: Window.EditMode(1)
# Timing the script is a good way to be aware on any speed hits when scripting
debug(0,'%s Script finished in %.2f seconds' % (__script__,sys.time()-t) )
Window.WaitCursor(0)
return
########################################
# This lets you can import the script without running it
if __name__ == '__main__':
debug(0, "------------------------------------")
debug(0, "%s %s Script begins with mode=%i debug=%i batch=%s" % (__script__,__version__,MODE,DEBUG,BATCH))
benchmark()

View File

@@ -1,192 +0,0 @@
#!BPY
"""
Name: 'Clean Animation Curves'
Blender: 249
Group: 'Animation'
Tooltip: 'Remove unused keyframes for ipo curves'
"""
# ***** BEGIN GPL LICENSE BLOCK *****
#
# Copyright (C) 2008-2009: Blender Foundation
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# --------------------------------------------------------------------------
import bpy
from Blender import IpoCurve, Draw, Window
def clean_ipos(ipos):
eul = 0.001
def isflat(vec):
prev_y = vec[0][1]
mid_y = vec[1][1]
next_y = vec[2][1]
# flat status for prev and next
return abs(mid_y-prev_y) < eul, abs(mid_y-next_y) < eul
X=0
Y=1
PREV=0
MID=1
NEXT=2
LEFT = 0
RIGHT = 1
TOT = 0
TOTBEZ = 0
# for ipo in bpy.data.ipos:
for ipo in ipos:
if ipo.lib:
continue
# print ipo
for icu in ipo:
interp = icu.interpolation
extend = icu.extend
bezierPoints = icu.bezierPoints
bezierVecs = [bez.vec for bez in bezierPoints]
l = len(bezierPoints)
TOTBEZ += l
# our aim is to simplify this ipo as much as possible!
if interp == IpoCurve.InterpTypes.BEZIER or interp == interp == IpoCurve.InterpTypes.LINEAR:
#print "Not yet supported"
if interp == IpoCurve.InterpTypes.BEZIER:
flats = [isflat(bez) for bez in bezierVecs]
else:
# A bit of a waste but fake the locations for these so they will always be flats
# IS better then too much duplicate code.
flats = [(True, True)] * l
for v in bezierVecs:
v[PREV][Y] = v[NEXT][Y] = v[MID][Y]
# remove middle points
if l>2:
done_nothing = False
while not done_nothing and len(bezierVecs) > 2:
done_nothing = True
i = l-2
while i > 0:
#print i
#print i, len(bezierVecs)
if flats[i]==(True,True) and flats[i-1][RIGHT] and flats[i+1][LEFT]:
if abs(bezierVecs[i][MID][Y] - bezierVecs[i-1][MID][Y]) < eul and abs(bezierVecs[i][MID][Y] - bezierVecs[i+1][MID][Y]) < eul:
done_nothing = False
del flats[i]
del bezierVecs[i]
icu.delBezier(i)
TOT += 1
l-=1
i-=1
# remove endpoints
if extend == IpoCurve.ExtendTypes.CONST and len(bezierVecs) > 1:
#print l, len(bezierVecs)
# start
while l > 2 and (flats[0][RIGHT] and flats[1][LEFT] and (abs(bezierVecs[0][MID][Y] - bezierVecs[1][MID][Y]) < eul)):
print "\tremoving 1 point from start of the curve"
del flats[0]
del bezierVecs[0]
icu.delBezier(0)
TOT += 1
l-=1
# End
while l > 2 and flats[-2][RIGHT] and flats[-1][LEFT] and (abs(bezierVecs[-2][MID][Y] - bezierVecs[-1][MID][Y]) < eul):
print "\tremoving 1 point from end of the curve", l
del flats[l-1]
del bezierVecs[l-1]
icu.delBezier(l-1)
TOT += 1
l-=1
if l==2:
if isflat( bezierVecs[0] )[RIGHT] and isflat( bezierVecs[1] )[LEFT] and abs(bezierVecs[0][MID][Y] - bezierVecs[1][MID][Y]) < eul:
# remove the second point
print "\tremoving 1 point from 2 point bez curve"
# remove the second point
del flats[1]
del bezierVecs[1]
icu.delBezier(1)
TOT+=1
l-=1
# Change to linear for faster evaluation
'''
if l==1:
print 'Linear'
icu.interpolation = IpoCurve.InterpTypes.LINEAR
'''
if interp== IpoCurve.InterpTypes.CONST:
print "Not yet supported"
print 'total', TOT, TOTBEZ
return TOT, TOTBEZ
def main():
ret = Draw.PupMenu('Clean Selected Objects Ipos%t|Object IPO%x1|Object Action%x2|%l|All IPOs (be careful!)%x3')
sce = bpy.data.scenes.active
ipos = []
if ret == 3:
ipos.extend(list(bpy.data.ipos))
else:
for ob in sce.objects.context:
if ret == 1:
ipo = ob.ipo
if ipo:
ipos.append(ipo)
elif ret == 2:
action = ob.action
if action:
ipos.extend([ipo for ipo in action.getAllChannelIpos().values() if ipo])
if not ipos:
Draw.PupMenu('Error%t|No ipos found')
else:
total_removed, total = clean_ipos(ipos)
Draw.PupMenu('Done!%t|Removed ' + str(total_removed) + ' of ' + str(total) + ' points')
Window.RedrawAll()
if __name__ == '__main__':
main()

View File

@@ -1,575 +0,0 @@
#!BPY
""" Registration info for Blender menus: <- these words are ignored
Name: 'Trajectory'
Blender: 243
Group: 'Animation'
Tip: 'See Trajectory of selected object'
"""
__author__ = '3R - R3gis'
__version__ = '2.43'
__url__ = ["Script's site , http://blenderfrance.free.fr/python/Trajectory_en.htm","Author's site , http://cybercreator.free.fr", "French Blender support forum, http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender"]
__email__=["3R, r3gis@free.fr"]
__bpydoc__ = """
Usage:
* Launch with alt+P (or put it in .script folder)
Allow to see in real time trajectory of selected object.
On first run, it ask you
- If you want that actually selected object have they trajectory always shown
- If you want to use Space Handler or a Scriptlink in Redraw mode
- Future and Past : it is the frame in past and future
of the beggining and the end of the path
- Width of line that represent the trajectory
Then the object's trajectory will be shown in all 3D areas.
When trajectory is red, you can modifiy it by moving object.
When trajectory is blue and you want to be able to modify it, inser a Key (I-Key)
Points appears on trajectory :
- Left Clic to modify position
- Right Clic to go to the frame it represents
Notes:<br>
In scriptlink mode, it create one script link so make sure that 'Enable Script Link' toogle is on
In SpaceHandler mode, you have to go in View>>SpaceHandlerScript menu to activate Trajectory
"""
# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
# Copyright (C) 2004-2006: Regis Montoya
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
#################################
# by 3R - 26/08/05
# for any problem :
# r3gis@free.fr
# ou sur le newsgroup:
# http://zoo-logique.org/3D.Blender/
#################################
#Many thanks to cambo for his fixes
#################################
import Blender
scene= Blender.Scene.GetCurrent()
#Writing
def write_script(name, script):
global scene
#List texts and their name
#write : type of writing : 1->New, 2->Overwrite
scripting= None
for text in Blender.Text.Get():
if text.name==name and text.asLines()[1] != "#"+str(__version__):
scripting = text
scripting.clear()
scripting.write(script)
break
if not scripting:
scripting= Blender.Text.New(name)
scripting.write(script)
def link_script(name, type):
global scene
scriptlinks = scene.getScriptLinks(type) # none or list
if not scriptlinks or name not in scriptlinks:
scene.addScriptLink(name, type)
#Deleting of a text
def text_remove(name):
global scene
#try to delete text if already linked
try:
text= Blender.Text.Get(name)
# Texte.clear()
scene.clearScriptLinks([name])
Blender.Text.unlink(text)
except:
print('---Initialisation of Trajectory_'+str(__version__)+'.py---')
#Whether is already running, also check if it's the last version of the script : second line contain the version fo the script
ask_modif= 0 # Default
for text in Blender.Text.Get():
if text.name == 'Trajectory' and text.asLines()[1] == "#"+str(__version__):
#We ask if script modify his seetings, keep it or stop script
ask_modif= Blender.Draw.PupMenu("Script already launch %t|Modify settings%x0|Keep settings%x1|Stop script%x2|")
if ask_modif==-1: # user canceled.
ask_modif= 1
break
selection_mode= 0
future= 35
past= 20
width= 2
#In modify case
if ask_modif==0:
handle_mode= Blender.Draw.Create(0)
selection_mode= Blender.Draw.Create(0)
future= Blender.Draw.Create(35)
past= Blender.Draw.Create(20)
width= Blender.Draw.Create(2)
block= []
block.append(("Space Handlers", handle_mode, "You have to activate for each area by View>>SpaceHandler")) #You can delete this option...
block.append(("Always Draw", selection_mode, "Selected object will have their trajectory always shown"))
block.append(("Past :", past, 1, 900))
block.append(("Futur:", future, 1, 900))
block.append(("Width:", width, 1,5))
if not Blender.Draw.PupBlock("Trajectory seetings", block):
ask_modif=1
handle_mode= handle_mode.val
selection_mode= selection_mode.val
future= future.val
past= past.val
width= width.val
#put names of selected objects in objects_select if option choosen by user
if selection_mode==1:
objects_select= [ob.name for ob in scene.objects.context]
else:
objects_select= []
try:
if handle_mode==1:
DrawPart="#SPACEHANDLER.VIEW3D.DRAW\n"
else:
DrawPart="#!BPY\n"
except:DrawPart="#BadlyMade"
#Here is the script to write in Blender and to link, options are also written now
DrawPart=DrawPart+"#"+str(__version__)+"""
#This script is a part of Trajectory.py and have to be linked to the scene in Redraw if not in HANDLER mode.
#Author : 3R - Regis Montoya
#It's better to use the Trajectory_"version_number".py
#You can modify the two following value to change the path settings
future="""+str(future)+"""
past="""+str(past)+"""
object_init_names="""+str(objects_select)+"""
import Blender, math
from Blender import BGL, Draw, Ipo
from Blender.BGL import *
from Blender.Draw import *
from math import *
from Blender.Mathutils import Vector
#take actual frame
frameC=Blender.Get('curframe')
scene = Blender.Scene.GetCurrent()
render_context=scene.getRenderingContext()
#ajust number of frames with NewMap and OldMapvalue values
k=1.00*render_context.oldMapValue()/render_context.newMapValue()
if k<1:
tr=-1*int(log(k*0.1, 10))
else:
tr=-1*int(log(k, 10))
#The real and integer frame to compare to ipos keys frames
frameCtr=round(frameC*k, tr)
frameCr=frameC*k
frameC=int(round(frameC*k, 0))
#List objects that we have to show trajectory in $objects
# In this case, using a dict for unique objects is the fastest way.
object_dict= dict([(ob.name, ob) for ob in scene.objects.context])
for obname in object_init_names:
if not object_dict.has_key(obname):
try: # Object may be removed.
object_dict[obname]= Blender.Object.Get(obname)
except:
pass # object was removed.
#This fonction give the resulting matrix of all parents at a given frame
#parent_list is the list of all parents [object, matrix, locX_ipo, locY, Z, rotX, Y, Z, sizeX, Y, Z] of current object
def matrixForTraj(frame, parent_list):
DecMatC=Blender.Mathutils.Matrix([1,0,0,0], [0,1,0,0], [0,0,1,0], [0,0,0,1])
for parent_data in parent_list:
parent_ob= parent_data[0]
try: X= parent_data[5][frame]*pi/18
except: X= parent_ob.RotX
try: Y= parent_data[6][frame]*pi/18
except: Y= parent_ob.RotY
try: Z= parent_data[7][frame]*pi/18
except: Z= parent_ob.RotZ
try: LX= parent_data[2][frame]
except: LX= parent_ob.LocX
try: LY= parent_data[3][frame]
except: LY= parent_ob.LocY
try: LZ= parent_data[4][frame]
except: LZ= parent_ob.LocZ
try: SX= parent_data[8][frame]
except: SX= parent_ob.SizeX
try: SY= parent_data[9][frame]
except: SY= parent_ob.SizeY
try: SZ= parent_data[10][frame]
except: SZ= parent_ob.SizeZ
NMat=Blender.Mathutils.Matrix([cos(Y)*cos(Z)*SX,SX*cos(Y)*sin(Z),-SX*sin(Y),0],
[(-cos(X)*sin(Z)+sin(Y)*sin(X)*cos(Z))*SY,(sin(X)*sin(Y)*sin(Z)+cos(X)*cos(Z))*SY,sin(X)*cos(Y)*SY,0],
[(cos(X)*sin(Y)*cos(Z)+sin(X)*sin(Z))*SZ,(cos(X)*sin(Y)*sin(Z)-sin(X)*cos(Z))*SZ,SZ*cos(X)*cos(Y),0],
[LX,LY,LZ,1])
DecMatC=DecMatC*parent_data[1]*NMat
return DecMatC
#####
TestLIST=[]
matview=Blender.Window.GetPerspMatrix()
###########
#Fonction to draw trajectories
###########
def Trace_Traj(ob):
global TestLIST, matview
#we draw trajectories for all objects in list
LocX=[]
LocY=[]
LocZ=[]
#List with trajectories' vertexs
vertexX=[]
contextIpo= ob.ipo
if contextIpo:
ipoLocX=contextIpo[Ipo.OB_LOCX]
ipoLocY=contextIpo[Ipo.OB_LOCY]
ipoLocZ=contextIpo[Ipo.OB_LOCZ]
ipoTime=contextIpo[Ipo.OB_TIME]
else: # only do if there is no IPO (if no ipo curves : return None object and don't go in this except)
ipoLocX= ipoLocY= ipoLocZ= ipoTime= None
if ipoTime:
return 0
#Get all parents of ob
parent=ob.parent
backup_ob= ob
child= ob
parent_list= []
#Get parents's infos :
#list of [name, initial matrix at make parent, ipo in X,Y,Z,rotX,rotY,rotZ,sizeX,Y,Z]
while parent:
Init_Mat=Blender.Mathutils.Matrix(child.getMatrix('worldspace')) #must be done like it (it isn't a matrix otherwise)
Init_Mat.invert()
Init_Mat=Init_Mat*child.getMatrix('localspace')
Init_Mat=parent.getMatrix()*Init_Mat
Init_Mat.invert()
contextIpo= parent.ipo # None or IPO
if contextIpo:
ipo_Parent_LocX=contextIpo[Ipo.OB_LOCX]
ipo_Parent_LocY=contextIpo[Ipo.OB_LOCY]
ipo_Parent_LocZ=contextIpo[Ipo.OB_LOCZ]
ipo_Parent_RotX=contextIpo[Ipo.OB_ROTX]
ipo_Parent_RotY=contextIpo[Ipo.OB_ROTY]
ipo_Parent_RotZ=contextIpo[Ipo.OB_ROTZ]
ipo_Parent_SizeX=contextIpo[Ipo.OB_SIZEX]
ipo_Parent_SizeY=contextIpo[Ipo.OB_SIZEY]
ipo_Parent_SizeZ=contextIpo[Ipo.OB_SIZEZ]
else:
ipo_Parent_LocX=ipo_Parent_LocY=ipo_Parent_LocZ=\
ipo_Parent_RotX=ipo_Parent_RotY=ipo_Parent_RotZ=\
ipo_Parent_SizeX=ipo_Parent_SizeY=ipo_Parent_SizeZ= None
parent_list.append([parent, Init_Mat, ipo_Parent_LocX, ipo_Parent_LocY, ipo_Parent_LocZ, ipo_Parent_RotX, ipo_Parent_RotY, ipo_Parent_RotZ, ipo_Parent_SizeX, ipo_Parent_SizeY, ipo_Parent_SizeZ])
child=parent
parent=parent.parent
#security : if one of parents object are a path>>follow : trajectory don't work properly so it have to draw nothing
for parent in parent_list:
if parent[0].type == 'Curve':
if parent[0].data.flag & 1<<4: # Follow path, 4th bit
return 1
#ob >> re-assign obj and not parent
ob= backup_ob
ob= backup_ob
if ipoLocX: LXC= ipoLocX[frameC]
else: LXC= ob.LocX
if ipoLocY: LYC= ipoLocY[frameC]
else: LYC= ob.LocY
if ipoLocZ: LZC= ipoLocZ[frameC]
else: LZC= ob.LocZ
vect= Vector([ob.LocX, ob.LocY, ob.LocZ, 1])
color=[0, 1]
#If trajectory is being modified and we are at a frame where a ipo key already exist
if round(ob.LocX, 5)!=round(LXC, 5):
for bez in ipoLocX.bezierPoints:
if round(bez.pt[0], tr)==frameCtr:
bez.pt = [frameCr, vect[0]]
ipoLocX.recalc()
if round(ob.LocY, 5)!=round(LYC, 5):
for bez in ipoLocY.bezierPoints:
if round(bez.pt[0], tr)==frameCtr:
bez.pt = [frameCr, vect[1]]
ipoLocY.recalc()
if round(ob.LocZ, 5)!=round(LZC, 5):
for bez in ipoLocZ.bezierPoints:
if round(bez.pt[0], tr)==frameCtr:
bez.pt = [frameCr, vect[2]]
ipoLocZ.recalc()
#change trajectory color if at an ipoKey
VertexFrame=[]
bezier_Coord=0
if ipoLocX: # FIXED like others it was just in case ipoLocX==None
for bez in ipoLocX.bezierPoints:
bezier_Coord=round(bez.pt[0], tr)
if bezier_Coord not in VertexFrame:
VertexFrame.append(bezier_Coord)
if bezier_Coord==frameCtr:
color=[1, color[1]-0.3]
if ipoLocY: # FIXED
for bez in ipoLocY.bezierPoints:
bezier_Coord=round(bez.pt[0], tr)
if bezier_Coord not in VertexFrame:
VertexFrame.append(bezier_Coord)
if round(bez.pt[0], tr)==frameCtr:
color=[1, color[1]-0.3]
if ipoLocZ: # FIXED
for bez in ipoLocZ.bezierPoints:
bezier_Coord=round(bez.pt[0], tr)
if bezier_Coord not in VertexFrame:
VertexFrame.append(bezier_Coord)
if round(bez.pt[0], tr)==frameCtr:
color=[1, color[1]-0.3]
#put in LocX, LocY and LocZ all points of trajectory
for frame in xrange(frameC-past, frameC+future):
DecMat=matrixForTraj(frame, parent_list)
if ipoLocX: LX= ipoLocX[frame]
else: LX= ob.LocX
if ipoLocY: LY= ipoLocY[frame]
else: LY= ob.LocY
if ipoLocZ: LZ= ipoLocZ[frame]
else: LZ= ob.LocZ
vect=Vector(LX, LY, LZ)*DecMat
LocX.append(vect[0])
LocY.append(vect[1])
LocZ.append(vect[2])
#draw part : get current view
MatPreBuff= [matview[i][j] for i in xrange(4) for j in xrange(4)]
MatBuff=BGL.Buffer(GL_FLOAT, 16, MatPreBuff)
glLoadIdentity()
glMatrixMode(GL_PROJECTION)
glPushMatrix()
glLoadMatrixf(MatBuff)
#draw trajectory line
glLineWidth("""+str(width)+""")
glBegin(GL_LINE_STRIP)
for i in xrange(len(LocX)):
glColor3f((i+1)*1.00/len(LocX)*color[0], 0, (i+1)*1.00/len(LocX)*color[1])
glVertex3f(LocX[i], LocY[i], LocZ[i])
glEnd()
#draw trajectory's "vertexs"
if not Blender.Window.EditMode():
glPointSize(5)
glBegin(GL_POINTS)
TestPOINTS=[]
TestFRAME=[]
i=0
for frame in VertexFrame:
ix=int(frame)-frameC+past
if ix>=0 and ix<len(LocX):
glColor3f(1, 0.7, 0.2)
glVertex3f(LocX[ix], LocY[ix], LocZ[ix])
TestPOINTS.append(Vector([LocX[ix], LocY[ix], LocZ[ix], 1]))
TestFRAME.append(int(frame))
i+=1
glEnd()
#this list contains info about where to check if we click over a "vertex" in 3D view
TestLIST.append((ob, TestPOINTS, TestFRAME))
glLineWidth(1)
return 0
for ob in object_dict.itervalues():
Trace_Traj(ob)
###########
#Fonction to handle trajectories
###########
def Manip():
#use TestLIST and matview defined by Trace_Traj
global TestLIST, matview
for screen in Blender.Window.GetScreenInfo(Blender.Window.Types.VIEW3D):
if screen['id']==Blender.Window.GetAreaID():
x0, y0, x1, y1= screen['vertices']
break
#Projection of GL matrix in 3D view
glPushMatrix()
glMatrixMode(GL_PROJECTION)
glPushMatrix()
glLoadIdentity()
#Global coordinates' matrix
glOrtho(x0, x1, y0, y1, -1, 0)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
#Test mouse clics and other events
if Blender.Window.QTest():
evt, val= Blender.Window.QRead()
if (evt==LEFTMOUSE or evt==RIGHTMOUSE) and not Blender.Window.EditMode():
mouse_co=Blender.Window.GetMouseCoords()
#if click on trajectory "vertexs"...
for ob, TestPOINTS, TestFRAME in TestLIST: # ob is now used, line 552 to know what object it had to select
for k, Vect in enumerate(TestPOINTS):
proj=Vect*matview
pt=[(proj[0]/proj[3])*(x1-x0)/2+(x1+x0)/2, (proj[1]/proj[3])*(y1-y0)/2+(y1+y0)/2]
if mouse_co[0]<pt[0]+4 and mouse_co[0]>pt[0]-4 and mouse_co[1]>pt[1]-4 and mouse_co[1]<pt[1]+4:
if evt==LEFTMOUSE:
#remember current selected object
object_names=[obj.name for obj in Blender.Object.GetSelected()]
#this script allow to simulate a GKey, but I have to write a script
#another way would made a infinit redraw or don't allow to move object
#it auto unlink and delete itself
script=\"\"\"
import Blender
from Blender import Draw, Window
from Blender.Window import *
from Blender.Draw import *
from Blender.Mathutils import Vector
# The following code is a bit of a hack, it allows clicking on the points and dragging directly
#It simulate user press GKey
#It also set the cursor position at center (because user have previously clic on area and moved the cursor):
#And I can't get previous cursor position : redraw appear after it has been moved
#If there is no better way you can remove this comments
f= GetAreaID()
SetCursorPos(0,0,0)
#SetKeyQualifiers(1) #FIXED : the bug in older versions seems to have been fixed
SetKeyQualifiers(0)
QAdd(f, Blender.Draw.GKEY, 1, 0)
QHandle(f)
Blender.Redraw()
done=0
while not done:
while Blender.Window.QTest():
ev=Blender.Window.QRead()[0]
if ev not in (4, 5, 18, 112, 213): #all event needed to move object
#SetKeyQualifiers(1) #FIXED too, same reason that above
#SetKeyQualifiers(0)
SetKeyQualifiers(Blender.Window.GetKeyQualifiers())
QAdd(f, ev, 1, 0)
QHandle(f)
Blender.Redraw()
if ev in (RIGHTMOUSE, LEFTMOUSE, ESCKEY):
done=1
Blender.Set('curframe',\"\"\"+str(Blender.Get('curframe'))+\"\"\")
Blender.Object.GetSelected()[0].sel= False
for obname in \"\"\"+str(object_names)+\"\"\":
ob=Blender.Object.Get(obname)
ob.sel= True
SetCursorPos(0,0,0)
scripting=Blender.Text.Get('Edit_Trajectory')
scripting.clear()
Blender.Text.unlink(scripting)
\"\"\"
#FIXED Edit_Trajectory was longer : all SetKeyQualifiers removed
scene=Blender.Scene.GetCurrent()
try:
scripting=Blender.Text.Get('Edit_Trajectory')
scripting.clear()
except:
scripting=Blender.Text.New('Edit_Trajectory')
scripting.write(script)
#script= scripting #FIXED seems not needed anymore
#Go to frame that correspond to selected "vertex"
Blender.Set('curframe', TestFRAME[k])
scene.objects.selected = [] #un select all objects
#FIXED TestLIST[j][0].sel=0, but no j. So ob.sel and above variable changed in obj
ob.sel= True
Blender.Run('Edit_Trajectory')
#work well now !!!
if evt==RIGHTMOUSE :
Blender.Set('curframe', TestFRAME[k])
Manip()
#retrieve a normal matrix
glPopMatrix()
glMatrixMode(GL_PROJECTION)
glPopMatrix()
glMatrixMode(GL_MODELVIEW)
"""
if ask_modif==0:
text_remove('Trajectory')
write_script('Trajectory', DrawPart)
if handle_mode==1:
Blender.UpdateMenus()
else:
link_script('Trajectory', 'Redraw')
if ask_modif==2:
text_remove('Trajectory')
print("---End of Trajectory_"+str(__version__)+".py---\n--- Thanks for use ---")

View File

@@ -1,325 +0,0 @@
#!BPY
"""
Name: 'Armature Symmetry'
Blender: 242
Group: 'Armature'
Tooltip: 'Make an Armature symmetrical'
"""
__author__ = "Campbell Barton"
__url__ = ("blender", "blenderartist")
__version__ = "1.0 2006-7-26"
__doc__ = """\
This script creates perfectly symmetrical armatures,
based on the best fit when comparing the mirrored locations of 2 bones.
Hidden bones are ignored, and optionally only operate on selected bones.
"""
# ***** BEGIN GPL LICENSE BLOCK *****
#
# Script copyright (C) Campbell J Barton 2006
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
import Blender
import bpy
Vector= Blender.Mathutils.Vector
def VecXFlip(vec):
'''
Return a copy of this vector x flipped.
'''
x,y,z= vec
return Vector(-x,y,z)
def editbone_mirror_diff(editbone1, editbone2):
'''
X Mirror bone compare
return a float representing the difference between the 2 bones
the smaller the better the match
'''
h1= editbone1.head
h2= editbone2.head
t1= editbone1.tail
t2= editbone2.tail
# Mirror bone2's location
h2= VecXFlip(h2)
t2= VecXFlip(t2)
#return (h1-h2).length + (t1-t2).length # returns the length only
# For this function its easier to return the bones also
return ((h1-h2).length + (t1-t2).length)/2, editbone1, editbone2
def editbone_mirror_merge(editbone1, editbone2, PREF_MODE_L2R, PREF_MODE_R2L):
'''
Merge these 2 bones to their mirrored locations
'''
h1= editbone1.head
h2= editbone2.head
t1= editbone1.tail
t2= editbone2.tail
if PREF_MODE_L2R and PREF_MODE_R2L:
# Median, flip bone2's locations and average, then apply to editbone1, flip and apply to editbone2
h2_f= VecXFlip(h2)
t2_f= VecXFlip(t2)
h_med= (h1+h2_f)*0.5 # middle between t1 and flipped t2
t_med= (t1+t2_f)*0.5 # middle between h1 and flipped h2
# Apply the median to editbone1
editbone1.head= h_med
editbone1.tail= t_med
# Flip in place for editbone2
h_med.x= -h_med.x
t_med.x= -t_med.x
# Apply the median to editbone2
editbone2.head= h_med
editbone2.tail= t_med
# Average the roll, this might need some logical work, but looks good for now.
r1= editbone1.roll
r2= -editbone2.roll
# print 'rolls are', r1,r2
r_med= (r1+r2)/2
# print 'new roll is', r_med
editbone1.roll= r_med
editbone2.roll= -r_med # mirror roll
else: # Copy from 1 side to another
# Crafty function we can use so L>R and R>L can use the same code
def IS_XMIRROR_SOURCE(xval):
'''Source means is this the value we want to copy from'''
if PREF_MODE_L2R:
if xval<0: return True
else: return False
else: # PREF_MODE_R2L
if xval<0: return False
else: return True
if IS_XMIRROR_SOURCE( h1.x ):# head bone 1s negative, so copy it to h2
editbone2.head= VecXFlip(h1)
else:
'''
assume h2.x<0 - not a big deal if were wrong,
its unlikely to ever happen because the bones would both be on the same side.
'''
# head bone 2s negative, so copy it to h1
editbone1.head= VecXFlip(h2)
# Same as above for tail
if IS_XMIRROR_SOURCE(t1.x):
editbone2.tail= VecXFlip(t1)
else:
editbone1.tail= VecXFlip(t2)
# Copy roll from 1 bone to another, use the head's location to decide which side it's on.
if IS_XMIRROR_SOURCE(editbone1.head):
editbone2.roll= -editbone1.roll
else:
editbone1.roll= -editbone2.roll
def armature_symetry(\
arm_ob,\
PREF_MAX_DIST,\
PREF_XMID_SNAP,\
PREF_XZERO_THRESH,\
PREF_MODE_L2R,\
PREF_MODE_R2L,\
PREF_SEL_ONLY):
'''
Main function that does all the work,
return the number of
'''
arm_data= arm_ob.data
arm_data.makeEditable()
# Get the bones
bones= []
HIDDEN_EDIT= Blender.Armature.HIDDEN_EDIT
BONE_SELECTED= Blender.Armature.BONE_SELECTED
if PREF_SEL_ONLY:
for eb in arm_data.bones.values():
options= eb.options
if HIDDEN_EDIT not in options and BONE_SELECTED in options:
bones.append(eb)
else:
# All non hidden bones
for eb in arm_data.bones.values():
options= eb.options
if HIDDEN_EDIT not in options:
bones.append(eb)
del HIDDEN_EDIT # remove temp variables
del BONE_SELECTED
# Store the numder of bones we have modified for a message
tot_editbones= len(bones)
tot_editbones_modified= 0
if PREF_XMID_SNAP:
# Remove bones that are in the middle (X Zero)
# reverse loop so we can remove items in the list.
for eb_idx in xrange(len(bones)-1, -1, -1):
edit_bone= bones[eb_idx]
if abs(edit_bone.head.x) + abs(edit_bone.tail.x) <= PREF_XZERO_THRESH/2:
# This is a center bone, clamp and remove from the bone list so we dont use again.
if edit_bone.tail.x or edit_bone.head.x:
tot_editbones_modified += 1
edit_bone.tail.x= edit_bone.head.x= 0
del bones[eb_idx]
bone_comparisons= []
# Compare every bone with every other bone, shouldn't be too slow.
# These 2 "for" loops only compare once
for eb_idx_a in xrange(len(bones)-1, -1, -1):
edit_bone_a= bones[eb_idx_a]
for eb_idx_b in xrange(eb_idx_a-1, -1, -1):
edit_bone_b= bones[eb_idx_b]
# Error float the first value from editbone_mirror_diff() so we can sort the resulting list.
bone_comparisons.append(editbone_mirror_diff(edit_bone_a, edit_bone_b))
bone_comparisons.sort() # best matches first
# Make a dict() of bone names that have been used so we dont mirror more then once
bone_mirrored= {}
for error, editbone1, editbone2 in bone_comparisons:
# print 'Trying to merge at error %.3f' % error
if error > PREF_MAX_DIST:
# print 'breaking, max error limit reached PREF_MAX_DIST: %.3f' % PREF_MAX_DIST
break
if not bone_mirrored.has_key(editbone1.name) and not bone_mirrored.has_key(editbone2.name):
# Were not used, execute the mirror
editbone_mirror_merge(editbone1, editbone2, PREF_MODE_L2R, PREF_MODE_R2L)
# print 'Merging bones'
# Add ourselves so we aren't touched again
bone_mirrored[editbone1.name] = None # dummy value, would use sets in python 2.4
bone_mirrored[editbone2.name] = None
# If both options are enabled, then we have changed 2 bones
tot_editbones_modified+= PREF_MODE_L2R + PREF_MODE_R2L
arm_data.update() # get out of armature editmode
return tot_editbones, tot_editbones_modified
def main():
'''
User interface function that gets the options and calls armature_symetry()
'''
scn= bpy.data.scenes.active
arm_ob= scn.objects.active
if not arm_ob or arm_ob.type!='Armature':
Blender.Draw.PupMenu('No Armature object selected.')
return
# Cant be in editmode for armature.makeEditable()
is_editmode= Blender.Window.EditMode()
if is_editmode: Blender.Window.EditMode(0)
Draw= Blender.Draw
# Defaults for the user input
PREF_XMID_SNAP= Draw.Create(1)
PREF_MAX_DIST= Draw.Create(0.4)
PREF_XZERO_THRESH= Draw.Create(0.02)
PREF_MODE_L2R= Draw.Create(1)
PREF_MODE_R2L= Draw.Create(0)
PREF_SEL_ONLY= Draw.Create(1)
pup_block = [\
'Left (-), Right (+)',\
('Left > Right', PREF_MODE_L2R, 'Copy from the Left to Right of the mesh. Enable Both for a mid loc.'),\
('Right > Left', PREF_MODE_R2L, 'Copy from the Right to Left of the mesh. Enable Both for a mid loc.'),\
'',\
('MaxDist:', PREF_MAX_DIST, 0.0, 4.0, 'Maximum difference in mirror bones to match up pairs.'),\
('XZero limit:', PREF_XZERO_THRESH, 0.0, 2.0, 'Tolerance for locking bones into the middle (X/zero).'),\
('XMidSnap Bones', PREF_XMID_SNAP, 'Snap middle verts to X Zero (uses XZero limit)'),\
('Selected Only', PREF_SEL_ONLY, 'Only xmirror selected bones.'),\
]
# Popup, exit if the user doesn't click OK
if not Draw.PupBlock("X Mirror mesh tool", pup_block):
return
# Replace the variables with their button values.
PREF_XMID_SNAP= PREF_XMID_SNAP.val
PREF_MAX_DIST= PREF_MAX_DIST.val
PREF_MODE_L2R= PREF_MODE_L2R.val
PREF_MODE_R2L= PREF_MODE_R2L.val
PREF_XZERO_THRESH= PREF_XZERO_THRESH.val
PREF_SEL_ONLY= PREF_SEL_ONLY.val
# If both are off assume mid-point and enable both
if not PREF_MODE_R2L and not PREF_MODE_L2R:
PREF_MODE_R2L= PREF_MODE_L2R= True
tot_editbones, tot_editbones_modified = armature_symetry(\
arm_ob,\
PREF_MAX_DIST,\
PREF_XMID_SNAP,\
PREF_XZERO_THRESH,\
PREF_MODE_L2R,\
PREF_MODE_R2L,\
PREF_SEL_ONLY)
if is_editmode: Blender.Window.EditMode(1)
# Redraw all views before popup
Blender.Window.RedrawAll()
# Print results
if PREF_SEL_ONLY:
msg= 'moved %i bones of %i selected' % (tot_editbones_modified, tot_editbones)
else:
msg= 'moved %i bones of %i visible' % (tot_editbones_modified, tot_editbones)
Blender.Draw.PupMenu(msg)
# Check for __main__ so this function can be imported by other scripts without running the script.
if __name__=='__main__':
main()

View File

@@ -1,474 +0,0 @@
#!BPY
# -*- coding: utf-8 -*-
""" Registration info for Blender menus
Name: 'Bevel Center'
Blender: 243
Group: 'Mesh'
Tip: 'Bevel selected faces, edges, and vertices'
"""
__author__ = "Loic BERTHE"
__url__ = ("blender", "blenderartists.org")
__version__ = "2.0"
__bpydoc__ = """\
This script implements vertex and edges bevelling in Blender.
Usage:
Select the mesh you want to work on, enter Edit Mode and select the edges
to bevel. Then run this script from the 3d View's Mesh->Scripts menu.
You can control the thickness of the bevel with the slider -- redefine the
end points for bigger or smaller ranges. The thickness can be changed even
after applying the bevel, as many times as needed.
For an extra smoothing after or instead of direct bevel, set the level of
recursiveness and use the "Recursive" button.
This "Recursive" Button, won't work in face select mode, unless you choose
"faces" in the select mode menu.
Notes:<br>
You can undo and redo your steps just like with normal mesh operations in
Blender.
"""
######################################################################
# Bevel Center v2.0 for Blender
# This script lets you bevel the selected vertices or edges and control the
# thickness of the bevel
# (c) 2004-2006 Loïc Berthe (loic+blender@lilotux.net)
# released under Blender Artistic License
######################################################################
import Blender
from Blender import NMesh, Window, Scene
from Blender.Draw import *
from Blender.Mathutils import *
from Blender.BGL import *
import BPyMessages
#PY23 NO SETS#
'''
try:
set()
except:
from sets import set
'''
######################################################################
# Functions to handle the global structures of the script NF, NE and NC
# which contain informations about faces and corners to be created
global E_selected
E_selected = NMesh.EdgeFlags['SELECT']
old_dist = None
def act_mesh_ob():
scn = Scene.GetCurrent()
ob = scn.objects.active
if ob == None or ob.type != 'Mesh':
BPyMessages.Error_NoMeshActive()
return
if ob.getData(mesh=1).multires:
BPyMessages.Error_NoMeshMultiresEdit()
return
return ob
def make_sel_vert(*co):
v= NMesh.Vert(*co)
v.sel = 1
me.verts.append(v)
return v
def make_sel_face(verts):
f = NMesh.Face(verts)
f.sel = 1
me.addFace(f)
def add_to_NV(old,dir,new):
try:
NV[old][dir] = new
except:
NV[old] = {dir:new}
def get_v(old, *neighbors):
# compute the direction of the new vert
if len(neighbors) == 1: dir = (neighbors[0].co - old.co).normalize()
#dir
else: dir = (neighbors[0].co - old.co).normalize() + (neighbors[1].co-old.co).normalize()
# look in NV if this vert already exists
key = tuple(dir)
if old in NV and key in NV[old] : return NV[old][key]
# else, create it
new = old.co + dist.val*dir
v = make_sel_vert(new.x,new.y,new.z)
add_to_NV(old,key,v)
return v
def make_faces():
""" Analyse the mesh, make the faces corresponding to selected faces and
fill the structures NE and NC """
# make the differents flags consistent
for e in me.edges:
if e.flag & E_selected :
e.v1.sel = 1
e.v2.sel = 1
NF =[] # NF : New faces
for f in me.faces:
V = f.v
nV = len(V)
enumV = range(nV)
E = [me.findEdge(V[i],V[(i+1) % nV]) for i in enumV]
Esel = [x.flag & E_selected for x in E]
# look for selected vertices and creates a list containing the new vertices
newV = V[:]
changes = False
for (i,v) in enumerate(V):
if v.sel :
changes = True
if Esel[i-1] == 0 and Esel[i] == 1 : newV[i] = get_v(v,V[i-1])
elif Esel[i-1] == 1 and Esel[i] == 0 : newV[i] = get_v(v,V[(i+1) % nV])
elif Esel[i-1] == 1 and Esel[i] == 1 : newV[i] = get_v(v,V[i-1],V[(i+1) % nV])
else : newV[i] = [get_v(v,V[i-1]),get_v(v,V[(i+1) % nV])]
if changes:
# determine and store the face to be created
lenV = [len(x) for x in newV]
if 2 not in lenV :
new_f = NMesh.Face(newV)
if sum(Esel) == nV : new_f.sel = 1
NF.append(new_f)
else :
nb2 = lenV.count(2)
if nV == 4 : # f is a quad
if nb2 == 1 :
ind2 = lenV.index(2)
NF.append(NMesh.Face([newV[ind2-1],newV[ind2][0],newV[ind2][1],newV[ind2-3]]))
NF.append(NMesh.Face([newV[ind2-1],newV[ind2-2],newV[ind2-3]]))
elif nb2 == 2 :
# We must know if the tuples are neighbours
ind2 = ''.join([str(x) for x in lenV+lenV[:1]]).find('22')
if ind2 != -1 : # They are
NF.append(NMesh.Face([newV[ind2][0],newV[ind2][1],newV[ind2-3][0],newV[ind2-3][1]]))
NF.append(NMesh.Face([newV[ind2][0],newV[ind2-1],newV[ind2-2],newV[ind2-3][1]]))
else: # They aren't
ind2 = lenV.index(2)
NF.append(NMesh.Face([newV[ind2][0],newV[ind2][1],newV[ind2-2][0],newV[ind2-2][1]]))
NF.append(NMesh.Face([newV[ind2][1],newV[ind2-3],newV[ind2-2][0]]))
NF.append(NMesh.Face([newV[ind2][0],newV[ind2-1],newV[ind2-2][1]]))
elif nb2 == 3 :
ind2 = lenV.index(3)
NF.append(NMesh.Face([newV[ind2-1][1],newV[ind2],newV[ind2-3][0]]))
NF.append(NMesh.Face([newV[ind2-1][0],newV[ind2-1][1],newV[ind2-3][0],newV[ind2-3][1]]))
NF.append(NMesh.Face([newV[ind2-3][1],newV[ind2-2][0],newV[ind2-2][1],newV[ind2-1][0]]))
else:
if (newV[0][1].co-newV[3][0].co).length + (newV[1][0].co-newV[2][1].co).length \
< (newV[0][0].co-newV[1][1].co).length + (newV[2][0].co-newV[3][1].co).length :
ind2 = 0
else :
ind2 = 1
NF.append(NMesh.Face([newV[ind2-1][0],newV[ind2-1][1],newV[ind2][0],newV[ind2][1]]))
NF.append(NMesh.Face([newV[ind2][1],newV[ind2-3][0],newV[ind2-2][1],newV[ind2-1][0]]))
NF.append(NMesh.Face([newV[ind2-3][0],newV[ind2-3][1],newV[ind2-2][0],newV[ind2-2][1]]))
else : # f is a tri
if nb2 == 1:
ind2 = lenV.index(2)
NF.append(NMesh.Face([newV[ind2-2],newV[ind2-1],newV[ind2][0],newV[ind2][1]]))
elif nb2 == 2:
ind2 = lenV.index(3)
NF.append(NMesh.Face([newV[ind2-1][1],newV[ind2],newV[ind2-2][0]]))
NF.append(NMesh.Face([newV[ind2-2][0],newV[ind2-2][1],newV[ind2-1][0],newV[ind2-1][1]]))
else:
ind2 = min( [((newV[i][1].co-newV[i-1][0].co).length, i) for i in enumV] )[1]
NF.append(NMesh.Face([newV[ind2-1][1],newV[ind2][0],newV[ind2][1],newV[ind2-2][0]]))
NF.append(NMesh.Face([newV[ind2-2][0],newV[ind2-2][1],newV[ind2-1][0],newV[ind2-1][1]]))
# Preparing the corners
for i in enumV:
if lenV[i] == 2 : NC.setdefault(V[i],[]).append(newV[i])
old_faces.append(f)
# Preparing the Edges
for i in enumV:
if Esel[i]:
verts = [newV[i],newV[(i+1) % nV]]
if V[i].index > V[(i+1) % nV].index : verts.reverse()
NE.setdefault(E[i],[]).append(verts)
# Create the faces
for f in NF: me.addFace(f)
def make_edges():
""" Make the faces corresponding to selected edges """
for old,new in NE.iteritems() :
if len(new) == 1 : # This edge was on a border
oldv = [old.v1, old.v2]
if old.v1.index < old.v2.index : oldv.reverse()
make_sel_face(oldv+new[0])
me.findEdge(*oldv).flag |= E_selected
me.findEdge(*new[0]).flag |= E_selected
#PY23 NO SETS# for v in oldv : NV_ext.add(v)
for v in oldv : NV_ext[v]= None
else:
make_sel_face(new[0] + new[1][::-1])
me.findEdge(*new[0]).flag |= E_selected
me.findEdge(*new[1]).flag |= E_selected
def make_corners():
""" Make the faces corresponding to corners """
for v in NV.iterkeys():
V = NV[v].values()
nV = len(V)
if nV == 1: pass
elif nV == 2 :
#PY23 NO SETS# if v in NV_ext:
if v in NV_ext.iterkeys():
make_sel_face(V+[v])
me.findEdge(*V).flag |= E_selected
else:
#PY23 NO SETS# if nV == 3 and v not in NV_ext : make_sel_face(V)
if nV == 3 and v not in NV_ext.iterkeys() : make_sel_face(V)
else :
# We need to know which are the edges around the corner.
# First, we look for the quads surrounding the corner.
eed = []
for old, new in NE.iteritems():
if v in (old.v1,old.v2) :
if v.index == min(old.v1.index,old.v2.index) : ind = 0
else : ind = 1
if len(new) == 1: eed.append([v,new[0][ind]])
else : eed.append([new[0][ind],new[1][ind]])
# We will add the edges coming from faces where only one vertice is selected.
# They are stored in NC.
if v in NC: eed = eed+NC[v]
# Now we have to sort these vertices
hc = {}
for (a,b) in eed :
hc.setdefault(a,[]).append(b)
hc.setdefault(b,[]).append(a)
for x0,edges in hc.iteritems():
if len(edges) == 1 : break
b = [x0] # b will contain the sorted list of vertices
for i in xrange(len(hc)-1):
for x in hc[x0] :
if x not in b : break
b.append(x)
x0 = x
b.append(b[0])
# Now we can create the faces
if len(b) == 5: make_sel_face(b[:4])
else:
New_V = Vector(0.0, 0.0,0.0)
New_d = [0.0, 0.0,0.0]
for x in hc.iterkeys(): New_V += x.co
for dir in NV[v] :
for i in xrange(3): New_d[i] += dir[i]
New_V *= 1./len(hc)
for i in xrange(3) : New_d[i] /= nV
center = make_sel_vert(New_V.x,New_V.y,New_V.z)
add_to_NV(v,tuple(New_d),center)
for k in xrange(len(b)-1): make_sel_face([center, b[k], b[k+1]])
if 2 < nV and v in NC :
for edge in NC[v] : me.findEdge(*edge).flag |= E_selected
def clear_old():
""" Erase old faces and vertices """
for f in old_faces: me.removeFace(f)
for v in NV.iterkeys():
#PY23 NO SETS# if v not in NV_ext : me.verts.remove(v)
if v not in NV_ext.iterkeys() : me.verts.remove(v)
for e in me.edges:
if e.flag & E_selected :
e.v1.sel = 1
e.v2.sel = 1
######################################################################
# Interface
global dist
dist = Create(0.2)
left = Create(0.0)
right = Create(1.0)
num = Create(2)
# Events
EVENT_NOEVENT = 1
EVENT_BEVEL = 2
EVENT_UPDATE = 3
EVENT_RECURS = 4
EVENT_EXIT = 5
def draw():
global dist, left, right, num, old_dist
global EVENT_NOEVENT, EVENT_BEVEL, EVENT_UPDATE, EVENT_RECURS, EVENT_EXIT
glClear(GL_COLOR_BUFFER_BIT)
Button("Bevel",EVENT_BEVEL,10,100,280,25)
BeginAlign()
left=Number('', EVENT_NOEVENT,10,70,45, 20,left.val,0,right.val,'Set the minimum of the slider')
dist=Slider("Thickness ",EVENT_UPDATE,60,70,180,20,dist.val,left.val,right.val,0, \
"Thickness of the bevel, can be changed even after bevelling")
right = Number("",EVENT_NOEVENT,245,70,45,20,right.val,left.val,200,"Set the maximum of the slider")
EndAlign()
glRasterPos2d(8,40)
Text('To finish, you can use recursive bevel to smooth it')
if old_dist != None:
num=Number('', EVENT_NOEVENT,10,10,40, 16,num.val,1,100,'Recursion level')
Button("Recursive",EVENT_RECURS,55,10,100,16)
Button("Exit",EVENT_EXIT,210,10,80,20)
def event(evt, val):
if ((evt == QKEY or evt == ESCKEY) and not val): Exit()
def bevent(evt):
if evt == EVENT_EXIT : Exit()
elif evt == EVENT_BEVEL : bevel()
elif evt == EVENT_UPDATE :
try: bevel_update()
except NameError : pass
elif evt == EVENT_RECURS : recursive()
Register(draw, event, bevent)
######################################################################
def bevel():
""" The main function, which creates the bevel """
global me,NV,NV_ext,NE,NC, old_faces,old_dist
ob = act_mesh_ob()
if not ob: return
Window.WaitCursor(1) # Change the Cursor
t= Blender.sys.time()
is_editmode = Window.EditMode()
if is_editmode: Window.EditMode(0)
me = ob.data
NV = {}
#PY23 NO SETS# NV_ext = set()
NV_ext= {}
NE = {}
NC = {}
old_faces = []
make_faces()
make_edges()
make_corners()
clear_old()
old_dist = dist.val
print '\tbevel in %.6f sec' % (Blender.sys.time()-t)
me.update(1)
if is_editmode: Window.EditMode(1)
Window.WaitCursor(0)
Blender.Redraw()
def bevel_update():
""" Use NV to update the bevel """
global dist, old_dist
if old_dist == None:
# PupMenu('Error%t|Must bevel first.')
return
is_editmode = Window.EditMode()
if is_editmode: Window.EditMode(0)
fac = dist.val - old_dist
old_dist = dist.val
for old_v in NV.iterkeys():
for dir in NV[old_v].iterkeys():
for i in xrange(3):
NV[old_v][dir].co[i] += fac*dir[i]
me.update(1)
if is_editmode: Window.EditMode(1)
Blender.Redraw()
def recursive():
""" Make a recursive bevel... still experimental """
global dist
from math import pi, sin
if num.val > 1:
a = pi/4
ang = []
for k in xrange(num.val):
ang.append(a)
a = (pi+2*a)/4
l = [2*(1-sin(x))/sin(2*x) for x in ang]
R = dist.val/sum(l)
l = [x*R for x in l]
dist.val = l[0]
bevel_update()
for x in l[1:]:
dist.val = x
bevel()

View File

@@ -1,729 +0,0 @@
#!BPY
# coding: utf-8
"""
Name: 'BlenderLipSynchro'
Blender: 242
Group: 'Animation'
Tooltip: 'Import phonemes from Papagayo or JLipSync for lip synchronization'
"""
__author__ = "Dienben: Benoit Foucque dienben_mail@yahoo.fr"
__url__ = ["blenderLipSynchro Blog, http://blenderlipsynchro.blogspot.com/",
"Papagayo (Python), http://www.lostmarble.com/papagayo/index.shtml",
"JLipSync (Java), http://jlipsync.sourceforge.net/"]
__version__ = "2.0"
__bpydoc__ = """\
Description:
This script imports Voice Export made by Papagayo or JLipSync and maps the export with your shapes.
Usage:
Import a Papagayo or JLipSync voice export file and link it with your shapes.
Note:<br>
- Naturally, you need files exported from one of the supported lip synching
programs. Check their sites to learn more and download them.
"""
# --------------------------------------------------------------------------
# BlenderLipSynchro
# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
#il y a 3 etapes
#la deuxieme on charge le dictionnaire de correspondance
#la troisieme on fait le choix des correpondance
#la quatrieme on construit les cles a partir du fichiers frame
#there are 3 stages
#the second one load the mapping dictionnary
#the tird make the mapping
#the fourth make the key in the IPO Curve
#voici mes differents imports
#the imports
import os
import Blender
from Blender import Ipo
from Blender.Draw import *
from Blender.BGL import *
from Blender.sys import basename
#ici commencent mes fonctions
#here begin my functions
#cette fonction trace l'interface graphique
#this functions draw the User interface
def trace():
#voici mes variables pouvant etre modifie
#my variables
global nbr_phoneme, mon_fichier_dico
global let01, let02, let03, let04,let05, let06, let07, let08, let09, let10
global let11, let12, let13, let14,let15, let16, let17, let18, let19, let20
global let21, let22, let23, let24
global let01selectkey,let02selectkey,let03selectkey,let04selectkey,let05selectkey
global let06selectkey,let07selectkey,let08selectkey,let09selectkey,let10selectkey,let11selectkey
global let12selectkey,let13selectkey,let14selectkey,let15selectkey,let16selectkey,let17selectkey
global let18selectkey,let19selectkey,let20selectkey,let21selectkey,let22selectkey,let23selectkey
global let24selectkey
glClearColor(0.4,0.5,0.6 ,0.0)
glClear(GL_COLOR_BUFFER_BIT)
glColor3d(1,1,1)
glRasterPos2i(87, 375)
Text("Blendersynchro V 2.0")
glColor3d(1,1,1)
glRasterPos2i(84, 360)
Text("Programming: Dienben")
glColor3d(0,0,0)
glRasterPos2i(13, 342)
Text("Lip Synchronization Tool")
glColor3d(0,0,0)
glRasterPos2i(13, 326)
Text("Thanks to Chris Clawson and Liubomir Kovatchev")
glColor3d(1,1,1)
glRasterPos2i(5, 320)
Text("_______________________________________________________")
glColor3d(0,0,0)
glRasterPos2i(6, 318)
Text("_______________________________________________________")
if (etape==1):
#cette etape permet de choisi la correspondance entre les phonemes et les cles
#this stage offer the possibility to choose the mapping between phonems and shapes
glColor3d(1,1,1)
glRasterPos2i(140, 300)
Text("Objet: "+Blender.Object.GetSelected()[0].getName() )
glColor3d(1,1,1)
glRasterPos2i(5, 215)
Text("Assign phonems to shapes:")
#on mesure la taille de la liste de phonemes
#this is the lenght of the phonem list
nbr_phoneme=len(liste_phoneme)
#on dessine les listes de choix
#we draw the choice list
#
if (nbr_phoneme > 0):
let01 = String(" ", 4, 5, 185, 30, 16, liste_phoneme[0], 3)
glColor3d(0,0,0)
glRasterPos2i(40, 188)
Text("=")
let01selectkey = Menu(key_menu, 50, 50, 185, 70, 16, let01selectkey.val)
#
if (nbr_phoneme > 1):
let02 = String(" ", 4, 150, 185, 30, 16, liste_phoneme[1], 2)
glColor3d(0,0,0)
glRasterPos2i(185, 188)
Text("=")
let02selectkey = Menu(key_menu, 51, 195, 185, 70, 16, let02selectkey.val)
#
if (nbr_phoneme > 2):
let03 = String(" ", 4, 5, 165, 30, 16, liste_phoneme[2], 2)
glColor3d(0,0,0)
glRasterPos2i(40, 168)
Text("=")
let03selectkey = Menu(key_menu, 52, 50, 165, 70, 16, let03selectkey.val)
#
if (nbr_phoneme > 3):
let04 = String(" ", 4, 150, 165, 30, 16, liste_phoneme[3], 2)
glColor3d(0,0,0)
glRasterPos2i(185, 168)
Text("=")
let04selectkey = Menu(key_menu, 53, 195, 165, 70, 16, let04selectkey.val)
#
if (nbr_phoneme > 4):
let05 = String(" ", 4, 5, 145, 30, 16, liste_phoneme[4], 2)
glColor3d(0,0,0)
glRasterPos2i(40, 148)
Text("=")
let05selectkey = Menu(key_menu, 54, 50, 145, 70, 16, let05selectkey.val)
#
if (nbr_phoneme > 5):
let06 = String(" ", 4, 150, 145, 30, 16, liste_phoneme[5], 2)
glColor3d(0,0,0)
glRasterPos2i(185, 148)
Text("=")
let06selectkey = Menu(key_menu, 55, 195, 145, 70, 16, let06selectkey.val)
#
if (nbr_phoneme > 6):
let07 = String(" ", 4, 5, 125, 30, 16, liste_phoneme[6], 2)
glColor3d(0,0,0)
glRasterPos2i(40, 128)
Text("=")
let07selectkey = Menu(key_menu, 56, 50, 125, 70, 16, let07selectkey.val)
#
if (nbr_phoneme > 7):
let08 = String(" ", 4, 150, 125, 30, 16, liste_phoneme[7], 2)
glColor3d(0,0,0)
glRasterPos2i(185, 128)
Text("=")
let08selectkey = Menu(key_menu, 57, 195, 125, 70, 16,let08selectkey.val)
#
if (nbr_phoneme > 8):
let09 = String(" ", 4, 5, 105, 30, 16, liste_phoneme[8], 2)
glColor3d(0,0,0)
glRasterPos2i(40, 108)
Text("=")
let09selectkey = Menu(key_menu, 58, 50, 105, 70, 16,let09selectkey.val)
#
if (nbr_phoneme > 9):
let10 = String(" ", 4, 150, 105, 30, 16, liste_phoneme[9], 2)
glColor3d(0,0,0)
glRasterPos2i(185, 108)
Text("=")
let10selectkey = Menu(key_menu, 59, 195, 105, 70, 16, let10selectkey.val)
#
if (nbr_phoneme > 10):
let11 = String(" ", 4, 5, 85, 30, 16, liste_phoneme[10], 2)
glColor3d(0,0,0)
glRasterPos2i(40, 88)
Text("=")
let11selectkey = Menu(key_menu, 60, 50, 85, 70, 16, let11selectkey.val)
#
if (nbr_phoneme > 11):
let12 = String(" ", 4, 150, 85, 30, 16, liste_phoneme[11], 2)
glColor3d(0,0,0)
Text("=")
let12selectkey = Menu(key_menu, 61, 195, 85, 70, 16, let12selectkey.val)
#
if (nbr_phoneme > 12):
let13 = String(" ", 4, 5, 65, 30, 16, liste_phoneme[12], 2)
glColor3d(0,0,0)
glRasterPos2i(40, 68)
Text("=")
let13selectkey = Menu(key_menu, 62, 50, 65, 70, 16, let13selectkey.val)
#
if (nbr_phoneme > 13):
let14 = String(" ", 4, 150, 65, 30, 16, liste_phoneme[13], 2)
glColor3d(0,0,0)
glRasterPos2i(185, 68)
Text("=")
let14selectkey = Menu(key_menu, 63, 195, 65, 70, 16, let14selectkey.val)
#
if (nbr_phoneme > 14):
let15 = String(" ", 4, 5, 45, 30, 16, liste_phoneme[14], 2)
glColor3d(0,0,0)
glRasterPos2i(40, 48)
Text("=")
let15selectkey = Menu(key_menu, 64, 50, 45, 70, 16, let15selectkey.val)
#
if (nbr_phoneme > 15):
let16 = String(" ", 4, 150, 45, 30, 16, liste_phoneme[15], 2)
glColor3d(0,0,0)
glRasterPos2i(185, 48)
Text("=")
let16selectkey = Menu(key_menu, 65, 195, 45, 70, 16, let16selectkey.val)
#
if (nbr_phoneme > 16):
let17 = String(" ", 4, 295, 185, 30, 16, liste_phoneme[16], 2)
glColor3d(0,0,0)
glRasterPos2i(330, 188)
Text("=")
let17selectkey = Menu(key_menu, 66, 340, 185, 70, 16, let17selectkey.val)
#
if (nbr_phoneme > 17):
let18 = String(" ", 4, 440, 185, 70, 16, liste_phoneme[17], 8)
glColor3d(0,0,0)
glRasterPos2i(515, 188)
Text("=")
let18selectkey = Menu(key_menu, 67, 525, 185, 70, 16, let18selectkey.val)
#
if (nbr_phoneme > 18):
let19 = String(" ", 4, 295, 165, 30, 16, liste_phoneme[18], 2)
glColor3d(0,0,0)
glRasterPos2i(330, 168)
Text("=")
let19selectkey = Menu(key_menu, 68, 340, 165, 70, 16, let19selectkey.val)
#
if (nbr_phoneme > 19):
let20 = String(" ", 4, 440, 165, 70, 16, liste_phoneme[19], 8)
glColor3d(0,0,0)
glRasterPos2i(515, 168)
Text("=")
let20selectkey = Menu(key_menu, 69, 525, 165, 70, 16, let20selectkey.val)
#
if (nbr_phoneme > 20):
let21 = String(" ", 4, 295, 145, 30, 16, liste_phoneme[20], 2)
glColor3d(0,0,0)
glRasterPos2i(330, 148)
Text("=")
let21selectkey = Menu(key_menu, 70, 340, 145, 70, 16, let21selectkey.val)
#
if (nbr_phoneme > 21):
let22 = String(" ", 4, 440, 145, 70, 16, liste_phoneme[21], 8)
glColor3d(0,0,0)
glRasterPos2i(515, 148)
Text("=")
let22selectkey = Menu(key_menu, 71, 525, 145, 70, 16, let22selectkey.val)
#
if (nbr_phoneme > 22):
let23 = String(" ", 4, 295, 125, 30, 16, liste_phoneme[22], 2)
glColor3d(0,0,0)
glRasterPos2i(330, 128)
Text("=")
let23selectkey = Menu(key_menu, 72, 340, 125, 70, 16,let23selectkey.val)
#
if (nbr_phoneme > 23):
let24 = String(" ", 4, 440, 125, 70, 16, liste_phoneme[23], 8)
glColor3d(0,0,0)
glRasterPos2i(515, 128)
Text("=")
let24selectkey = Menu(key_menu, 73, 525, 125, 70, 16, let24selectkey.val)
#
if (nbr_phoneme > 24):
let25 = String(" ", 4, 295, 105, 30, 16, liste_phoneme[24], 2)
glColor3d(0,0,0)
glRasterPos2i(330, 108)
Text("=")
let25selectkey = Menu(key_menu, 74, 340, 105, 70, 16, let25selectkey.val)
#
if (nbr_phoneme > 25):
let26 = String(" ", 4, 440, 105, 70, 16, liste_phoneme[25], 8)
glColor3d(0,0,0)
glRasterPos2i(515, 108)
Text("=")
let26selectkey = Menu(key_menu, 75, 525, 105, 70, 16,let26selectkey.val)
#
if (nbr_phoneme > 26):
let27 = String(" ", 4, 295, 85, 30, 16, liste_phoneme[26], 2)
glColor3d(0,0,0)
glRasterPos2i(330, 88)
Text("=")
let27selectkey = Menu(key_menu, 76, 340, 85, 70, 16, let27selectkey.val)
#
if (nbr_phoneme > 27):
let28 = String(" ", 4, 440, 85, 70, 16, liste_phoneme[27], 8)
glColor3d(0,0,0)
glRasterPos2i(515, 88)
Text("=")
let28selectkey = Menu(key_menu, 77, 525, 85, 70, 16,let28selectkey.val)
#
if (nbr_phoneme > 28):
let29 = String(" ", 4, 295, 65, 30, 16, liste_phoneme[28], 2)
glColor3d(0,0,0)
glRasterPos2i(330, 68)
Text("=")
let29selectkey = Menu(key_menu, 78, 340, 65, 70, 16, let29selectkey.val)
#
if (nbr_phoneme > 29):
let30 = String(" ", 4, 440, 65, 70, 16, liste_phoneme[29], 8)
glColor3d(0,0,0)
glRasterPos2i(515, 68)
Text("=")
let30selectkey = Menu(key_menu, 79, 525, 65, 70, 16, let30selectkey.val)
#
if (nbr_phoneme > 30):
let31 = String(" ", 4, 295, 45, 30, 16, liste_phoneme[30], 2)
glColor3d(0,0,0)
glRasterPos2i(330, 48)
Text("=")
let31selectkey = Menu(key_menu, 80, 340, 45, 70, 16, let31selectkey.val)
#
if (nbr_phoneme > 31):
let32 = String(" ", 4, 440, 45, 70, 16, liste_phoneme[31], 8)
glColor3d(0,0,0)
glRasterPos2i(515, 48)
Text("=")
let32selectkey = Menu(key_menu, 81, 525, 45, 70, 16, let32selectkey.val)
Button("Go", 3, 155, 5, 145, 22)
if (etape==2):
glColor3d(1,1,1)
glRasterPos2i(125, 200)
Text("Operation Completed")
if (etape==0):
glColor3d(1,1,1)
glRasterPos2i(125, 200)
Text("Please select a Mesh'Object and Create all the IPO Curves for your Shapes")
if (etape==3):
#this stage permits to load a custom dictionnary
load_file_text = "Load File"
if mon_fichier_dico:
Button("Import Loaded File", 2, 5, 5, 145, 22)
glColor3d(1,1,1)
glRasterPos2i(6, 50)
Text("loaded file: %s" % basename(mon_fichier_dico))
load_file_text = "Choose Another File"
Button(load_file_text, 8, 125, 180, 145, 22)
glRasterPos2i(6, 40)
Text("_______________________________________________________")
glColor3d(0,0,0)
glRasterPos2i(6, 38)
Text("_______________________________________________________")
Button("Exit", 1, 305, 5, 80, 22)
#cette fonction sur evenement quite en cas d'ESC
#this functions catch the ESC event and quit
def event(evt,val):
if (evt == ESCKEY and not val): Exit()
#cette fonction gere les evenements
#the event functions
def bevent(evt):
global etape,soft_type,liste_phoneme,dico_phoneme_export
if (evt == 1):
Exit()
elif (evt == 2):
#c'est l'import du dictionnaire
#we create and import the dictionnary
lecture_chaine(mon_fichier_dico,dico_phoneme_export)
construction_dictionnaire_phoneme()
#we change the stage
etape=1
elif (evt == 3):
#c'est l'import
#we import
lecture_chaine(mon_fichier_export,dico_phoneme_export)
construction_dico_correspondance()
construction_lipsynchro()
#on change d'etape
#we change the stage
etape=2
elif (evt == 8):
#we choose the file
Blender.Window.FileSelector(selectionner_fichier,"Select File")
Blender.Redraw()
#cette fonction recupere le nom et le chemin du fichier dictionnaire
#we catch the name and the path of the dictionnary
def selectionner_fichier(filename):
global mon_fichier_dico,mon_fichier_export
mon_fichier_dico=filename
mon_fichier_export=filename
#fonction de lecture de la liste frame phoneme
#we read the frame and phonems
def lecture_chaine(fichier,liste):
mon_fichier=open(fichier)
#je lis la premiere ligne qui contiens la version de moho
#first, we read the moho version
mon_fichier.readline()
#je lis jusqu'a la fin
#then we read until the end of the file
while 1:
ma_ligne=mon_fichier.readline()
if ma_ligne=='':
break
decoup=ma_ligne.split()
liste[decoup[0]]=decoup[1]
print liste
#fonction qui construit la liste dictionnaire simple
#we make the dictionnary
def construction_dictionnaire_phoneme():
global liste_phoneme
index_liste=0
#je transforme mon dictionnaire en list de tulpes
#we transform the list in tulpes
ma_liste=dico_phoneme_export.items()
#je parcours ma liste a la recherche d'elements non existant
#we read the list to find non existing elements
print dico_phoneme
for index in range(len(ma_liste)):
if ma_liste[index][1] not in liste_phoneme:
liste_phoneme[index_liste:index_liste]=[ma_liste[index][1]]
index_liste=index_liste+1
print liste_phoneme
#cette fonction recupere les courbes cible
#this functon catch the IPO curve
def recuperation_courbe():
global key_menu,dico_key
#on recupere le nom des shapes
#we catch the shapes
key=Blender.Object.GetSelected()[0].getData().getKey().getBlocks()
for n in range(len(key)):
#on vire la premi<6D>re cle (en effet basic n'est pas une cle en tant que telle)
#we threw away the basic shapes
if (n>0):
key_menu=key_menu+key[n].name + " %x" + str(n-1) + "|"
dico_key[str(n-1)]=Blender.Object.GetSelected()[0].getData().getKey().getIpo().getCurves()[n-1]
print "dico_key"
print dico_key
print 'end dico_key'
#cette fonction construit un dictionnaire de correspondance entre les phonemes prononces et les cles a utiliser
#we make the dictionnary for the mapping between shapes and phonems
def construction_dico_correspondance():
global dico_correspondance
#je parcours les phonemes
#we read the phonems
if (nbr_phoneme>0):
dico_correspondance[liste_phoneme[0]]=dico_key[str(let01selectkey.val)]
if (nbr_phoneme>1):
dico_correspondance[liste_phoneme[1]]=dico_key[str(let02selectkey.val)]
if (nbr_phoneme>2):
dico_correspondance[liste_phoneme[2]]=dico_key[str(let03selectkey.val)]
if (nbr_phoneme>3):
dico_correspondance[liste_phoneme[3]]=dico_key[str(let04selectkey.val)]
if (nbr_phoneme>4):
dico_correspondance[liste_phoneme[4]]=dico_key[str(let05selectkey.val)]
if (nbr_phoneme>5):
dico_correspondance[liste_phoneme[5]]=dico_key[str(let06selectkey.val)]
if (nbr_phoneme>6):
dico_correspondance[liste_phoneme[6]]=dico_key[str(let07selectkey.val)]
if (nbr_phoneme>7):
dico_correspondance[liste_phoneme[7]]=dico_key[str(let08selectkey.val)]
if (nbr_phoneme>8):
dico_correspondance[liste_phoneme[8]]=dico_key[str(let09selectkey.val)]
if (nbr_phoneme>9):
dico_correspondance[liste_phoneme[9]]=dico_key[str(let10selectkey.val)]
if (nbr_phoneme>10):
dico_correspondance[liste_phoneme[10]]=dico_key[str(let11selectkey.val)]
if (nbr_phoneme>11):
dico_correspondance[liste_phoneme[11]]=dico_key[str(let12selectkey.val)]
if (nbr_phoneme>12):
dico_correspondance[liste_phoneme[12]]=dico_key[str(let13selectkey.val)]
if (nbr_phoneme>13):
dico_correspondance[liste_phoneme[13]]=dico_key[str(let14selectkey.val)]
if (nbr_phoneme>14):
dico_correspondance[liste_phoneme[14]]=dico_key[str(let15selectkey.val)]
if (nbr_phoneme>15):
dico_correspondance[liste_phoneme[15]]=dico_key[str(let16selectkey.val)]
if (nbr_phoneme>16):
dico_correspondance[liste_phoneme[16]]=dico_key[str(let17selectkey.val)]
if (nbr_phoneme>17):
dico_correspondance[liste_phoneme[17]]=dico_key[str(let18selectkey.val)]
if (nbr_phoneme>18):
dico_correspondance[liste_phoneme[18]]=dico_key[str(let19selectkey.val)]
if (nbr_phoneme>19):
dico_correspondance[liste_phoneme[19]]=dico_key[str(let20selectkey.val)]
if (nbr_phoneme>20):
dico_correspondance[liste_phoneme[20]]=dico_key[str(let21selectkey.val)]
if (nbr_phoneme>21):
dico_correspondance[liste_phoneme[21]]=dico_key[str(let22selectkey.val)]
if (nbr_phoneme>22):
dico_correspondance[liste_phoneme[22]]=dico_key[str(let23selectkey.val)]
if (nbr_phoneme>23):
dico_correspondance[liste_phoneme[23]]=dico_key[str(let24selectkey.val)]
if (nbr_phoneme>24):
dico_correspondance[liste_phoneme[24]]=dico_key[str(let25selectkey.val)]
if (nbr_phoneme>25):
dico_correspondance[liste_phoneme[25]]=dico_key[str(let26selectkey.val)]
if (nbr_phoneme>26):
dico_correspondance[liste_phoneme[26]]=dico_key[str(let27selectkey.val)]
if (nbr_phoneme>27):
dico_correspondance[liste_phoneme[27]]=dico_key[str(let28selectkey.val)]
if (nbr_phoneme>28):
dico_correspondance[liste_phoneme[28]]=dico_key[str(let29selectkey.val)]
if (nbr_phoneme>29):
dico_correspondance[liste_phoneme[29]]=dico_key[str(let30selectkey.val)]
if (nbr_phoneme>30):
dico_correspondance[liste_phoneme[30]]=dico_key[str(let31selectkey.val)]
if (nbr_phoneme>31):
dico_correspondance[liste_phoneme[31]]=dico_key[str(let32selectkey.val)]
print dico_correspondance
#cette fonction ajoute un points a la cle donnee a la frame donnee
#we add a point to the IPO curve Target
def ajoute_point(cle,frame,valeur):
cle.setInterpolation('Linear')
cle.append((frame,valeur))
cle.Recalc()
#cette fonction parcours le dictionnaire des frame <20> ajouter et construit les points
#we add all the point to the IPO Curve
def construction_lipsynchro():
print "je construit"
doublet_old=""
#construction de la liste des frame
cpt=0
liste_frame=[]
for frame in dico_phoneme_export:
liste_frame.append(int(frame))
cpt=cpt+1
liste_frame.sort()
print "listeframe"
print liste_frame
print "fini"
for doublet in liste_frame:
ajoute_point(dico_correspondance[dico_phoneme_export[str(doublet)]],doublet,1)
if (doublet_old==""):
ajoute_point(dico_correspondance[dico_phoneme_export[str(doublet)]],(doublet-2),0)
if (doublet_old!=''):
if (dico_correspondance[dico_phoneme_export[str(doublet)]]!=dico_correspondance[dico_phoneme_export[doublet_old]]):
print "doublet:"+str(doublet)
print "doublet old:"+doublet_old
ajoute_point(dico_correspondance[dico_phoneme_export[doublet_old]],(int(doublet_old)+2),0)
ajoute_point(dico_correspondance[dico_phoneme_export[str(doublet)]],(doublet-2),0)
doublet_old=str(doublet)
#end of my functions we begin the execution
#je commence l execution-----------------------------------------------------------------------------------------------
#voici mes variables
#declaration et instanciation
#decleration and instanciation
#voici mon objet de travail
objet_travail=Create(0)
#my soft type
soft_type=1
#voici la liste des phoneme effectivement utilise
#the phonems'list
#liste_phoneme_papagayo=['AI','E','O','U','FV','L','WQ','MBP','etc','rest']
#liste_phoneme_jlipsinch=['A','B','C','Closed','D','E','F','G','I','K','L','M','N','O','P','Q','R','S','SH','T','TH','U','V','W']
liste_phoneme=[]
#voici mon dictionnaire des frames o
dico_phoneme_export = Create(0)
dico_phoneme_export={}
dico_phoneme={}
#voici mes cle
key_menu=""
dico_key={}
#voici mes ipo
dico_bloc={}
iponame = Create(0)
#voici mon dictionnaire de correspondance
dico_correspondance={}
try:
#on verifie est bien une mesh et qu'il a des courbes
if ((Blender.Object.GetSelected()[0].getType()=='Mesh')):
#on verifie que l'objet a bien toute ses Courbes
if (len(Blender.Object.GetSelected()[0].getData().getKey().getBlocks())-1==Blender.Object.GetSelected()[0].getData().getKey().getIpo().getNcurves()):
etape=3
#on lance la creation du dictionnaire
recuperation_courbe()
else:
print "not the good number of IPO Curve"
etape = 0
else:
print "error: bad object Type:"
print Blender.Object.GetSelected()[0].getType()
etape = 0
except:
print 'error: exception'
etape = 0
#voici le fichier dictionnaire
mon_fichier_dico=""
#voici le fichier export pamela
mon_fichier_export=""
let01selectkey = Create(0)
let02selectkey = Create(0)
let03selectkey = Create(0)
let04selectkey = Create(0)
let05selectkey = Create(0)
let06selectkey = Create(0)
let07selectkey = Create(0)
let08selectkey = Create(0)
let09selectkey = Create(0)
let10selectkey = Create(0)
let11selectkey = Create(0)
let12selectkey = Create(0)
let13selectkey = Create(0)
let14selectkey = Create(0)
let15selectkey = Create(0)
let16selectkey = Create(0)
let17selectkey = Create(0)
let18selectkey = Create(0)
let19selectkey = Create(0)
let20selectkey = Create(0)
let21selectkey = Create(0)
let22selectkey = Create(0)
let23selectkey = Create(0)
let24selectkey = Create(0)
Register (trace,event,bevent)

View File

@@ -1,121 +0,0 @@
Version 3.233-2004
******************
Espanol
Sale del programa
Utilidades de...%t|Alinea objetos%x1|Creacion%x2|Edita mallas%x3|Edita objetos%x4
11
Mov
Esc
Encaja
Abarca
Separa
Alinea
Rota
Incr.
Crea nuevos objetos
Es+
Es*
Separar entre:%t|Origenes%x1|Centros geometricos%x2|Minimos%x3|Maximos%x4|Baricentro%x5|Objetos%x6
Crear%t|Arco (3 ptos.)%x1|Arco (interactivo)%x2|Circunferencia (3 ptos.)%x3
12
Puntos
Centro
Orden
Objeto
AngIni:
AngFin:
Angulo:
Radio:
Puntos:
Centro
Nombre:
Puntos
Modifica vertices%t|Subdivide%x1|Envia a un plano%x2|Aplica LocRotSize%x3
Partes
Proyectar en el plano:%t|Coordenado global...%x1|Coordenado local...%x2
Actuar sobre el plano%t|Yz%x1|Zx%x2|Xy%x3
En la direcci<63>n%t|X%x1|Y%x2|Z%x3|Ortogonal al plano%x4
Captura
Buffer%t|Copia vector diferencia%x1|Copia distancia%x2|Copia diferencia de rotacion%x3|Copia media LocRotSiz%x4|Ver buffer en consola%x5
Transformar LocRotSize%t|Hacia el obj. activo%x1|Aleatoriamente%x2
Poner a distancia fija%x1|Sumar (desp. absoluto)%x2|Multiplicar (desp. relativo)%x3
********************
English
Exit program
Utils about:%t|Align Objects%x1|Create%x2|Edit Meshes%x3|Edit Objects%x4
11
Mov
Sca
Fit
Embrace
Separate
Align
Rota
Incr.
Create new objects
Sc+
Sc*
Separate between:%t|Origins%x1|Geometric centers%x2|Minimum%x3|Maximum%x4|Baricenter%x5|Objects%x6
Create what%t|Arc (3 pts.)%x1|Arc (interactive)%x2|Circunference (3 pts.)%x3
12
Points
Centre
Sort
Object
AngIni:
AngEnd:
Angle:
Radius:
Points:
Centre
ObjName:
Points
Modify vertices%t|Subdivide edges%x1|Send to a plane%x2|Set LocRotSize%x3
Parts
Project onto the plane:%t|Global coordinated...%x1|Local coordinated...%x2
Act on plane%t|Yz%x1|Zx%x2|Xy%x3
In direction%t|X%x1|Y%x2|Z%x3|Ortogonal to plane%x4
Get
Buffer%t|Copy diference vector%x1|Copy distance%x2|Copy rot diference%x3|Copy LocRotSiz average%x4|Show Buffer in Console%x5
Transform LocRotSize%t|Close to active%x1|Randomly%x2
Set at fixed distance%x1|Add (absolute displ.)%x2|Multiply (relative displ.)%x3
********************
Catala
Surt del programa
Utilitats de...%t|Alinea objectes%x1|Creacio%x2|Edita malles%x3|Edita objetes%x4
11
Mov
Esc
Encaixa
Abarca
Separa
Alinea
Rotacio
Incr.
Crea objectes nous
Es+
Es*
Separa entra:%t|Origens%x1|Centres geometrics%x2|Minims%x3|Maxims%x4|Baricentre%x5|Objectes%x6
Crear%t|Arc (3 pts.)%x1|Arc (interactiu)%x2|Circumferencia (3 pts.)%x3
12
Punts
Centre
Ordre
Objecte
AngIni:
AngFi:
Angle:
Radi:
Punts:
Centre
Nom:
Punts
Modifica vertex%t|Subdivideix%x1|Envia a un pla%x2|Aplica LocRotSize%x3
Parts
Projectar en el pla:%t|Coordenacio global...%x1|Coordenacio local...%x2
Actuar sobre el pla%t|Yz%x1|Zx%x2|Xy%x3
En la direccio%t|X%x1|Y%x2|Z%x3|Ortogonal al pla%x4
Captura
Buffer%t|Copia vector diferencia%x1|Copia distancia%x2|Copia diferencia de rotacio%x3|Copia mitjana LocRotSiz%x4|Veure buffer en consola%x5
Transformar LocRotSize%t|Cap al obj. actiu%x1|Aleatoriamente%x2
Posar a distancia fixa%x1|Sumar (desp. absolut)%x2|Multiplicar (desp. relatiu)%x3

View File

@@ -1,6 +0,0 @@
This folder is for automatically saved scripts configuration data.
To use this feature scripts just need to set a proper Blender.Registry key.
To know more, check the API Reference doc (specifically the API_related and
Registry parts) and the documentation for the "Scripts Config Editor" script.

View File

@@ -1,9 +0,0 @@
This directory is the default place for scripts to put their data,
like internal files needed by the script and its saved configuration.
Scripts can find the path to this dir using Blender.Get("datadir").
Ex:
import Blender
print Blender.Get("datadir")

View File

@@ -1,159 +0,0 @@
import Blender
from Blender.Window import EditMode, GetCursorPos, GetViewQuat
import bpy
import BPyMessages
def add_mesh_simple(name, verts, edges, faces):
'''
Adds a mesh from verts, edges and faces
name - new object/mesh name
verts - list of 3d vectors
edges - list of int pairs
faces - list of int triplets/quads
'''
scn = bpy.data.scenes.active
if scn.lib: return
ob_act = scn.objects.active
is_editmode = EditMode()
cursor = GetCursorPos()
quat = None
if is_editmode or Blender.Get('add_view_align'): # Aligning seems odd for editmode, but blender does it, oh well
try: quat = Blender.Mathutils.Quaternion(GetViewQuat())
except: pass
# Exist editmode for non mesh types
if ob_act and ob_act.type != 'Mesh' and is_editmode:
EditMode(0)
# We are in mesh editmode
if EditMode():
me = ob_act.getData(mesh=1)
if me.multires:
BPyMessages.Error_NoMeshMultiresEdit()
return
# Add to existing mesh
# must exit editmode to modify mesh
EditMode(0)
me.sel = False
vert_offset = len(me.verts)
edge_offset = len(me.edges)
face_offset = len(me.faces)
# transform the verts
txmat = Blender.Mathutils.TranslationMatrix(Blender.Mathutils.Vector(cursor))
if quat:
mat = quat.toMatrix()
mat.invert()
mat.resize4x4()
txmat = mat * txmat
txmat = txmat * ob_act.matrixWorld.copy().invert()
me.verts.extend(verts)
# Transform the verts by the cursor and view rotation
me.transform(txmat, selected_only=True)
if vert_offset:
me.edges.extend([[i+vert_offset for i in e] for e in edges])
me.faces.extend([[i+vert_offset for i in f] for f in faces])
else:
# Mesh with no data, unlikely
me.edges.extend(edges)
me.faces.extend(faces)
else:
# Object mode add new
me = bpy.data.meshes.new(name)
me.verts.extend(verts)
me.edges.extend(edges)
me.faces.extend(faces)
me.sel = True
# Object creation and location
scn.objects.selected = []
ob_act = scn.objects.new(me, name)
scn.objects.active = ob_act
if quat:
mat = quat.toMatrix()
mat.invert()
mat.resize4x4()
ob_act.setMatrix(mat)
ob_act.loc = cursor
me.calcNormals()
if is_editmode or Blender.Get('add_editmode'):
EditMode(1)
def write_mesh_script(filepath, me):
'''
filepath - path to py file
me - mesh to write
'''
name = me.name
file = open(filepath, 'w')
file.write('#!BPY\n')
file.write('"""\n')
file.write('Name: \'%s\'\n' % name)
file.write('Blender: 245\n')
file.write('Group: \'AddMesh\'\n')
file.write('"""\n\n')
file.write('import BPyAddMesh\n')
file.write('from Blender.Mathutils import Vector\n\n')
file.write('verts = [\\\n')
for v in me.verts:
file.write('Vector(%f,%f,%f),\\\n' % tuple(v.co))
file.write(']\n')
file.write('edges = []\n') # TODO, write loose edges
file.write('faces = [\\\n')
for f in me.faces:
file.write('%s,\\\n' % str(tuple([v.index for v in f])))
file.write(']\n')
file.write('BPyAddMesh.add_mesh_simple("%s", verts, edges, faces)\n' % name)
# The script below can make a file from a mesh with teh above function...
'''
#!BPY
"""
Name: 'Mesh as AddMesh Script'
Blender: 242
Group: 'Mesh'
Tip: ''
"""
import BPyAddMesh
reload(BPyAddMesh)
import bpy
def main():
# Add error checking
scn = bpy.data.scenes.active
ob = scn.objects.active
me = ob.getData(mesh=1)
BPyAddMesh.write_mesh_script('/test.py', me)
main()
'''

View File

@@ -1,152 +0,0 @@
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
# Version History:
# 1.0 original release bakes an armature into a matrix
# 1.1 optional params (ACTION_BAKE, ACTION_BAKE_FIRST_FRAME, direct function to key and return the Action
import Blender
from Blender import sys
import bpy
def getBakedPoseData(ob_arm, start_frame, end_frame, ACTION_BAKE = False, ACTION_BAKE_FIRST_FRAME = True):
'''
If you are currently getting IPO's this function can be used to
ACTION_BAKE==False: return a list of frame aligned bone dictionary's
ACTION_BAKE==True: return an action with keys aligned to bone constrained movement
if ACTION_BAKE_FIRST_FRAME is not supplied or is true: keys begin at frame 1
The data in these can be swaped in for the IPO loc and quat
If you want to bake an action, this is not as hard and the ipo hack can be removed.
'''
# --------------------------------- Dummy Action! Only for this functon
backup_action = ob_arm.action
backup_frame = Blender.Get('curframe')
DUMMY_ACTION_NAME = '~DONT_USE~'
# Get the dummy action if it has no users
try:
new_action = bpy.data.actions[DUMMY_ACTION_NAME]
if new_action.users:
new_action = None
except:
new_action = None
if not new_action:
new_action = bpy.data.actions.new(DUMMY_ACTION_NAME)
new_action.fakeUser = False
# ---------------------------------- Done
Matrix = Blender.Mathutils.Matrix
Quaternion = Blender.Mathutils.Quaternion
Vector = Blender.Mathutils.Vector
POSE_XFORM= [Blender.Object.Pose.LOC, Blender.Object.Pose.ROT]
# Each dict a frame
bake_data = [{} for i in xrange(1+end_frame-start_frame)]
pose= ob_arm.getPose()
armature_data= ob_arm.getData();
pose_bones= pose.bones
# --------------------------------- Build a list of arma data for reuse
armature_bone_data = []
bones_index = {}
for bone_name, rest_bone in armature_data.bones.items():
pose_bone = pose_bones[bone_name]
rest_matrix = rest_bone.matrix['ARMATURESPACE']
rest_matrix_inv = rest_matrix.copy().invert()
armature_bone_data.append( [len(bones_index), -1, bone_name, rest_bone, rest_matrix, rest_matrix_inv, pose_bone, None ])
bones_index[bone_name] = len(bones_index)
# Set the parent ID's
for bone_name, pose_bone in pose_bones.items():
parent = pose_bone.parent
if parent:
bone_index= bones_index[bone_name]
parent_index= bones_index[parent.name]
armature_bone_data[ bone_index ][1]= parent_index
# ---------------------------------- Done
# --------------------------------- Main loop to collect IPO data
frame_index = 0
NvideoFrames= end_frame-start_frame
for current_frame in xrange(start_frame, end_frame+1):
if frame_index==0: start=sys.time()
elif frame_index==15: print NvideoFrames*(sys.time()-start),"seconds estimated..." #slows as it grows *3
elif frame_index >15:
percom= frame_index*100/NvideoFrames
print "Frame %i Overall %i percent complete\r" % (current_frame, percom),
ob_arm.action = backup_action
#pose.update() # not needed
Blender.Set('curframe', current_frame)
#Blender.Window.RedrawAll()
#frame_data = bake_data[frame_index]
ob_arm.action = new_action
###for i,pose_bone in enumerate(pose_bones):
for index, parent_index, bone_name, rest_bone, rest_matrix, rest_matrix_inv, pose_bone, ipo in armature_bone_data:
matrix= pose_bone.poseMatrix
parent_bone= rest_bone.parent
if parent_index != -1:
parent_pose_matrix = armature_bone_data[parent_index][6].poseMatrix
parent_bone_matrix_inv = armature_bone_data[parent_index][5]
matrix= matrix * parent_pose_matrix.copy().invert()
rest_matrix= rest_matrix * parent_bone_matrix_inv
matrix=matrix * rest_matrix.copy().invert()
pose_bone.quat= matrix.toQuat()
pose_bone.loc= matrix.translationPart()
if ACTION_BAKE==False:
pose_bone.insertKey(ob_arm, 1, POSE_XFORM) # always frame 1
# THIS IS A BAD HACK! IT SUCKS BIGTIME BUT THE RESULT ARE NICE
# - use a temp action and bake into that, always at the same frame
# so as not to make big IPO's, then collect the result from the IPOs
# Now get the data from the IPOs
if not ipo: ipo = armature_bone_data[index][7] = new_action.getChannelIpo(bone_name)
loc = Vector()
quat = Quaternion()
for curve in ipo:
val = curve.evaluate(1)
curve_name= curve.name
if curve_name == 'LocX': loc[0] = val
elif curve_name == 'LocY': loc[1] = val
elif curve_name == 'LocZ': loc[2] = val
elif curve_name == 'QuatW': quat[3] = val
elif curve_name == 'QuatX': quat[0] = val
elif curve_name == 'QuatY': quat[1] = val
elif curve_name == 'QuatZ': quat[2] = val
bake_data[frame_index][bone_name] = loc, quat
else:
if ACTION_BAKE_FIRST_FRAME: pose_bone.insertKey(ob_arm, frame_index+1, POSE_XFORM)
else: pose_bone.insertKey(ob_arm, current_frame , POSE_XFORM)
frame_index+=1
print "\nBaking Complete."
ob_arm.action = backup_action
if ACTION_BAKE==False:
Blender.Set('curframe', backup_frame)
return bake_data
elif ACTION_BAKE==True:
return new_action
else: print "ERROR: Invalid ACTION_BAKE %i sent to BPyArmature" % ACTION_BAKE

View File

@@ -1,36 +0,0 @@
# $Id$
#
# --------------------------------------------------------------------------
# BPyBlender.py version 0.3 Mar 20, 2005
# --------------------------------------------------------------------------
# helper functions to be used by other scripts
# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
# Basic set of modules Blender should have in all supported platforms.
# The second and third lines are the contents of the Python23.zip file
# included with Windows Blender binaries along with zlib.pyd.
# Other platforms are assumed to have Python installed.
basic_modules = [
'Blender',
'chunk','colorsys','copy','copy_reg','gzip','os','random','repr','stat',
'string','StringIO','types','UserDict','webbrowser', 'zlib', 'math',
'BPyBlender', 'BPyRegistry'
]

View File

@@ -1,79 +0,0 @@
# --------------------------------------------------------------------------
# BPyImage.py version 0.15
# --------------------------------------------------------------------------
# helper functions to be used by other scripts
# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
from Blender import *
def curve2vecs(ob, WORLDSPACE= True):
'''
Takes a curve object and retuirns a list of vec lists (polylines)
one list per curve
This is usefull as a way to get a polyline per curve
so as not to have to deal with the spline types directly
'''
if ob.type != 'Curve':
raise 'must be a curve object'
me_dummy = Mesh.New()
me_dummy.getFromObject(ob)
if WORLDSPACE:
me_dummy.transform(ob.matrixWorld)
# build an edge dict
edges = {} # should be a set
def sort_pair(i1, i2):
if i1 > i2: return i2, i1
else: return i1, i2
for ed in me_dummy.edges:
edges[sort_pair(ed.v1.index,ed.v2.index)] = None # dummy value
# now set the curves
first_time = True
current_vecs = []
vec_list = [current_vecs]
for v in me_dummy.verts:
if first_time:
first_time = False
current_vecs.append(v.co.copy())
last_index = v.index
else:
index = v.index
if edges.has_key(sort_pair(index, last_index)):
current_vecs.append( v.co.copy() )
else:
current_vecs = []
vec_list.append(current_vecs)
last_index = index
me_dummy.verts = None
return vec_list

View File

@@ -1,318 +0,0 @@
# --------------------------------------------------------------------------
# BPyImage.py version 0.15
# --------------------------------------------------------------------------
# helper functions to be used by other scripts
# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
#===========================================================================#
# Comprehensive image loader, will search and find the image #
# Will return a blender image or a new image if the image is missing #
#===========================================================================#
import bpy
from Blender import sys
try:
import os
except:
os=None
#==============================================#
# Return directory, where the file is #
#==============================================#
def stripFile(path):
lastSlash = max(path.rfind('\\'), path.rfind('/'))
if lastSlash != -1:
path = path[:lastSlash]
newpath= '%s%s' % (path, sys.sep)
else:
newpath= path
return newpath
#==============================================#
# Strips the slashes from the back of a string #
#==============================================#
def stripPath(path):
return path.split('/')[-1].split('\\')[-1]
#====================================================#
# Strips the prefix off the name before writing #
#====================================================#
def stripExt(name): # name is a string
index = name.rfind('.')
if index != -1:
return name[ : index ]
else:
return name
def getExt(name):
index = name.rfind('.')
if index != -1:
return name[index+1:]
return name
#====================================================#
# Adds a slash to the end of a path if its not there #
#====================================================#
def addSlash(path):
if not path:
return ''
elif path.endswith('\\') or path.endswith('/'):
return path
return path + sys.sep
def comprehensiveImageLoad(imagePath, filePath, PLACE_HOLDER= True, RECURSIVE=True, VERBOSE=False, CONVERT_CALLBACK=None):
'''
imagePath: The image filename
If a path precedes it, this will be searched as well.
filePath: is the directory where the image may be located - any file at teh end will be ignored.
PLACE_HOLDER: if True a new place holder image will be created.
this is usefull so later you can relink the image to its original data.
VERBOSE: If True debug info will be printed.
RECURSIVE: If True, directories will be recursivly searched.
Be carefull with this if you have files in your root directory because it may take a long time.
CASE_INSENSITIVE: for non win32 systems, find the correct case for the file.
CONVERT_CALLBACK: a function that takes an existing path and returns a new one.
Use this when loading image formats blender may not support, the CONVERT_CALLBACK
can take the path for a GIF (for example), convert it to a PNG and return the PNG's path.
For formats blender can read, simply return the path that is given.
'''
# VERBOSE = True
if VERBOSE: print 'img:', imagePath, 'file:', filePath
if os == None and CASE_INSENSITIVE:
CASE_INSENSITIVE = True
# When we have the file load it with this. try/except niceness.
def imageLoad(path):
#if path.endswith('\\') or path.endswith('/'):
# raise 'INVALID PATH'
if CONVERT_CALLBACK:
path = CONVERT_CALLBACK(path)
try:
img = bpy.data.images.new(filename=path)
if VERBOSE: print '\t\tImage loaded "%s"' % path
return img
except:
if VERBOSE:
if sys.exists(path): print '\t\tImage failed loading "%s", mabe its not a format blender can read.' % (path)
else: print '\t\tImage not found, making a place holder "%s"' % (path)
if PLACE_HOLDER:
img= bpy.data.images.new(stripPath(path),4,4)
img.filename= path
return img #blank image
else:
return None
# Image formats blender can read
IMAGE_EXT = ['jpg', 'jpeg', 'png', 'tga', 'bmp', 'rgb', 'sgi', 'bw', 'iff', 'lbm', # Blender Internal
'gif', 'psd', 'tif', 'tiff', 'pct', 'pict', 'pntg', 'qtif'] # Quacktime, worth a try.
imageFileName = stripPath(imagePath) # image path only
imageFileName_lower = imageFileName.lower() # image path only
if VERBOSE: print '\tSearchingExisting Images for "%s"' % imagePath
for i in bpy.data.images:
if stripPath(i.filename.lower()) == imageFileName_lower:
if VERBOSE: print '\t\tUsing existing image.'
return i
if VERBOSE: print '\tAttempting to load "%s"' % imagePath
if sys.exists(imagePath):
if VERBOSE: print '\t\tFile found where expected "%s".' % imagePath
return imageLoad(imagePath)
imageFileName_noext = stripExt(imageFileName) # With no extension.
imageFileName_noext_lower = stripExt(imageFileName_lower) # With no extension.
imageFilePath = stripFile(imagePath)
# Remove relative path from image path
if imageFilePath.startswith('./') or imageFilePath.startswith('.\\'):
imageFilePath = imageFilePath[2:]
# Attempt to load from obj path.
tmpPath = stripFile(filePath) + stripPath(imageFileName)
if sys.exists(tmpPath):
if VERBOSE: print '\t\tFile found in path (1)"%s".' % tmpPath
return imageLoad(tmpPath)
# os needed if we go any further.
if not os:
if VERBOSE: print '\t\tCreating a placeholder with a face path: "%s".' % imagePath
return imageLoad(imagePath) # Will jus treturn a placeholder.
# We have os.
# GATHER PATHS.
paths = {} # Store possible paths we may use, dict for no doubles.
tmpPath = addSlash(sys.expandpath('//')) # Blenders path
if sys.exists(tmpPath):
if VERBOSE: print '\t\tSearching in %s' % tmpPath
paths[tmpPath] = [os.listdir(tmpPath)] # Orig name for loading
paths[tmpPath].append([f.lower() for f in paths[tmpPath][0]]) # Lower case list.
paths[tmpPath].append([stripExt(f) for f in paths[tmpPath][1]]) # Lower case no ext
else:
if VERBOSE: print '\tNo Path: "%s"' % tmpPath
tmpPath = imageFilePath
if sys.exists(tmpPath):
if VERBOSE: print '\t\tSearching in %s' % tmpPath
paths[tmpPath] = [os.listdir(tmpPath)] # Orig name for loading
paths[tmpPath].append([f.lower() for f in paths[tmpPath][0]]) # Lower case list.
paths[tmpPath].append([stripExt(f) for f in paths[tmpPath][1]]) # Lower case no ext
else:
if VERBOSE: print '\tNo Path: "%s"' % tmpPath
tmpPath = stripFile(filePath)
if sys.exists(tmpPath):
if VERBOSE: print '\t\tSearching in %s' % tmpPath
paths[tmpPath] = [os.listdir(tmpPath)] # Orig name for loading
paths[tmpPath].append([f.lower() for f in paths[tmpPath][0]]) # Lower case list.
paths[tmpPath].append([stripExt(f) for f in paths[tmpPath][1]]) # Lower case no ext
else:
if VERBOSE: print '\tNo Path: "%s"' % tmpPath
tmpPath = addSlash(bpy.config.textureDir)
if tmpPath and sys.exists(tmpPath):
if VERBOSE: print '\t\tSearching in %s' % tmpPath
paths[tmpPath] = [os.listdir(tmpPath)] # Orig name for loading
paths[tmpPath].append([f.lower() for f in paths[tmpPath][0]]) # Lower case list.
paths[tmpPath].append([stripExt(f) for f in paths[tmpPath][1]]) # Lower case no ext
else:
if VERBOSE: print '\tNo Path: "%s"' % tmpPath
# Add path if relative image patrh was given.
tmp_paths= paths.keys()
for k in tmp_paths:
tmpPath = k + imageFilePath
if sys.exists(tmpPath):
paths[tmpPath] = [os.listdir(tmpPath)] # Orig name for loading
paths[tmpPath].append([f.lower() for f in paths[tmpPath][0]]) # Lower case list.
paths[tmpPath].append([stripExt(f) for f in paths[tmpPath][1]]) # Lower case no ext
else:
if VERBOSE: print '\tNo Path: "%s"' % tmpPath
# DONE
#
for path, files in paths.iteritems():
if sys.exists(path + imageFileName):
if VERBOSE: print '\tFound image at path: "%s" file" "%s"' % (path, imageFileName)
return imageLoad(path + imageFileName)
# If the files not there then well do a case insensitive seek.
filesOrigCase = files[0]
filesLower = files[1]
filesLowerNoExt = files[2]
# We are going to try in index the file directly, if its not there just keep on
index = None
try:
# Is it just a case mismatch?
index = filesLower.index(imageFileName_lower)
except:
try:
# Have the extensions changed?
index = filesLowerNoExt.index(imageFileName_noext_lower)
ext = getExt( filesLower[index] ) # Get the extension of the file that matches all but ext.
# Check that the ext is useable eg- not a 3ds file :)
if ext.lower() not in IMAGE_EXT:
index = None
except:
index = None
if index != None:
tmpPath = path + filesOrigCase[index]
img = imageLoad( tmpPath )
if img != None:
if VERBOSE: print '\t\tImage Found "%s"' % tmpPath
return img
if RECURSIVE:
# IMAGE NOT FOUND IN ANY OF THE DIRS!, DO A RECURSIVE SEARCH.
if VERBOSE: print '\t\tImage Not Found in any of the dirs, doing a recusrive search'
for path in paths.iterkeys():
# Were not going to use files
if path == '/' or len(path) == 3 and path[1:] == ':\\':
continue
# print path , 'ASS'
#------------------
# finds the file starting at the root.
# def findImage(findRoot, imagePath):
#W---------------
# ROOT, DIRS, FILES
pathWalk = os.walk(path)
pathList = [True]
matchList = [] # Store a list of (match, size), choose the biggest.
while True:
try:
pathList = pathWalk.next()
except:
break
for file in pathList[2]:
file_lower = file.lower()
# FOUND A MATCH
if (file_lower == imageFileName_lower) or\
(stripExt(file_lower) == imageFileName_noext_lower and getExt(file_lower) in IMAGE_EXT):
name = pathList[0] + sys.sep + file
size = os.path.getsize(name)
if VERBOSE: print '\t\t\tfound:', name
matchList.append( (name, size) )
if matchList:
# Sort by file size
matchList.sort(lambda A, B: cmp(B[1], A[1]) )
if VERBOSE: print '\t\tFound "%s"' % matchList[0][0]
# Loop through all we have found
img = None
for match in matchList:
img = imageLoad(match[0]) # 0 - first, 0 - pathname
if img != None:
break
return img
# No go.
if VERBOSE: print '\t\tImage Not Found after looking everywhere! "%s"' % imagePath
return imageLoad(imagePath) # Will jus treturn a placeholder.

View File

@@ -1,228 +0,0 @@
# $Id$
#
# --------------------------------------------------------------------------
# helper functions to be used by other scripts
# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
import Blender
from Blender.Mathutils import *
# ------ Mersenne Twister - start
# Copyright (C) 1997 Makoto Matsumoto and Takuji Nishimura.
# Any feedback is very welcome. For any question, comments,
# see http://www.math.keio.ac.jp/matumoto/emt.html or email
# matumoto@math.keio.ac.jp
# The link above is dead, this is the new one:
# http://www.math.sci.hiroshima-u.ac.jp/m-mat/MT/emt.html
# And here the license info, from Mr. Matsumoto's site:
# Until 2001/4/6, MT had been distributed under GNU Public License,
# but after 2001/4/6, we decided to let MT be used for any purpose, including
# commercial use. 2002-versions mt19937ar.c, mt19937ar-cok.c are considered
# to be usable freely.
#
# So from the year above (1997), this code is under GPL.
# Period parameters
N = 624
M = 397
MATRIX_A = 0x9908b0dfL # constant vector a
UPPER_MASK = 0x80000000L # most significant w-r bits
LOWER_MASK = 0x7fffffffL # least significant r bits
# Tempering parameters
TEMPERING_MASK_B = 0x9d2c5680L
TEMPERING_MASK_C = 0xefc60000L
def TEMPERING_SHIFT_U(y):
return (y >> 11)
def TEMPERING_SHIFT_S(y):
return (y << 7)
def TEMPERING_SHIFT_T(y):
return (y << 15)
def TEMPERING_SHIFT_L(y):
return (y >> 18)
mt = [] # the array for the state vector
mti = N+1 # mti==N+1 means mt[N] is not initialized
# initializing the array with a NONZERO seed
def sgenrand(seed):
# setting initial seeds to mt[N] using
# the generator Line 25 of Table 1 in
# [KNUTH 1981, The Art of Computer Programming
# Vol. 2 (2nd Ed.), pp102]
global mt, mti
mt = []
mt.append(seed & 0xffffffffL)
for i in xrange(1, N + 1):
mt.append((69069 * mt[i-1]) & 0xffffffffL)
mti = i
# end sgenrand
def genrand():
global mt, mti
mag01 = [0x0L, MATRIX_A]
# mag01[x] = x * MATRIX_A for x=0,1
y = 0
if mti >= N: # generate N words at one time
if mti == N+1: # if sgenrand() has not been called,
sgenrand(4357) # a default initial seed is used
for kk in xrange((N-M) + 1):
y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK)
mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1]
for kk in xrange(kk, N):
y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK)
mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1]
y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK)
mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1]
mti = 0
y = mt[mti]
mti += 1
y ^= TEMPERING_SHIFT_U(y)
y ^= TEMPERING_SHIFT_S(y) & TEMPERING_MASK_B
y ^= TEMPERING_SHIFT_T(y) & TEMPERING_MASK_C
y ^= TEMPERING_SHIFT_L(y)
return ( float(y) / 0xffffffffL ) # reals
#------ Mersenne Twister -- end
""" 2d convexhull
Based from Dinu C. Gherman's work,
modified for Blender/Mathutils by Campell Barton
"""
######################################################################
# Public interface
######################################################################
def convexHull(point_list_2d):
"""Calculate the convex hull of a set of vectors
The vectors can be 3 or 4d but only the Xand Y are used.
returns a list of convex hull indicies to the given point list
"""
######################################################################
# Helpers
######################################################################
def _myDet(p, q, r):
"""Calc. determinant of a special matrix with three 2D points.
The sign, "-" or "+", determines the side, right or left,
respectivly, on which the point r lies, when measured against
a directed vector from p to q.
"""
return (q.x*r.y + p.x*q.y + r.x*p.y) - (q.x*p.y + r.x*q.y + p.x*r.y)
def _isRightTurn((p, q, r)):
"Do the vectors pq:qr form a right turn, or not?"
#assert p[0] != q[0] and q[0] != r[0] and p[0] != r[0]
if _myDet(p[0], q[0], r[0]) < 0:
return 1
else:
return 0
# Get a local list copy of the points and sort them lexically.
points = [(p, i) for i, p in enumerate(point_list_2d)]
try: points.sort(key = lambda a: (a[0].x, a[0].y))
except: points.sort(lambda a,b: cmp((a[0].x, a[0].y), (b[0].x, b[0].y)))
# Build upper half of the hull.
upper = [points[0], points[1]] # cant remove these.
for i in xrange(len(points)-2):
upper.append(points[i+2])
while len(upper) > 2 and not _isRightTurn(upper[-3:]):
del upper[-2]
# Build lower half of the hull.
points.reverse()
lower = [points.pop(0), points.pop(1)]
for p in points:
lower.append(p)
while len(lower) > 2 and not _isRightTurn(lower[-3:]):
del lower[-2]
# Concatenate both halfs and return.
return [p[1] for ls in (upper, lower) for p in ls]
def plane2mat(plane, normalize= False):
'''
Takes a plane and converts to a matrix
points between 0 and 1 are up
1 and 2 are right
assumes the plane has 90d corners
'''
cent= (plane[0]+plane[1]+plane[2]+plane[3] ) /4.0
up= cent - ((plane[0]+plane[1])/2.0)
right= cent - ((plane[1]+plane[2])/2.0)
z= up.cross(right)
if normalize:
up.normalize()
right.normalize()
z.normalize()
mat= Matrix(up, right, z)
# translate
mat.resize4x4()
tmat= Blender.Mathutils.TranslationMatrix(cent)
return mat * tmat
# Used for mesh_solidify.py and mesh_wire.py
# returns a length from an angle
# Imaging a 2d space.
# there is a hoz line at Y1 going to inf on both X ends, never moves (LINEA)
# down at Y0 is a unit length line point up at (angle) from X0,Y0 (LINEB)
# This function returns the length of LINEB at the point it would intersect LINEA
# - Use this for working out how long to make the vector - differencing it from surrounding faces,
# import math
from math import pi, sin, cos, sqrt
def angleToLength(angle):
# Alredy accounted for
if angle < 0.000001: return 1.0
else: return abs(1.0 / cos(pi*angle/180));

File diff suppressed because it is too large Load Diff

View File

@@ -1,652 +0,0 @@
# ***** BEGIN GPL LICENSE BLOCK *****
#
# (C) Copyright 2006 MetaVR, Inc.
# http://www.metavr.com
# Written by Campbell Barton
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
import Blender
import bpy
Vector= Blender.Mathutils.Vector
Ang= Blender.Mathutils.AngleBetweenVecs
MidpointVecs= Blender.Mathutils.MidpointVecs
import BPyMesh
# If python version is less than 2.4, try to get set stuff from module
try:
set
except:
try:
from sets import Set as set
except:
set= None
def uv_key(uv):
return round(uv.x, 5), round(uv.y, 5)
def uv_key_mix(uv1, uv2, w1, w2):
# Weighted mix. w1+w2==1.0
return w1*uv1[0]+w2*uv2[0], w1*uv1[1]+w2*uv2[1]
def col_key(col):
return col.r, col.g, col.b
def col_key_mix(col1, col2, w1, w2):
# Weighted mix. w1+w2==1.0
return int(w1*col1[0] + w2*col2[0]), int(w1*col1[1] + w2*col2[1]), int(w1*col1[2]+col2[2]*w2)
def redux(ob, REDUX=0.5, BOUNDRY_WEIGHT=2.0, REMOVE_DOUBLES=False, FACE_AREA_WEIGHT=1.0, FACE_TRIANGULATE=True, DO_UV=True, DO_VCOL=True, DO_WEIGHTS=True, VGROUP_INF_REDUX= None, VGROUP_INF_WEIGHT=0.5):
"""
BOUNDRY_WEIGHT - 0 is no boundry weighting. 2.0 will make them twice as unlikely to collapse.
FACE_AREA_WEIGHT - 0 is no weight. 1 is normal, 2.0 is higher.
"""
if REDUX<0 or REDUX>1.0:
raise 'Error, factor must be between 0 and 1.0'
elif not set:
raise 'Error, this function requires Python 2.4 or a full install of Python 2.3'
BOUNDRY_WEIGHT= 1+BOUNDRY_WEIGHT
""" # DEBUG!
if Blender.Get('rt') == 1000:
DEBUG=True
else:
DEBUG= False
"""
me= ob.getData(mesh=1)
me.hide= False # unhide all data,.
if len(me.faces)<5:
return
if FACE_TRIANGULATE or REMOVE_DOUBLES:
me.sel= True
if FACE_TRIANGULATE:
me.quadToTriangle()
if REMOVE_DOUBLES:
me.remDoubles(0.0001)
vgroups= me.getVertGroupNames()
if not me.getVertGroupNames():
DO_WEIGHTS= False
if (VGROUP_INF_REDUX!= None and VGROUP_INF_REDUX not in vgroups) or\
VGROUP_INF_WEIGHT==0.0:
VGROUP_INF_REDUX= None
try:
VGROUP_INF_REDUX_INDEX= vgroups.index(VGROUP_INF_REDUX)
except:
VGROUP_INF_REDUX_INDEX= -1
# del vgroups
len_vgroups= len(vgroups)
OLD_MESH_MODE= Blender.Mesh.Mode()
Blender.Mesh.Mode(Blender.Mesh.SelectModes.VERTEX)
if DO_UV and not me.faceUV:
DO_UV= False
if DO_VCOL and not me.vertexColors:
DO_VCOL = False
current_face_count= len(me.faces)
target_face_count= int(current_face_count * REDUX)
# % of the collapseable faces to collapse per pass.
#collapse_per_pass= 0.333 # between 0.1 - lots of small nibbles, slow but high q. and 0.9 - big passes and faster.
collapse_per_pass= 0.333 # between 0.1 - lots of small nibbles, slow but high q. and 0.9 - big passes and faster.
"""# DEBUG!
if DEBUG:
COUNT= [0]
def rd():
if COUNT[0]< 330:
COUNT[0]+=1
return
me.update()
Blender.Window.RedrawAll()
print 'Press key for next, count "%s"' % COUNT[0]
try: input()
except KeyboardInterrupt:
raise "Error"
except:
pass
COUNT[0]+=1
"""
class collapseEdge(object):
__slots__ = 'length', 'key', 'faces', 'collapse_loc', 'v1', 'v2','uv1', 'uv2', 'col1', 'col2', 'collapse_weight'
def __init__(self, ed):
self.init_from_edge(ed) # So we can re-use the classes without using more memory.
def init_from_edge(self, ed):
self.key= ed.key
self.length= ed.length
self.faces= []
self.v1= ed.v1
self.v2= ed.v2
if DO_UV or DO_VCOL:
self.uv1= []
self.uv2= []
self.col1= []
self.col2= []
# self.collapse_loc= None # new collapse location.
# Basic weighting.
#self.collapse_weight= self.length * (1+ ((ed.v1.no-ed.v2.no).length**2))
self.collapse_weight= 1.0
def collapse_locations(self, w1, w2):
'''
Generate a smart location for this edge to collapse to
w1 and w2 are vertex location bias
'''
v1co= self.v1.co
v2co= self.v2.co
v1no= self.v1.no
v2no= self.v2.no
# Basic operation, works fine but not as good as predicting the best place.
#between= ((v1co*w1) + (v2co*w2))
#self.collapse_loc= between
# normalize the weights of each vert - se we can use them as scalers.
wscale= w1+w2
if not wscale: # no scale?
w1=w2= 0.5
else:
w1/=wscale
w2/=wscale
length= self.length
between= MidpointVecs(v1co, v2co)
# Collapse
# new_location = between # Replace tricky code below. this code predicts the best collapse location.
# Make lines at right angles to the normals- these 2 lines will intersect and be
# the point of collapsing.
# Enlarge so we know they intersect: self.length*2
cv1= v1no.cross(v1no.cross(v1co-v2co))
cv2= v2no.cross(v2no.cross(v2co-v1co))
# Scale to be less then the edge lengths.
cv2.length = cv1.length = 1
cv1 = cv1 * (length* 0.4)
cv2 = cv2 * (length* 0.4)
smart_offset_loc= between + (cv1 + cv2)
# Now we need to blend between smart_offset_loc and w1/w2
# you see were blending between a vert and the edges midpoint, so we cant use a normal weighted blend.
if w1 > 0.5: # between v1 and smart_offset_loc
#self.collapse_loc= v1co*(w2+0.5) + smart_offset_loc*(w1-0.5)
w2*=2
w1= 1-w2
new_loc_smart= v1co*w1 + smart_offset_loc*w2
else: # w between v2 and smart_offset_loc
w1*=2
w2= 1-w1
new_loc_smart= v2co*w2 + smart_offset_loc*w1
if new_loc_smart.x != new_loc_smart.x: # NAN LOCATION, revert to between
new_loc_smart= None
return new_loc_smart, between, v1co*0.99999 + v2co*0.00001, v1co*0.00001 + v2co*0.99999
class collapseFace(object):
__slots__ = 'verts', 'normal', 'area', 'index', 'orig_uv', 'orig_col', 'uv', 'col' # , 'collapse_edge_count'
def __init__(self, f):
self.init_from_face(f)
def init_from_face(self, f):
self.verts= f.v
self.normal= f.no
self.area= f.area
self.index= f.index
if DO_UV:
self.orig_uv= [uv_key(uv) for uv in f.uv]
self.uv= f.uv
if DO_VCOL:
self.orig_col= [col_key(col) for col in f.col]
self.col= f.col
collapse_edges= collapse_faces= None
# So meshCalcNormals can avoid making a new list all the time.
reuse_vertNormals= [ Vector() for v in xrange(len(me.verts)) ]
while target_face_count <= len(me.faces):
BPyMesh.meshCalcNormals(me, reuse_vertNormals)
if DO_WEIGHTS:
#groupNames, vWeightDict= BPyMesh.meshWeight2Dict(me)
groupNames, vWeightList= BPyMesh.meshWeight2List(me)
# THIS CRASHES? Not anymore.
verts= list(me.verts)
edges= list(me.edges)
faces= list(me.faces)
# THIS WORKS
#verts= me.verts
#edges= me.edges
#faces= me.faces
# if DEBUG: DOUBLE_CHECK= [0]*len(verts)
me.sel= False
if not collapse_faces: # Initialize the list.
collapse_faces= [collapseFace(f) for f in faces]
collapse_edges= [collapseEdge(ed) for ed in edges]
else:
for i, ed in enumerate(edges):
collapse_edges[i].init_from_edge(ed)
# Strip the unneeded end off the list
collapse_edges[i+1:]= []
for i, f in enumerate(faces):
collapse_faces[i].init_from_face(f)
# Strip the unneeded end off the list
collapse_faces[i+1:]= []
collapse_edges_dict= dict( [(ced.key, ced) for ced in collapse_edges] )
# Store verts edges.
vert_ed_users= [[] for i in xrange(len(verts))]
for ced in collapse_edges:
vert_ed_users[ced.key[0]].append(ced)
vert_ed_users[ced.key[1]].append(ced)
# Store face users
vert_face_users= [[] for i in xrange(len(verts))]
# Have decieded not to use this. area is better.
#face_perim= [0.0]* len(me.faces)
for ii, cfa in enumerate(collapse_faces):
for i, v1 in enumerate(cfa.verts):
vert_face_users[v1.index].append( (i,cfa) )
# add the uv coord to the vert
v2 = cfa.verts[i-1]
i1= v1.index
i2= v2.index
if i1>i2: ced= collapse_edges_dict[i2,i1]
else: ced= collapse_edges_dict[i1,i2]
ced.faces.append(cfa)
if DO_UV or DO_VCOL:
# if the edge is flipped from its order in the face then we need to flip the order indicies.
if cfa.verts[i]==ced.v1: i1,i2 = i, i-1
else: i1,i2 = i-1, i
if DO_UV:
ced.uv1.append( cfa.orig_uv[i1] )
ced.uv2.append( cfa.orig_uv[i2] )
if DO_VCOL:
ced.col1.append( cfa.orig_col[i1] )
ced.col2.append( cfa.orig_col[i2] )
# PERIMITER
#face_perim[ii]+= ced.length
# How weight the verts by the area of their faces * the normal difference.
# when the edge collapses, to vert weights are taken into account
vert_weights= [0.5] * len(verts)
for ii, vert_faces in enumerate(vert_face_users):
for f in vert_faces:
try:
no_ang= (Ang(verts[ii].no, f[1].normal)/180) * f[1].area
except:
no_ang= 1.0
vert_weights[ii] += no_ang
# Use a vertex group as a weighting.
if VGROUP_INF_REDUX!=None:
# Get Weights from a vgroup.
"""
vert_weights_map= [1.0] * len(verts)
for i, wd in enumerate(vWeightDict):
try: vert_weights_map[i]= 1+(wd[VGROUP_INF_REDUX] * VGROUP_INF_WEIGHT)
except: pass
"""
vert_weights_map= [1+(wl[VGROUP_INF_REDUX_INDEX]*VGROUP_INF_WEIGHT) for wl in vWeightList ]
# BOUNDRY CHECKING AND WEIGHT EDGES. CAN REMOVE
# Now we know how many faces link to an edge. lets get all the boundry verts
if BOUNDRY_WEIGHT > 0:
verts_boundry= [1] * len(verts)
#for ed_idxs, faces_and_uvs in edge_faces_and_uvs.iteritems():
for ced in collapse_edges:
if len(ced.faces) < 2:
for key in ced.key: # only ever 2 key indicies.
verts_boundry[key]= 2
for ced in collapse_edges:
b1= verts_boundry[ced.key[0]]
b2= verts_boundry[ced.key[1]]
if b1 != b2:
# Edge has 1 boundry and 1 non boundry vert. weight higher
ced.collapse_weight= BOUNDRY_WEIGHT
#elif b1==b2==2: # if both are on a seam then weigh half as bad.
# ced.collapse_weight= ((BOUNDRY_WEIGHT-1)/2) +1
# weight the verts by their boundry status
del b1
del b2
for ii, boundry in enumerate(verts_boundry):
if boundry==2:
vert_weights[ii] *= BOUNDRY_WEIGHT
vert_collapsed= verts_boundry
del verts_boundry
else:
vert_collapsed= [1] * len(verts)
# Best method, no quick hacks here, Correction. Should be the best but needs tweaks.
def ed_set_collapse_error(ced):
# Use the vertex weights to bias the new location.
new_locs= ced.collapse_locations(vert_weights[ced.key[0]], vert_weights[ced.key[1]])
# Find the connecting faces of the 2 verts.
i1, i2= ced.key
test_faces= set()
for i in (i1,i2): # faster then LC's
for f in vert_face_users[i]:
test_faces.add(f[1].index)
for f in ced.faces:
test_faces.remove(f.index)
v1_orig= Vector(ced.v1.co)
v2_orig= Vector(ced.v2.co)
def test_loc(new_loc):
'''
Takes a location and tests the error without changing anything
'''
new_weight= ced.collapse_weight
ced.v1.co= ced.v2.co= new_loc
new_nos= [faces[i].no for i in test_faces]
# So we can compare the befire and after normals
ced.v1.co= v1_orig
ced.v2.co= v2_orig
# now see how bad the normals are effected
angle_diff= 1.0
for ii, i in enumerate(test_faces): # local face index, global face index
cfa= collapse_faces[i] # this collapse face
try:
# can use perim, but area looks better.
if FACE_AREA_WEIGHT:
# Psudo code for wrighting
# angle_diff= The before and after angle difference between the collapsed and un-collapsed face.
# ... devide by 180 so the value will be between 0 and 1.0
# ... add 1 so we can use it as a multiplyer and not make the area have no eefect (below)
# area_weight= The faces original area * the area weight
# ... add 1.0 so a small area face dosent make the angle_diff have no effect.
#
# Now multiply - (angle_diff * area_weight)
# ... The weight will be a minimum of 1.0 - we need to subtract this so more faces done give the collapse an uneven weighting.
angle_diff+= ((1+(Ang(cfa.normal, new_nos[ii])/180)) * (1+(cfa.area * FACE_AREA_WEIGHT))) -1 # 4 is how much to influence area
else:
angle_diff+= (Ang(cfa.normal), new_nos[ii])/180
except:
pass
# This is very arbirary, feel free to modify
try: no_ang= (Ang(ced.v1.no, ced.v2.no)/180) + 1
except: no_ang= 2.0
# do *= because we face the boundry weight to initialize the weight. 1.0 default.
new_weight *= ((no_ang * ced.length) * (1-(1/angle_diff)))# / max(len(test_faces), 1)
return new_weight
# End testloc
# Test the collapse locatons
collapse_loc_best= None
collapse_weight_best= 1000000000
ii= 0
for collapse_loc in new_locs:
if collapse_loc: # will only ever fail if smart loc is NAN
test_weight= test_loc(collapse_loc)
if test_weight < collapse_weight_best:
iii= ii
collapse_weight_best = test_weight
collapse_loc_best= collapse_loc
ii+=1
ced.collapse_loc= collapse_loc_best
ced.collapse_weight= collapse_weight_best
# are we using a weight map
if VGROUP_INF_REDUX:
v= vert_weights_map[i1]+vert_weights_map[i2]
ced.collapse_weight*= v
# End collapse Error
# We can calculate the weights on __init__ but this is higher qualuity.
for ced in collapse_edges:
if ced.faces: # dont collapse faceless edges.
ed_set_collapse_error(ced)
# Wont use the function again.
del ed_set_collapse_error
# END BOUNDRY. Can remove
# sort by collapse weight
try: collapse_edges.sort(key = lambda ced: ced.collapse_weight) # edges will be used for sorting
except: collapse_edges.sort(lambda ced1, ced2: cmp(ced1.collapse_weight, ced2.collapse_weight)) # edges will be used for sorting
vert_collapsed= [0]*len(verts)
collapse_edges_to_collapse= []
# Make a list of the first half edges we can collapse,
# these will better edges to remove.
collapse_count=0
for ced in collapse_edges:
if ced.faces:
i1, i2= ced.key
# Use vert selections
if vert_collapsed[i1] or vert_collapsed[i2]:
pass
else:
# Now we know the verts havnyt been collapsed.
vert_collapsed[i2]= vert_collapsed[i1]= 1 # Dont collapse again.
collapse_count+=1
collapse_edges_to_collapse.append(ced)
# Get a subset of the entire list- the first "collapse_per_pass", that are best to collapse.
if collapse_count > 4:
collapse_count = int(collapse_count*collapse_per_pass)
else:
collapse_count = len(collapse_edges)
# We know edge_container_list_collapse can be removed.
for ced in collapse_edges_to_collapse:
"""# DEBUG!
if DEBUG:
if DOUBLE_CHECK[ced.v1.index] or\
DOUBLE_CHECK[ced.v2.index]:
raise 'Error'
else:
DOUBLE_CHECK[ced.v1.index]=1
DOUBLE_CHECK[ced.v2.index]=1
tmp= (ced.v1.co+ced.v2.co)*0.5
Blender.Window.SetCursorPos(tmp.x, tmp.y, tmp.z)
Blender.Window.RedrawAll()
"""
# Chech if we have collapsed our quota.
collapse_count-=1
if not collapse_count:
break
current_face_count -= len(ced.faces)
# Find and assign the real weights based on collapse loc.
# Find the weights from the collapse error
if DO_WEIGHTS or DO_UV or DO_VCOL:
i1, i2= ced.key
# Dont use these weights since they may not have been used to make the collapse loc.
#w1= vert_weights[i1]
#w2= vert_weights[i2]
w1= (ced.v2.co-ced.collapse_loc).length
w2= (ced.v1.co-ced.collapse_loc).length
# Normalize weights
wscale= w1+w2
if not wscale: # no scale?
w1=w2= 0.5
else:
w1/= wscale
w2/= wscale
# Interpolate the bone weights.
if DO_WEIGHTS:
# add verts vgroups to eachother
wl1= vWeightList[i1] # v1 weight dict
wl2= vWeightList[i2] # v2 weight dict
for group_index in xrange(len_vgroups):
wl1[group_index]= wl2[group_index]= (wl1[group_index]*w1) + (wl2[group_index]*w2)
# Done finding weights.
if DO_UV or DO_VCOL:
# Handel UV's and vert Colors!
for v, my_weight, other_weight, edge_my_uvs, edge_other_uvs, edge_my_cols, edge_other_cols in (\
(ced.v1, w1, w2, ced.uv1, ced.uv2, ced.col1, ced.col2),\
(ced.v2, w2, w1, ced.uv2, ced.uv1, ced.col2, ced.col1)\
):
uvs_mixed= [ uv_key_mix(edge_my_uvs[iii], edge_other_uvs[iii], my_weight, other_weight) for iii in xrange(len(edge_my_uvs)) ]
cols_mixed= [ col_key_mix(edge_my_cols[iii], edge_other_cols[iii], my_weight, other_weight) for iii in xrange(len(edge_my_cols)) ]
for face_vert_index, cfa in vert_face_users[v.index]:
if len(cfa.verts)==3 and cfa not in ced.faces: # if the face is apart of this edge then dont bother finding the uvs since the face will be removed anyway.
if DO_UV:
# UV COORDS
uvk= cfa.orig_uv[face_vert_index]
try:
tex_index= edge_my_uvs.index(uvk)
except:
tex_index= None
""" # DEBUG!
if DEBUG:
print 'not found', uvk, 'in', edge_my_uvs, 'ed index', ii, '\nwhat about', edge_other_uvs
"""
if tex_index != None: # This face uses a uv in the collapsing face. - do a merge
other_uv= edge_other_uvs[tex_index]
uv_vec= cfa.uv[face_vert_index]
uv_vec.x, uv_vec.y= uvs_mixed[tex_index]
# TEXFACE COLORS
if DO_VCOL:
colk= cfa.orig_col[face_vert_index]
try: tex_index= edge_my_cols.index(colk)
except: pass
if tex_index != None:
other_col= edge_other_cols[tex_index]
col_ob= cfa.col[face_vert_index]
col_ob.r, col_ob.g, col_ob.b= cols_mixed[tex_index]
# DEBUG! if DEBUG: rd()
# Execute the collapse
ced.v1.sel= ced.v2.sel= True # Select so remove doubles removed the edges and faces that use it
ced.v1.co= ced.v2.co= ced.collapse_loc
# DEBUG! if DEBUG: rd()
if current_face_count <= target_face_count:
break
# Copy weights back to the mesh before we remove doubles.
if DO_WEIGHTS:
#BPyMesh.dict2MeshWeight(me, groupNames, vWeightDict)
BPyMesh.list2MeshWeight(me, groupNames, vWeightList)
doubles= me.remDoubles(0.0001)
current_face_count= len(me.faces)
if current_face_count <= target_face_count or not doubles: # not doubles shoule never happen.
break
me.update()
Blender.Mesh.Mode(OLD_MESH_MODE)
# Example usage
def main():
Blender.Window.EditMode(0)
scn= bpy.data.scenes.active
active_ob= scn.objects.active
t= Blender.sys.time()
redux(active_ob, 0.5)
print '%.4f' % (Blender.sys.time()-t)
if __name__=='__main__':
main()

View File

@@ -1,61 +0,0 @@
from Blender import Draw, sys
def Error_NoMeshSelected():
Draw.PupMenu('Error%t|No mesh objects selected')
def Error_NoActive():
Draw.PupMenu('Error%t|No active object')
def Error_NoMeshActive():
Draw.PupMenu('Error%t|Active object is not a mesh')
def Error_NoMeshUvSelected():
Draw.PupMenu('Error%t|No mesh objects with texface selected')
def Error_NoMeshUvActive():
Draw.PupMenu('Error%t|Active object is not a mesh with texface')
def Error_NoMeshMultiresEdit():
Draw.PupMenu('Error%t|Unable to complete action with multires enabled')
def Error_NoMeshFaces():
Draw.PupMenu('Error%t|Mesh has no faces')
# File I/O messages
def Error_NoFile(path):
'''True if file missing, False if files there
Use simply by doing...
if Error_NoFile(path): return
'''
if not sys.exists(sys.expandpath(path)):
Draw.PupMenu("Error%t|Can't open file: " + path)
return True
return False
def Error_NoDir(path):
'''True if dirs missing, False if dirs there
Use simply by doing...
if Error_NoDir(path): return
'''
if not sys.exists(sys.expandpath(path)):
Draw.PupMenu("Error%t|Path does not exist: " + path)
return True
return False
def Warning_MeshDistroyLayers(mesh):
'''Returns true if we can continue to edit the mesh, warn when using NMesh'''
if len(mesh.getUVLayerNames()) >1 and len(mesh.getColorLayerNames()) >1:
return True
ret = Draw.PupMenu('Warning%t|This script will distroy inactive UV and Color layers, OK?')
if ret == -1:
return False
return True
def Warning_SaveOver(path):
'''Returns - True to save, False dont save'''
if sys.exists(sys.expandpath(path)):
ret= Draw.PupMenu('Save over%t|' + path)
if ret == -1:
return False
return True

View File

@@ -1,48 +0,0 @@
# $Id$
#
# --------------------------------------------------------------------------
# BPyNMesh.py version 0.1
# --------------------------------------------------------------------------
# helper functions to be used by other scripts
# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
# --------------------------------------------------------------------------
# "Apply size and rotation" function by Jonas Petersen
# --------------------------------------------------------------------------
# This function does (hopefully) exactly what the
# "Apply size and rotation" command does (CTRL-A in Object Mode).
def ApplySizeAndRotation(obj):
if obj.getType() != "Mesh": return
if obj.SizeX==1.0 and obj.SizeY==1.0 and obj.SizeZ==1.0 and obj.RotX == 0.0 and obj.RotY == 0.0 and obj.RotZ == 0.0: return
mesh = obj.getData()
matrix = obj.matrix
v = [0,0,0]
for vert in mesh.verts:
co = vert.co
v[0] = co[0]*matrix[0][0] + co[1]*matrix[1][0] + co[2]*matrix[2][0]
v[1] = co[0]*matrix[0][1] + co[1]*matrix[1][1] + co[2]*matrix[2][1]
v[2] = co[0]*matrix[0][2] + co[1]*matrix[1][2] + co[2]*matrix[2][2]
co[0], co[1], co[2] = v
obj.SizeX = obj.SizeY = obj.SizeZ = 1.0
obj.RotX = obj.RotY = obj.RotZ = 0.0
mesh.update()

View File

@@ -1,108 +0,0 @@
import Blender
def getObjectArmature(ob):
'''
This returns the first armature the mesh uses.
remember there can be more then 1 armature but most people dont do that.
'''
if ob.type != 'Mesh':
return None
arm = ob.parent
if arm and arm.type == 'Armature' and ob.parentType == Blender.Object.ParentTypes.ARMATURE:
return arm
for m in ob.modifiers:
if m.type== Blender.Modifier.Types.ARMATURE:
arm = m[Blender.Modifier.Settings.OBJECT]
if arm:
return arm
return None
def getDerivedObjects(ob, PARTICLES= True):
'''
Takes an objects and returnes a list of (ob, maxrix4x4) pairs
that are derived from this object -
This will include the object its self if it would be rendered.
all dupli's for eg are not rendered themselves.
currently supports
* dupligroups
* dupliverts
* dupliframes
* static particles as a mesh
it is possible this function will return an empty list.
'''
ob_mtx_pairs = ob.DupObjects
effects= ob.effects
# Ignore self if were a dupli* or our parent is a duplivert.
if ob.enableDupFrames or ob.enableDupGroup or ob.enableDupVerts:
pass
else:
parent= ob.parent
if parent and parent.enableDupVerts:
pass
else:
if effects and (not effects[0].flag & Blender.Effect.Flags.EMESH):
# Particles mesh wont render
pass
else:
ob_mtx_pairs.append((ob, ob.matrixWorld))
if PARTICLES:
type_vec= type(Blender.Mathutils.Vector())
type_tp= type((0,0))
type_ls= type([])
# TODO, particles per child object.
# TODO Support materials
me= Blender.Mesh.New()
for eff in effects:
par= eff.getParticlesLoc()
if par:
type_par= type(par[0])
if type_par == type_vec:
# point particles
me.verts.extend(par)
elif type_par == type_tp:
# edge pairs
start_index= len(me.verts)
me.verts.extend([v for p in par for v in p])
me.edges.extend( [(i, i+1) for i in xrange(start_index, start_index + len(par) - 1 )] )
elif type_par == type_ls:
# lines of edges
start_index= len(me.verts)
me.verts.extend([v for line in par for v in line])
edges= []
for line in par:
edges.extend( [(i,i+1) for i in xrange(start_index, start_index+len(line)-1) ] )
start_index+= len(line)
me.edges.extend(edges)
if me.verts:
# If we have verts, then add the mesh
ob_par = Blender.Object.New('Mesh')
ob_par.link( me )
LOOSE= Blender.Mesh.EdgeFlags.LOOSE
for ed in me.edges:
ed.flag |= LOOSE
# Particle's are in worldspace so an identity matrix is fine.
ob_mtx_pairs.append( (ob_par, Blender.Mathutils.Matrix()) )
return ob_mtx_pairs

View File

@@ -1,267 +0,0 @@
# --------------------------------------------------------------------------
# Module BPyRegistry version 0.1
# Helper functions to store / restore configuration data.
# --------------------------------------------------------------------------
# $Id$
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
# Copyright (C) 2004: Willian P. Germano, wgermano _at_ ig.com.br
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# --------------------------------------------------------------------------
# The Registry is a Python dictionary that is kept in Blender for as long as
# the program is running, where scripts can store / restore persistent data
# (data that is not lost when the script exits). This module provides
# functions to save and restore Registry entries as config data in the
# bpydata/config folder. Scripts just need to give an extra parameter to
# the Blender.Registry.Get/Set() functions to have their data automatically
# saved and restored when needed.
#
# Note: entries starting with an underscore are not saved, so script authors
# can use that fact to define data that is not meant to be stored in a
# config file. Example: data to be passed to another script and references to
# invalid data, like Blender objects and any function or method.
#
# Check the Blender.Registry documentation for more information.
import Blender
from Blender import Registry, sys as bsys
_EXT = '.cfg' # file extension for saved config data
# limits:
#MAX_ITEMS_NUM = 60 # max number of keys per dict and itens per list and tuple
#MAX_STR_LEN = 300 # max string length (remember this is just for config data)
_CFG_DIR = ''
if Blender.Get('udatadir'):
_CFG_DIR = Blender.sys.join(Blender.Get('udatadir'), 'config')
if not _CFG_DIR or not bsys.exists(_CFG_DIR):
_CFG_DIR = Blender.sys.join(Blender.Get('datadir'), 'config')
if not bsys.exists(_CFG_DIR):
_CFG_DIR = ''
# to compare against, so we don't write to a cvs tree:
_CVS_SUBPATH = 'release/scripts/bpydata/config/'
if bsys.dirsep == '\\':
_CVS_SUBPATH = _CVS_SUBPATH.replace('/', '\\')
_KEYS = [k for k in Registry.Keys() if k[0] != '_']
# _ITEMS_NUM = 0
def _sanitize(o):
"Check recursively that all objects are valid, set invalid ones to None"
# global MAX_ITEMS_NUM, MAX_STR_LEN, _ITEMS_NUM
valid_types = [int, float, bool, long, type]
valid_checked_types = [str, unicode]
# Only very simple types are considered valid for configuration data,
# functions, methods and Blender objects (use their names instead) aren't.
t = type(o)
if t == dict:
'''
_ITEMS_NUM += len(o)
if _ITEMS_NUM > MAX_ITEMS_NUM:
return None
'''
for k, v in o.iteritems():
o[k] = _sanitize(v)
elif t in [list, tuple]:
'''
_ITEMS_NUM += len(o)
if _ITEMS_NUM > MAX_ITEMS_NUM:
return None
'''
return [_sanitize(i) for i in o]
elif t in valid_types:
return o
elif t in valid_checked_types:
'''
if len(o) > MAX_STR_LEN:
o = o[:MAX_STR_LEN]
'''
return o
else: return None
return o
def _dict_to_str(name, d):
"Return a pretty-print version of the passed dictionary"
if not d: return 'None' # d can be None if there was no config to pass
if name: l = ['%s = {' % name]
else: l = ['{']
#keys = d.keys()
for k,v in d.iteritems(): # .keys()
if type(v) == dict:
l.append("'%s': %s" % (k, _dict_to_str(None, v)))
else:
l.append("'%s': %s," % (k, repr(v)))
if name: l.append('}')
else: l.append('},')
return "\n".join(l)
_HELP_MSG = """
Please create a valid scripts config dir tree either by
copying release/scripts/ tree to your <blenderhome> dir
or by copying release/scripts/bpydata/ tree to a user
defined scripts dir that you can set in the
User Preferences -> Paths tab -> Python path input box.
"""
def _check_dir():
global _CFG_DIR, _CVS_SUBPATH, _HELP_MSG
if not _CFG_DIR:
errmsg = "scripts config dir not found!\n%s" % _HELP_MSG
raise IOError, errmsg
elif _CFG_DIR.find(_CVS_SUBPATH) > 0:
errmsg = """
Your scripts config dir:\n%s
seems to reside in your local Blender's cvs tree.\n%s""" % (_CFG_DIR, _HELP_MSG)
raise SystemError, errmsg
else: return
# API:
BPY_KEY_MISSING = 0
BPY_KEY_IN_REGISTRY = 1
BPY_KEY_IN_FILE = 2
def HasConfigData (key):
"""
Check if the given key exists, either already loaded in the Registry dict or
as a file in the script data config dir.
@type key: string
@param key: a given key name.
@returns:
- 0: key does not exist;
- 1: key exists in the Registry dict only;
- 2: key exists as a file only;
- 3: key exists in the Registry dict and also as a file.
@note: for readability it's better to check against the constant bitmasks
BPY_KEY_MISSING = 0, BPY_KEY_IN_REGISTRY = 1 and BPY_KEY_IN_FILE = 2.
"""
fname = bsys.join(_CFG_DIR, "%s%s" % (key, _EXT))
result = BPY_KEY_MISSING
if key in Registry.Keys(): result |= BPY_KEY_IN_REGISTRY
if bsys.exists(fname): result |= BPY_KEY_IN_FILE
return result
def LoadConfigData (key = None):
"""
Load config data from file(s) to the Registry dictionary.
@type key: string
@param key: a given key name. If None (default), all available keys are
loaded.
@returns: None
"""
_check_dir()
import os
if not key:
files = \
[bsys.join(_CFG_DIR, f) for f in os.listdir(_CFG_DIR) if f.endswith(_EXT)]
else:
files = []
fname = bsys.join(_CFG_DIR, "%s%s" % (key, _EXT))
if bsys.exists(fname): files.append(fname)
for p in files:
try:
f = file(p, 'r')
lines = f.readlines()
f.close()
if lines: # Lines may be blank
mainkey = lines[0].split('=')[0].strip()
pysrc = "\n".join(lines)
exec(pysrc)
exec("Registry.SetKey('%s', %s)" % (str(mainkey), mainkey))
except Exception, e:
raise Warning(e) # Resend exception as warning
def RemoveConfigData (key = None):
"""
Remove this key's config file from the <(u)datadir>/config/ folder.
@type key: string
@param key: the name of the key to be removed. If None (default) all
available config files are deleted.
"""
_check_dir()
if not key:
files = \
[bsys.join(_CFG_DIR, f) for f in os.listdir(_CFG_DIR) if f.endswith(_EXT)]
else:
files = []
fname = bsys.join(_CFG_DIR, "%s%s" % (key, _EXT))
if bsys.exists(fname): files.append(fname)
import os
try:
for p in files:
os.remove(p) # remove the file(s)
except Exception, e:
raise Warning(e) # Resend exception as warning
def SaveConfigData (key = None):
"""
Save Registry key(s) as file(s) in the <(u)datadir>/config/ folder.
@type key: string
@param key: the name of the key to be saved. If None (default) all
available keys are saved.
"""
global _KEYS, _CFG_DIR
_check_dir()
if key: keys = [key]
else: keys = _KEYS
for mainkey in keys:
cfgdict = Registry.GetKey(mainkey).copy()
for k in cfgdict: # .keys()
if not k or k[0] == '_':
del cfgdict[k]
if not cfgdict: continue
try:
filename = bsys.join(_CFG_DIR, "%s%s" % (mainkey, _EXT))
f = file(filename, 'w')
output = _dict_to_str(mainkey, _sanitize(cfgdict))
if output!='None':
f.write(output)
f.close()
except Exception, e:
raise Warning(e) # Resend exception as warning

View File

@@ -1,633 +0,0 @@
import Blender
from Blender import Scene, sys, Camera, Object, Image
from Blender.Scene import Render
Vector= Blender.Mathutils.Vector
def extFromFormat(format):
if format == Render.TARGA: return 'tga'
if format == Render.RAWTGA: return 'tga'
if format == Render.HDR: return 'hdr'
if format == Render.PNG: return 'png'
if format == Render.BMP: return 'bmp'
if format == Render.JPEG: return 'jpg'
if format == Render.HAMX: return 'ham'
if format == Render.TIFF: return 'tif'
if format == Render.CINEON: return 'cine'
if format == Render.DPX: return 'tif'
if format == Render.OPENEXR: return 'exr'
if format == Render.IRIS: return 'rgb'
return ''
def imageFromObjectsOrtho(objects, path, width, height, smooth, alpha= True, camera_matrix= None, format=Render.PNG):
'''
Takes any number of objects and renders them on the z axis, between x:y-0 and x:y-1
Usefull for making images from a mesh without per pixel operations
- objects must be alredy placed
- smooth, anti alias True/False
- path renders to a PNG image
- alpha weather to render background as alpha
returns the blender image
'''
ext = '.' + extFromFormat(format)
print ext
# remove an extension if its alredy there
if path.lower().endswith(ext):
path= path[:-4]
path_expand= sys.expandpath(path) + ext
print path_expand, 'path'
# Touch the path
try:
f= open(path_expand, 'w')
f.close()
except:
raise 'Error, could not write to path:' + path_expand
# RENDER THE FACES.
scn= Scene.GetCurrent()
render_scn= Scene.New()
render_scn.makeCurrent()
render_scn.Layers |= (1<<20)-1 # all layers enabled
# Add objects into the current scene
for ob in objects:
render_scn.link(ob)
render_context= render_scn.getRenderingContext()
render_context.setRenderPath('') # so we can ignore any existing path and save to the abs path.
render_context.imageSizeX(width)
render_context.imageSizeY(height)
if smooth:
render_context.enableOversampling(True)
render_context.setOversamplingLevel(16)
else:
render_context.enableOversampling(False)
render_context.setRenderWinSize(100)
render_context.setImageType(format)
render_context.enableExtensions(True)
#render_context.enableSky() # No alpha needed.
if alpha:
render_context.alphaMode= 1
render_context.enableRGBAColor()
else:
render_context.alphaMode= 0
render_context.enableRGBColor()
render_context.displayMode= 0 # fullscreen
# New camera and object
render_cam_data= Camera.New('ortho')
render_cam_ob= Object.New('Camera')
render_cam_ob.link(render_cam_data)
render_scn.link(render_cam_ob)
render_scn.objects.camera = render_cam_ob
render_cam_data.type= 'ortho'
# Position the camera
if camera_matrix:
render_cam_ob.setMatrix(camera_matrix)
# We need to take into account the matrix scaling when setting the size
# so we get the image bounds defined by the matrix
# first get the x and y factors from the matrix.
# To render the correct dimensions we must use the aspy and aspy to force the matrix scale to
# override the aspect enforced by the width and weight.
cent= Vector() * camera_matrix
xvec= Vector(1,0,0) * camera_matrix
yvec= Vector(0,1,0) * camera_matrix
# zvec= Vector(0,0,1) * camera_matrix
xlen = (cent-xvec).length # half height of the image
ylen = (cent-yvec).length # half width of the image
# zlen = (cent-zvec).length # dist to place the camera? - just use the loc for now.
# less then 1.0 portrate, 1.0 or more is portrate
asp_cam_mat= xlen/ylen # divide by zero? - possible but scripters fault.
asp_image_res= float(width)/height
#print 'asp quad', asp_cam_mat, 'asp_image', asp_image_res
#print 'xylen', xlen, ylen, 'w/h', width, height
# Setup the aspect
if asp_cam_mat > asp_image_res:
# camera is wider then image res.
# to make the image wider, reduce the aspy
asp_diff= asp_image_res/asp_cam_mat
min_asp= asp_diff * 200
#print 'X', min_asp
elif asp_cam_mat < asp_image_res: # asp_cam_mat < asp_image_res
# camera is narrower then image res
# to make the image narrower, reduce the aspx
asp_diff= asp_cam_mat/asp_image_res
min_asp= asp_diff * 200
#print 'Y', min_asp
else:
min_asp= 200
# set the camera size
if xlen > ylen:
if asp_cam_mat > asp_image_res:
render_context.aspectX= 200 # get the greatest range possible
render_context.aspectY= min_asp # get the greatest range possible
else:
render_context.aspectY= 200 # get the greatest range possible
render_context.aspectX= min_asp # get the greatest range possible
#print "xlen bigger"
render_cam_data.scale= xlen * 2
elif xlen < ylen:# ylen is bigger
if asp_cam_mat > asp_image_res:
render_context.aspectX= 200 # get the greatest range possible
render_context.aspectY= min_asp # get the greatest range possible
else:
render_context.aspectY= 200 # get the greatest range possible
render_context.aspectX= min_asp # get the greatest range possible
#print "ylen bigger"
render_cam_data.scale= ylen *2
else:
# asppect 1:1
#print 'NOLEN Bigger'
render_cam_data.scale= xlen * 2
#print xlen, ylen, 'xlen, ylen'
else:
if width > height:
min_asp = int((float(height) / width) * 200)
render_context.aspectX= min_asp
render_context.aspectY= 200
else:
min_asp = int((float(width) / height) * 200)
render_context.aspectX= 200
render_context.aspectY= min_asp
render_cam_data.scale= 1.0
render_cam_ob.LocZ= 1.0
render_cam_ob.LocX= 0.5
render_cam_ob.LocY= 0.5
Blender.Window.RedrawAll()
render_context.render()
render_context.saveRenderedImage(path)
Render.CloseRenderWindow()
#if not B.sys.exists(PREF_IMAGE_PATH_EXPAND):
# raise 'Error!!!'
scn.makeCurrent()
Scene.Unlink(render_scn)
# NOW APPLY THE SAVED IMAGE TO THE FACES!
#print PREF_IMAGE_PATH_EXPAND
try:
target_image= Image.Load(path_expand)
return target_image
except:
raise 'Error: Could not render or load the image at path "%s"' % path_expand
return
#-----------------------------------------------------------------------------#
# UV Baking functions, make a picture from mesh(es) uvs #
#-----------------------------------------------------------------------------#
def mesh2uv(me_s, PREF_SEL_FACES_ONLY=False):
'''
Converts a uv mapped mesh into a 2D Mesh from UV coords.
returns a triple -
(mesh2d, face_list, col_list)
"mesh" is the new mesh and...
"face_list" is the faces that were used to make the mesh,
"material_list" is a list of materials used by each face
These are in alligned with the meshes faces, so you can easerly copy data between them
'''
render_me= Blender.Mesh.New()
render_me.verts.extend( [Vector(0,0,0),] ) # 0 vert uv bugm dummy vert
face_list= []
material_list= []
for me in me_s:
me_materials= me.materials
if PREF_SEL_FACES_ONLY:
me_faces= [f for f in me.faces if f.sel]
else:
me_faces= me.faces
face_list.extend(me_faces)
# Dittro
if me_materials:
material_list.extend([me_materials[f.mat] for f in me_faces])
else:
material_list.extend([None]*len(me_faces))
# Now add the verts
render_me.verts.extend( [ Vector(uv.x, uv.y, 0) for f in face_list for uv in f.uv ] )
# Now add the faces
tmp_faces= []
vert_offset= 1
for f in face_list:
tmp_faces.append( [ii+vert_offset for ii in xrange(len(f))] )
vert_offset+= len(f)
render_me.faces.extend(tmp_faces)
render_me.faceUV=1
return render_me, face_list, material_list
def uvmesh_apply_normals(render_me, face_list):
'''Worldspace normals to vertex colors'''
for i, f in enumerate(render_me.faces):
face_orig= face_list[i]
f_col= f.col
for j, v in enumerate(face_orig):
c= f_col[j]
nx, ny, nz= v.no
c.r= int((nx+1)*128)-1
c.g= int((ny+1)*128)-1
c.b= int((nz+1)*128)-1
def uvmesh_apply_image(render_me, face_list):
'''Copy the image and uvs from the original faces'''
for i, f in enumerate(render_me.faces):
f.uv= face_list[i].uv
f.image= face_list[i].image
def uvmesh_apply_vcol(render_me, face_list):
'''Copy the vertex colors from the original faces'''
for i, f in enumerate(render_me.faces):
face_orig= face_list[i]
f_col= f.col
for j, c_orig in enumerate(face_orig.col):
c= f_col[j]
c.r= c_orig.r
c.g= c_orig.g
c.b= c_orig.b
def uvmesh_apply_matcol(render_me, material_list):
'''Get the vertex colors from the original materials'''
for i, f in enumerate(render_me.faces):
mat_orig= material_list[i]
f_col= f.col
if mat_orig:
for c in f_col:
c.r= int(mat_orig.R*255)
c.g= int(mat_orig.G*255)
c.b= int(mat_orig.B*255)
else:
for c in f_col:
c.r= 255
c.g= 255
c.b= 255
def uvmesh_apply_col(render_me, color):
'''Get the vertex colors from the original materials'''
r,g,b= color
for i, f in enumerate(render_me.faces):
f_col= f.col
for c in f_col:
c.r= r
c.g= g
c.b= b
def vcol2image(me_s,\
PREF_IMAGE_PATH,\
PREF_IMAGE_SIZE,\
PREF_IMAGE_BLEED,\
PREF_IMAGE_SMOOTH,\
PREF_IMAGE_WIRE,\
PREF_IMAGE_WIRE_INVERT,\
PREF_IMAGE_WIRE_UNDERLAY,\
PREF_USE_IMAGE,\
PREF_USE_VCOL,\
PREF_USE_MATCOL,\
PREF_USE_NORMAL,\
PREF_USE_TEXTURE,\
PREF_SEL_FACES_ONLY):
def rnd_mat():
render_mat= Blender.Material.New()
mode= render_mat.mode
# Dont use lights ever
mode |= Blender.Material.Modes.SHADELESS
if PREF_IMAGE_WIRE:
# Set the wire color
if PREF_IMAGE_WIRE_INVERT:
render_mat.rgbCol= (1,1,1)
else:
render_mat.rgbCol= (0,0,0)
mode |= Blender.Material.Modes.WIRE
if PREF_USE_VCOL or PREF_USE_MATCOL or PREF_USE_NORMAL: # both vcol and material color use vertex cols to avoid the 16 max limit in materials
mode |= Blender.Material.Modes.VCOL_PAINT
if PREF_USE_IMAGE:
mode |= Blender.Material.Modes.TEXFACE
# Copy back the mode
render_mat.mode |= mode
return render_mat
render_me, face_list, material_list= mesh2uv(me_s, PREF_SEL_FACES_ONLY)
# Normals exclude all others
if PREF_USE_NORMAL:
uvmesh_apply_normals(render_me, face_list)
else:
if PREF_USE_IMAGE:
uvmesh_apply_image(render_me, face_list)
uvmesh_apply_vcol(render_me, face_list)
elif PREF_USE_VCOL:
uvmesh_apply_vcol(render_me, face_list)
elif PREF_USE_MATCOL:
uvmesh_apply_matcol(render_me, material_list)
elif PREF_USE_TEXTURE:
# if we have more then 16 materials across all the mesh objects were stuffed :/
# get unique materials
tex_unique_materials= dict([(mat.name, mat) for mat in material_list]).values()[:16] # just incase we have more then 16
tex_me= Blender.Mesh.New()
# Backup the original shadless setting
tex_unique_materials_shadeless= [ mat.mode & Blender.Material.Modes.SHADELESS for mat in tex_unique_materials ]
# Turn shadeless on
for mat in tex_unique_materials:
mat.mode |= Blender.Material.Modes.SHADELESS
# Assign materials
render_me.materials= tex_unique_materials
tex_material_indicies= dict([(mat.name, i) for i, mat in enumerate(tex_unique_materials)])
tex_me.verts.extend([Vector(0,0,0),]) # dummy
tex_me.verts.extend( [ Vector(v.co) for f in face_list for v in f ] )
# Now add the faces
tmp_faces= []
vert_offset= 1
for f in face_list:
tmp_faces.append( [ii+vert_offset for ii in xrange(len(f))] )
vert_offset+= len(f)
tex_me.faces.extend(tmp_faces)
# Now we have the faces, put materials and normal, uvs into the mesh
if len(tex_me.faces) != len(face_list):
# Should never happen
raise "Error face length mismatch"
# Copy data to the mesh that could be used as texture coords
for i, tex_face in enumerate(tex_me.faces):
orig_face= face_list[i]
# Set the material index
try:
render_face.mat= tex_material_indicies[ material_list[i].name ]
except:
# more then 16 materials
pass
# set the uvs on the texmesh mesh
tex_face.uv= orig_face.uv
orig_face_v= orig_face.v
# Set the normals
for j, v in enumerate(tex_face):
v.no= orig_face_v[j].no
# Set the texmesh
render_me.texMesh= tex_me
# END TEXMESH
# Handel adding objects
render_ob= Blender.Object.New('Mesh')
render_ob.link(render_me)
if not PREF_USE_TEXTURE: # textures use the original materials
render_me.materials= [rnd_mat()]
obs= [render_ob]
if PREF_IMAGE_WIRE_UNDERLAY:
# Make another mesh with the material colors
render_me_under, face_list, material_list= mesh2uv(me_s, PREF_SEL_FACES_ONLY)
uvmesh_apply_matcol(render_me_under, material_list)
# Handel adding objects
render_ob= Blender.Object.New('Mesh')
render_ob.link(render_me_under)
render_ob.LocZ= -0.01
# Add material and disable wire
mat= rnd_mat()
mat.rgbCol= 1,1,1
mat.alpha= 0.5
mat.mode &= ~Blender.Material.Modes.WIRE
mat.mode |= Blender.Material.Modes.VCOL_PAINT
render_me_under.materials= [mat]
obs.append(render_ob)
elif PREF_IMAGE_BLEED and not PREF_IMAGE_WIRE:
# EVIL BLEEDING CODE!! - Just do copys of the mesh and place behind. Crufty but better then many other methods I have seen. - Cam
BLEED_PIXEL= 1.0/PREF_IMAGE_SIZE
z_offset= 0.0
for i in xrange(PREF_IMAGE_BLEED):
for diag1, diag2 in ((-1,-1),(-1,1),(1,-1),(1,1), (1,0), (0,1), (-1,0), (0, -1)): # This line extends the object in 8 different directions, top avoid bleeding.
render_ob= Blender.Object.New('Mesh')
render_ob.link(render_me)
render_ob.LocX= (i+1)*diag1*BLEED_PIXEL
render_ob.LocY= (i+1)*diag2*BLEED_PIXEL
render_ob.LocZ= -z_offset
obs.append(render_ob)
z_offset += 0.01
image= imageFromObjectsOrtho(obs, PREF_IMAGE_PATH, PREF_IMAGE_SIZE, PREF_IMAGE_SIZE, PREF_IMAGE_SMOOTH)
# Clear from memory as best as we can
render_me.verts= None
if PREF_IMAGE_WIRE_UNDERLAY:
render_me_under.verts= None
if PREF_USE_TEXTURE:
tex_me.verts= None
# Restire Shadeless setting
for i, mat in enumerate(tex_unique_materials):
# we know there all on so turn it off of its not set
if not tex_unique_materials_shadeless[i]:
mat.mode &= ~Blender.Material.Modes.SHADELESS
return image
def bakeToPlane(sce, ob_from, width, height, bakemodes, axis='z', margin=0, depth=32):
'''
Bakes terrain onto a plane from one object
sce - scene to bake with
ob_from - mesh object
width/height - image size
bakemodes - list of baking modes to use, Blender.Scene.Render.BakeModes.NORMALS, Blender.Scene.Render.BakeModes.AO ... etc
axis - axis to allign the plane to.
margin - margin setting for baking.
depth - bit depth for the images to bake into, (32 or 128 for floating point images)
Example:
import Blender
from Blender import *
import BPyRender
sce = Scene.GetCurrent()
ob = Object.Get('Plane')
BPyRender.bakeToPlane(sce, ob, 512, 512, [Scene.Render.BakeModes.DISPLACEMENT, Scene.Render.BakeModes.NORMALS], 'z', 8 )
'''
# Backup bake settings
rend = sce.render
BACKUP_bakeDist = rend.bakeDist
BACKUP_bakeBias = rend.bakeBias
BACKUP_bakeMode = rend.bakeMode
BACKUP_bakeClear = rend.bakeClear
BACKUP_bakeMargin = rend.bakeMargin
BACKUP_bakeToActive = rend.bakeToActive
BACKUP_bakeNormalize = rend.bakeNormalize
# Backup object selection
BACKUP_obsel = list(sce.objects.selected)
BACKUP_obact = sce.objects.active
# New bake settings
rend.bakeClear = True
rend.bakeMargin = margin
rend.bakeToActive = True
rend.bakeNormalize = True
# Assume a mesh
me_from = ob_from.getData(mesh=1)
xmin = ymin = zmin = 10000000000
xmax = ymax = zmax =-10000000000
# Dont trust bounding boxes :/
#bounds = ob_from.boundingBox
#for v in bounds:
# x,y,z = tuple(v)
mtx = ob_from.matrixWorld
for v in me_from.verts:
x,y,z = tuple(v.co*mtx)
xmax = max(xmax, x)
ymax = max(ymax, y)
zmax = max(zmax, z)
xmin = min(xmin, x)
ymin = min(ymin, y)
zmin = min(zmin, z)
if axis=='x':
xmed = (xmin+xmax)/2.0
co1 = (xmed, ymin, zmin)
co2 = (xmed, ymin, zmax)
co3 = (xmed, ymax, zmax)
co4 = (xmed, ymax, zmin)
rend.bakeDist = ((xmax-xmin)/2.0) + 0.000001 # we need a euler value for this since it
elif axis=='y':
ymed = (ymin+ymax)/2.0
co1 = (xmin, ymed, zmin)
co2 = (xmin, ymed, zmax)
co3 = (xmax, ymed, zmax)
co4 = (xmax, ymed, zmin)
rend.bakeDist = ((ymax-ymin)/2.0) + 0.000001
elif axis=='z':
zmed = (zmin+zmax)/2.0
co1 = (xmin, ymin, zmed)
co2 = (xmin, ymax, zmed)
co3 = (xmax, ymax, zmed)
co4 = (xmax, ymin, zmed)
rend.bakeDist = ((zmax-zmin)/2.0) + 0.000001
else:
raise "invalid axis"
me_plane = Blender.Mesh.New()
ob_plane = Blender.Object.New('Mesh')
ob_plane.link(me_plane)
sce.objects.link(ob_plane)
ob_plane.Layers = ob_from.Layers
ob_from.sel = 1 # make active
sce.objects.active = ob_plane
ob_plane.sel = 1
me_plane.verts.extend([co4, co3, co2, co1])
me_plane.faces.extend([(0,1,2,3)])
me_plane.faceUV = True
me_plane_face = me_plane.faces[0]
uvs = me_plane_face.uv
uvs[0].x = 0.0; uvs[0].y = 0.0
uvs[1].x = 0.0; uvs[1].y = 1.0
uvs[2].x = 1.0; uvs[2].y = 1.0
uvs[3].x = 1.0; uvs[3].y = 0.0
images_return = []
for mode in bakemodes:
img = Blender.Image.New('bake', width, height, depth)
me_plane_face.image = img
rend.bakeMode = mode
rend.bake()
images_return.append( img )
# Restore bake settings
#'''
rend.bakeDist = BACKUP_bakeDist
rend.bakeBias = BACKUP_bakeBias
rend.bakeMode = BACKUP_bakeMode
rend.bakeClear = BACKUP_bakeClear
rend.bakeMargin = BACKUP_bakeMargin
rend.bakeToActive = BACKUP_bakeToActive
rend.bakeNormalize = BACKUP_bakeNormalize
# Restore obsel
sce.objects.selected = BACKUP_obsel
sce.objects.active = BACKUP_obact
me_plane.verts = None
sce.objects.unlink(ob_plane)
#'''
return images_return

View File

@@ -1,74 +0,0 @@
## This was used to make V, but faster not to do all that
##valid = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_'
##v = range(255)
##for c in valid: v.remove(ord(c))
v = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,46,47,58,59,60,61,62,63,64,91,92,93,94,96,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254]
invalid = ''.join([chr(i) for i in v])
## del v, c, i, valid
del v, i
def cleanName(name):
for ch in invalid: name = name.replace(ch, '_')
return name
def caseInsensitivePath(path, RET_FOUND=False):
'''
Get a case insensitive path on a case sensitive system
RET_FOUND is for internal use only, to avoid too many calls to os.path.exists
# Example usage
getCaseInsensitivePath('/hOmE/mE/sOmEpAtH.tXt')
'''
import os # todo, what happens with no os?
if os==None:
if RET_FOUND: ret = path, True
else: ret = path
return ret
if path=='' or os.path.exists(path):
if RET_FOUND: ret = path, True
else: ret = path
return ret
f = os.path.basename(path) # f may be a directory or a file
d = os.path.dirname(path)
suffix = ''
if not f: # dir ends with a slash?
if len(d) < len(path):
suffix = path[:len(path)-len(d)]
f = os.path.basename(d)
d = os.path.dirname(d)
if not os.path.exists(d):
d, found = caseInsensitivePath(d, True)
if not found:
if RET_FOUND: ret = path, False
else: ret = path
return ret
# at this point, the directory exists but not the file
try: # we are expecting 'd' to be a directory, but it could be a file
files = os.listdir(d)
except:
if RET_FOUND: ret = path, False
else: ret = path
f_low = f.lower()
try: f_nocase = [fl for fl in files if fl.lower() == f_low][0]
except: f_nocase = None
if f_nocase:
if RET_FOUND: ret = os.path.join(d, f_nocase) + suffix, True
else: ret = os.path.join(d, f_nocase) + suffix
return ret
else:
if RET_FOUND: ret = path, False
else: ret = path
return ret # cant find the right one, just return the path as is.

View File

@@ -1,814 +0,0 @@
"""The BPyTextPlugin Module
Use get_cached_descriptor(txt) to retrieve information about the script held in
the txt Text object.
Use print_cache_for(txt) to print the information to the console.
Use line, cursor = current_line(txt) to get the logical line and cursor position
Use get_targets(line, cursor) to find out what precedes the cursor:
aaa.bbb.cc|c.ddd -> ['aaa', 'bbb', 'cc']
Use resolve_targets(txt, targets) to turn a target list into a usable object if
one is found to match.
"""
import bpy, sys, os
import __builtin__, tokenize
from Blender.sys import time
from tokenize import generate_tokens, TokenError, \
COMMENT, DEDENT, INDENT, NAME, NEWLINE, NL, STRING, NUMBER
class Definition:
"""Describes a definition or defined object through its name, line number
and docstring. This is the base class for definition based descriptors.
"""
def __init__(self, name, lineno, doc=''):
self.name = name
self.lineno = lineno
self.doc = doc
class ScriptDesc:
"""Describes a script through lists of further descriptor objects (classes,
defs, vars) and dictionaries to built-in types (imports). If a script has
not been fully parsed, its incomplete flag will be set. The time of the last
parse is held by the time field and the name of the text object from which
it was parsed, the name field.
"""
def __init__(self, name, imports, classes, defs, vars, incomplete=False):
self.name = name
self.imports = imports
self.classes = classes
self.defs = defs
self.vars = vars
self.incomplete = incomplete
self.parse_due = 0
def set_delay(self, delay):
self.parse_due = time() + delay
class ClassDesc(Definition):
"""Describes a class through lists of further descriptor objects (defs and
vars). The name of the class is held by the name field and the line on
which it is defined is held in lineno.
"""
def __init__(self, name, parents, defs, vars, lineno, doc=''):
Definition.__init__(self, name, lineno, doc)
self.parents = parents
self.defs = defs
self.vars = vars
class FunctionDesc(Definition):
"""Describes a function through its name and list of parameters (name,
params) and the line on which it is defined (lineno).
"""
def __init__(self, name, params, lineno, doc=''):
Definition.__init__(self, name, lineno, doc)
self.params = params
class VarDesc(Definition):
"""Describes a variable through its name and type (if ascertainable) and the
line on which it is defined (lineno). If no type can be determined, type
will equal None.
"""
def __init__(self, name, type, lineno):
Definition.__init__(self, name, lineno)
self.type = type # None for unknown (supports: dict/list/str)
# Context types
CTX_UNSET = -1
CTX_NORMAL = 0
CTX_SINGLE_QUOTE = 1
CTX_DOUBLE_QUOTE = 2
CTX_COMMENT = 3
# Python keywords
KEYWORDS = ['and', 'del', 'from', 'not', 'while', 'as', 'elif', 'global',
'or', 'with', 'assert', 'else', 'if', 'pass', 'yield',
'break', 'except', 'import', 'print', 'class', 'exec', 'in',
'raise', 'continue', 'finally', 'is', 'return', 'def', 'for',
'lambda', 'try' ]
# Module file extensions
MODULE_EXTS = ['.py', '.pyc', '.pyo', '.pyw', '.pyd']
ModuleType = type(__builtin__)
NoneScriptDesc = ScriptDesc('', dict(), dict(), dict(), dict(), True)
_modules = {}
_modules_updated = 0
_parse_cache = dict()
def _load_module_names():
"""Searches the sys.path for module files and lists them, along with
sys.builtin_module_names, in the global dict _modules.
"""
global _modules
for n in sys.builtin_module_names:
_modules[n] = None
for p in sys.path:
if p == '': p = os.curdir
if not os.path.isdir(p): continue
for f in os.listdir(p):
for ext in MODULE_EXTS:
if f.endswith(ext):
_modules[f[:-len(ext)]] = None
break
_load_module_names()
def _trim_doc(doc):
"""Trims the quotes from a quoted STRING token (eg. "'''text'''" -> "text")
"""
l = len(doc)
i = 0
while i < l/2 and (doc[i] == "'" or doc[i] == '"'):
i += 1
return doc[i:-i]
def resolve_targets(txt, targets):
"""Attempts to return a useful object for the locally or externally defined
entity described by targets. If the object is local (defined in txt), a
Definition instance is returned. If the object is external (imported or
built in), the object itself is returned. If no object can be found, None is
returned.
"""
count = len(targets)
if count==0: return None
obj = None
local = None
i = 1
desc = get_cached_descriptor(txt)
b = targets[0].find('(')
if b==-1: b = None # Trick to let us use [:b] and get the whole string
if desc.classes.has_key(targets[0][:b]):
local = desc.classes[targets[0][:b]]
elif desc.defs.has_key(targets[0]):
local = desc.defs[targets[0]]
elif desc.vars.has_key(targets[0]):
obj = desc.vars[targets[0]].type
if local:
while i < count:
b = targets[i].find('(')
if b==-1: b = None
if hasattr(local, 'classes') and local.classes.has_key(targets[i][:b]):
local = local.classes[targets[i][:b]]
elif hasattr(local, 'defs') and local.defs.has_key(targets[i]):
local = local.defs[targets[i]]
elif hasattr(local, 'vars') and local.vars.has_key(targets[i]):
obj = local.vars[targets[i]].type
local = None
i += 1
break
else:
local = None
break
i += 1
if local: return local
if not obj:
if desc.imports.has_key(targets[0]):
obj = desc.imports[targets[0]]
else:
builtins = get_builtins()
if builtins.has_key(targets[0]):
obj = builtins[targets[0]]
while obj and i < count:
if hasattr(obj, targets[i]):
obj = getattr(obj, targets[i])
else:
obj = None
break
i += 1
return obj
def get_cached_descriptor(txt, force_parse=0):
"""Returns the cached ScriptDesc for the specified Text object 'txt'. If the
script has not been parsed in the last 'period' seconds it will be reparsed
to obtain this descriptor.
Specifying TP_AUTO for the period (default) will choose a period based on the
size of the Text object. Larger texts are parsed less often.
"""
global _parse_cache
parse = True
key = hash(txt)
if not force_parse and _parse_cache.has_key(key):
desc = _parse_cache[key]
if desc.parse_due > time():
parse = desc.incomplete
if parse:
desc = parse_text(txt)
return desc
def parse_text(txt):
"""Parses an entire script's text and returns a ScriptDesc instance
containing information about the script.
If the text is not a valid Python script (for example if brackets are left
open), parsing may fail to complete. However, if this occurs, no exception
is thrown. Instead the returned ScriptDesc instance will have its incomplete
flag set and information processed up to this point will still be accessible.
"""
start_time = time()
txt.reset()
tokens = generate_tokens(txt.readline) # Throws TokenError
curl, cursor = txt.getCursorPos()
linen = curl + 1 # Token line numbers are one-based
imports = dict()
imp_step = 0
classes = dict()
cls_step = 0
defs = dict()
def_step = 0
vars = dict()
var1_step = 0
var2_step = 0
var3_step = 0
var_accum = dict()
var_forflag = False
indent = 0
prev_type = -1
prev_text = ''
incomplete = False
while True:
try:
type, text, start, end, line = tokens.next()
except StopIteration:
break
except (TokenError, IndentationError):
incomplete = True
break
# Skip all comments and line joining characters
if type == COMMENT or type == NL:
continue
#################
## Indentation ##
#################
if type == INDENT:
indent += 1
elif type == DEDENT:
indent -= 1
#########################
## Module importing... ##
#########################
imp_store = False
# Default, look for 'from' or 'import' to start
if imp_step == 0:
if text == 'from':
imp_tmp = []
imp_step = 1
elif text == 'import':
imp_from = None
imp_tmp = []
imp_step = 2
# Found a 'from', create imp_from in form '???.???...'
elif imp_step == 1:
if text == 'import':
imp_from = '.'.join(imp_tmp)
imp_tmp = []
imp_step = 2
elif type == NAME:
imp_tmp.append(text)
elif text != '.':
imp_step = 0 # Invalid syntax
# Found 'import', imp_from is populated or None, create imp_name
elif imp_step == 2:
if text == 'as':
imp_name = '.'.join(imp_tmp)
imp_step = 3
elif type == NAME or text == '*':
imp_tmp.append(text)
elif text != '.':
imp_name = '.'.join(imp_tmp)
imp_symb = imp_name
imp_store = True
# Found 'as', change imp_symb to this value and go back to step 2
elif imp_step == 3:
if type == NAME:
imp_symb = text
else:
imp_store = True
# Both imp_name and imp_symb have now been populated so we can import
if imp_store:
# Handle special case of 'import *'
if imp_name == '*':
parent = get_module(imp_from)
imports.update(parent.__dict__)
else:
# Try importing the name as a module
try:
if imp_from:
module = get_module(imp_from +'.'+ imp_name)
else:
module = get_module(imp_name)
except (ImportError, ValueError, AttributeError, TypeError):
# Try importing name as an attribute of the parent
try:
module = __import__(imp_from, globals(), locals(), [imp_name])
imports[imp_symb] = getattr(module, imp_name)
except (ImportError, ValueError, AttributeError, TypeError):
pass
else:
imports[imp_symb] = module
# More to import from the same module?
if text == ',':
imp_tmp = []
imp_step = 2
else:
imp_step = 0
###################
## Class parsing ##
###################
# If we are inside a class then def and variable parsing should be done
# for the class. Otherwise the definitions are considered global
# Look for 'class'
if cls_step == 0:
if text == 'class':
cls_name = None
cls_lineno = start[0]
cls_indent = indent
cls_step = 1
# Found 'class', look for cls_name followed by '(' parents ')'
elif cls_step == 1:
if not cls_name:
if type == NAME:
cls_name = text
cls_sline = False
cls_parents = dict()
cls_defs = dict()
cls_vars = dict()
elif type == NAME:
if classes.has_key(text):
parent = classes[text]
cls_parents[text] = parent
cls_defs.update(parent.defs)
cls_vars.update(parent.vars)
elif text == ':':
cls_step = 2
# Found 'class' name ... ':', now check if it's a single line statement
elif cls_step == 2:
if type == NEWLINE:
cls_sline = False
else:
cls_sline = True
cls_doc = ''
cls_step = 3
elif cls_step == 3:
if not cls_doc and type == STRING:
cls_doc = _trim_doc(text)
if cls_sline:
if type == NEWLINE:
classes[cls_name] = ClassDesc(cls_name, cls_parents, cls_defs, cls_vars, cls_lineno, cls_doc)
cls_step = 0
else:
if type == DEDENT and indent <= cls_indent:
classes[cls_name] = ClassDesc(cls_name, cls_parents, cls_defs, cls_vars, cls_lineno, cls_doc)
cls_step = 0
#################
## Def parsing ##
#################
# Look for 'def'
if def_step == 0:
if text == 'def':
def_name = None
def_lineno = start[0]
def_step = 1
# Found 'def', look for def_name followed by '('
elif def_step == 1:
if type == NAME:
def_name = text
def_params = []
elif def_name and text == '(':
def_step = 2
# Found 'def' name '(', now identify the parameters upto ')'
# TODO: Handle ellipsis '...'
elif def_step == 2:
if type == NAME:
def_params.append(text)
elif text == ':':
def_step = 3
# Found 'def' ... ':', now check if it's a single line statement
elif def_step == 3:
if type == NEWLINE:
def_sline = False
else:
def_sline = True
def_doc = ''
def_step = 4
elif def_step == 4:
if type == STRING:
def_doc = _trim_doc(text)
newdef = None
if def_sline:
if type == NEWLINE:
newdef = FunctionDesc(def_name, def_params, def_lineno, def_doc)
else:
if type == NAME:
newdef = FunctionDesc(def_name, def_params, def_lineno, def_doc)
if newdef:
if cls_step > 0: # Parsing a class
cls_defs[def_name] = newdef
else:
defs[def_name] = newdef
def_step = 0
##########################
## Variable assignation ##
##########################
if cls_step > 0: # Parsing a class
# Look for 'self.???'
if var1_step == 0:
if text == 'self':
var1_step = 1
elif var1_step == 1:
if text == '.':
var_name = None
var1_step = 2
else:
var1_step = 0
elif var1_step == 2:
if type == NAME:
var_name = text
if cls_vars.has_key(var_name):
var_step = 0
else:
var1_step = 3
elif var1_step == 3:
if text == '=':
var1_step = 4
elif text != ',':
var1_step = 0
elif var1_step == 4:
var_type = None
if type == NUMBER:
close = end[1]
if text.find('.') != -1: var_type = float
else: var_type = int
elif type == STRING:
close = end[1]
var_type = str
elif text == '[':
close = line.find(']', end[1])
var_type = list
elif text == '(':
close = line.find(')', end[1])
var_type = tuple
elif text == '{':
close = line.find('}', end[1])
var_type = dict
elif text == 'dict':
close = line.find(')', end[1])
var_type = dict
if var_type and close+1 < len(line):
if line[close+1] != ' ' and line[close+1] != '\t':
var_type = None
cls_vars[var_name] = VarDesc(var_name, var_type, start[0])
var1_step = 0
elif def_step > 0: # Parsing a def
# Look for 'global ???[,???]'
if var2_step == 0:
if text == 'global':
var2_step = 1
elif var2_step == 1:
if type == NAME:
if not vars.has_key(text):
vars[text] = VarDesc(text, None, start[0])
elif text != ',' and type != NL:
var2_step == 0
else: # In global scope
if var3_step == 0:
# Look for names
if text == 'for':
var_accum = dict()
var_forflag = True
elif text == '=' or (var_forflag and text == 'in'):
var_forflag = False
var3_step = 1
elif type == NAME:
if prev_text != '.' and not vars.has_key(text):
var_accum[text] = VarDesc(text, None, start[0])
elif not text in [',', '(', ')', '[', ']']:
var_accum = dict()
var_forflag = False
elif var3_step == 1:
if len(var_accum) != 1:
var_type = None
vars.update(var_accum)
else:
var_name = var_accum.keys()[0]
var_type = None
if type == NUMBER:
if text.find('.') != -1: var_type = float
else: var_type = int
elif type == STRING: var_type = str
elif text == '[': var_type = list
elif text == '(': var_type = tuple
elif text == '{': var_type = dict
vars[var_name] = VarDesc(var_name, var_type, start[0])
var3_step = 0
#######################
## General utilities ##
#######################
prev_type = type
prev_text = text
desc = ScriptDesc(txt.name, imports, classes, defs, vars, incomplete)
desc.set_delay(10 * (time()-start_time) + 0.05)
global _parse_cache
_parse_cache[hash(txt)] = desc
return desc
def get_modules(since=1):
"""Returns the set of built-in modules and any modules that have been
imported into the system upto 'since' seconds ago.
"""
global _modules, _modules_updated
t = time()
if _modules_updated < t - since:
_modules.update(sys.modules)
_modules_updated = t
return _modules.keys()
def suggest_cmp(x, y):
"""Use this method when sorting a list of suggestions.
"""
return cmp(x[0].upper(), y[0].upper())
def get_module(name):
"""Returns the module specified by its name. The module itself is imported
by this method and, as such, any initialization code will be executed.
"""
mod = __import__(name)
components = name.split('.')
for comp in components[1:]:
mod = getattr(mod, comp)
return mod
def type_char(v):
"""Returns the character used to signify the type of a variable. Use this
method to identify the type character for an item in a suggestion list.
The following values are returned:
'm' if the parameter is a module
'f' if the parameter is callable
'v' if the parameter is variable or otherwise indeterminable
"""
if isinstance(v, ModuleType):
return 'm'
elif callable(v):
return 'f'
else:
return 'v'
def get_context(txt):
"""Establishes the context of the cursor in the given Blender Text object
Returns one of:
CTX_NORMAL - Cursor is in a normal context
CTX_SINGLE_QUOTE - Cursor is inside a single quoted string
CTX_DOUBLE_QUOTE - Cursor is inside a double quoted string
CTX_COMMENT - Cursor is inside a comment
"""
l, cursor = txt.getCursorPos()
lines = txt.asLines(0, l+1)
# FIXME: This method is too slow in large files for it to be called as often
# as it is. So for lines below the 1000th line we do this... (quorn)
if l > 1000: return CTX_NORMAL
# Detect context (in string or comment)
in_str = CTX_NORMAL
for line in lines:
if l == 0:
end = cursor
else:
end = len(line)
l -= 1
# Comments end at new lines
if in_str == CTX_COMMENT:
in_str = CTX_NORMAL
for i in range(end):
if in_str == 0:
if line[i] == "'": in_str = CTX_SINGLE_QUOTE
elif line[i] == '"': in_str = CTX_DOUBLE_QUOTE
elif line[i] == '#': in_str = CTX_COMMENT
else:
if in_str == CTX_SINGLE_QUOTE:
if line[i] == "'":
in_str = CTX_NORMAL
# In again if ' escaped, out again if \ escaped, and so on
for a in range(i-1, -1, -1):
if line[a] == '\\': in_str = 1-in_str
else: break
elif in_str == CTX_DOUBLE_QUOTE:
if line[i] == '"':
in_str = CTX_NORMAL
# In again if " escaped, out again if \ escaped, and so on
for a in range(i-1, -1, -1):
if line[i-a] == '\\': in_str = 2-in_str
else: break
return in_str
def current_line(txt):
"""Extracts the Python script line at the cursor in the Blender Text object
provided and cursor position within this line as the tuple pair (line,
cursor).
"""
lineindex, cursor = txt.getCursorPos()
lines = txt.asLines()
line = lines[lineindex]
# Join previous lines to this line if spanning
i = lineindex - 1
while i > 0:
earlier = lines[i].rstrip()
if earlier.endswith('\\'):
line = earlier[:-1] + ' ' + line
cursor += len(earlier)
i -= 1
# Join later lines while there is an explicit joining character
i = lineindex
while i < len(lines)-1 and lines[i].rstrip().endswith('\\'):
later = lines[i+1].strip()
line = line + ' ' + later[:-1]
i += 1
return line, cursor
def get_targets(line, cursor):
"""Parses a period separated string of valid names preceding the cursor and
returns them as a list in the same order.
"""
brk = 0
targets = []
j = cursor
i = j-1
while i >= 0:
if line[i] == ')': brk += 1
elif brk:
if line[i] == '(': brk -= 1
else:
if line[i] == '.':
targets.insert(0, line[i+1:j]); j=i
elif not (line[i].isalnum() or line[i] == '_' or line[i] == '.'):
break
i -= 1
targets.insert(0, line[i+1:j])
return targets
def get_defs(txt):
"""Returns a dictionary which maps definition names in the source code to
a list of their parameter names.
The line 'def doit(one, two, three): print one' for example, results in the
mapping 'doit' : [ 'one', 'two', 'three' ]
"""
return get_cached_descriptor(txt).defs
def get_vars(txt):
"""Returns a dictionary of variable names found in the specified Text
object. This method locates all names followed directly by an equal sign:
'a = ???' or indirectly as part of a tuple/list assignment or inside a
'for ??? in ???:' block.
"""
return get_cached_descriptor(txt).vars
def get_imports(txt):
"""Returns a dictionary which maps symbol names in the source code to their
respective modules.
The line 'from Blender import Text as BText' for example, results in the
mapping 'BText' : <module 'Blender.Text' (built-in)>
Note that this method imports the modules to provide this mapping as as such
will execute any initilization code found within.
"""
return get_cached_descriptor(txt).imports
def get_builtins():
"""Returns a dictionary of built-in modules, functions and variables."""
return __builtin__.__dict__
#################################
## Debugging utility functions ##
#################################
def print_cache_for(txt, period=sys.maxint):
"""Prints out the data cached for a given Text object. If no period is
given the text will not be reparsed and the cached version will be returned.
Otherwise if the period has expired the text will be reparsed.
"""
desc = get_cached_descriptor(txt, period)
print '================================================'
print 'Name:', desc.name, '('+str(hash(txt))+')'
print '------------------------------------------------'
print 'Defs:'
for name, ddesc in desc.defs.items():
print ' ', name, ddesc.params, ddesc.lineno
print ' ', ddesc.doc
print '------------------------------------------------'
print 'Vars:'
for name, vdesc in desc.vars.items():
print ' ', name, vdesc.type, vdesc.lineno
print '------------------------------------------------'
print 'Imports:'
for name, item in desc.imports.items():
print ' ', name.ljust(15), item
print '------------------------------------------------'
print 'Classes:'
for clsnme, clsdsc in desc.classes.items():
print ' *********************************'
print ' Name:', clsnme
print ' ', clsdsc.doc
print ' ---------------------------------'
print ' Defs:'
for name, ddesc in clsdsc.defs.items():
print ' ', name, ddesc.params, ddesc.lineno
print ' ', ddesc.doc
print ' ---------------------------------'
print ' Vars:'
for name, vdesc in clsdsc.vars.items():
print ' ', name, vdesc.type, vdesc.lineno
print ' *********************************'
print '================================================'

View File

@@ -1,206 +0,0 @@
import Blender
from Blender import Mathutils, Window, Scene, Draw, Mesh
from Blender.Mathutils import Matrix, Vector, Intersect
# DESCRIPTION:
# screen_x, screen_y the origin point of the pick ray
# it is either the mouse location
# localMatrix is used if you want to have the returned values in an objects localspace.
# this is usefull when dealing with an objects data such as verts.
# or if useMid is true, the midpoint of the current 3dview
# returns
# Origin - the origin point of the pick ray
# Direction - the direction vector of the pick ray
# in global coordinates
epsilon = 1e-3 # just a small value to account for floating point errors
def mouseViewRay(screen_x, screen_y, localMatrix=None, useMid = False):
# Constant function variables
p = mouseViewRay.p
d = mouseViewRay.d
for win3d in Window.GetScreenInfo(Window.Types.VIEW3D): # we search all 3dwins for the one containing the point (screen_x, screen_y) (could be the mousecoords for example)
win_min_x, win_min_y, win_max_x, win_max_y = win3d['vertices']
# calculate a few geometric extents for this window
win_mid_x = (win_max_x + win_min_x + 1.0) * 0.5
win_mid_y = (win_max_y + win_min_y + 1.0) * 0.5
win_size_x = (win_max_x - win_min_x + 1.0) * 0.5
win_size_y = (win_max_y - win_min_y + 1.0) * 0.5
#useMid is for projecting the coordinates when we subdivide the screen into bins
if useMid: # == True
screen_x = win_mid_x
screen_y = win_mid_y
# if the given screencoords (screen_x, screen_y) are within the 3dwin we fount the right one...
if (win_max_x > screen_x > win_min_x) and ( win_max_y > screen_y > win_min_y):
# first we handle all pending events for this window (otherwise the matrices might come out wrong)
Window.QHandle(win3d['id'])
# now we get a few matrices for our window...
# sorry - i cannot explain here what they all do
# - if you're not familiar with all those matrices take a look at an introduction to OpenGL...
pm = Window.GetPerspMatrix() # the prespective matrix
pmi = Matrix(pm); pmi.invert() # the inverted perspective matrix
if (1.0 - epsilon < pmi[3][3] < 1.0 + epsilon):
# pmi[3][3] is 1.0 if the 3dwin is in ortho-projection mode (toggled with numpad 5)
hms = mouseViewRay.hms
ortho_d = mouseViewRay.ortho_d
# ortho mode: is a bit strange - actually there's no definite location of the camera ...
# but the camera could be displaced anywhere along the viewing direction.
ortho_d.x, ortho_d.y, ortho_d.z = Window.GetViewVector()
ortho_d.w = 0
# all rays are parallel in ortho mode - so the direction vector is simply the viewing direction
#hms.x, hms.y, hms.z, hms.w = (screen_x-win_mid_x) /win_size_x, (screen_y-win_mid_y) / win_size_y, 0.0, 1.0
hms[:] = (screen_x-win_mid_x) /win_size_x, (screen_y-win_mid_y) / win_size_y, 0.0, 1.0
# these are the homogenious screencoords of the point (screen_x, screen_y) ranging from -1 to +1
p=(hms*pmi) + (1000*ortho_d)
p.resize3D()
d[:] = ortho_d[:3]
# Finally we shift the position infinitely far away in
# the viewing direction to make sure the camera if outside the scene
# (this is actually a hack because this function
# is used in sculpt_mesh to initialize backface culling...)
else:
# PERSPECTIVE MODE: here everything is well defined - all rays converge at the camera's location
vmi = Matrix(Window.GetViewMatrix()); vmi.invert() # the inverse viewing matrix
fp = mouseViewRay.fp
dx = pm[3][3] * (((screen_x-win_min_x)/win_size_x)-1.0) - pm[3][0]
dy = pm[3][3] * (((screen_y-win_min_y)/win_size_y)-1.0) - pm[3][1]
fp[:] = \
pmi[0][0]*dx+pmi[1][0]*dy,\
pmi[0][1]*dx+pmi[1][1]*dy,\
pmi[0][2]*dx+pmi[1][2]*dy
# fp is a global 3dpoint obtained from "unprojecting" the screenspace-point (screen_x, screen_y)
#- figuring out how to calculate this took me quite some time.
# The calculation of dxy and fp are simplified versions of my original code
#- so it's almost impossible to explain what's going on geometrically... sorry
p[:] = vmi[3][:3]
# the camera's location in global 3dcoords can be read directly from the inverted viewmatrix
#d.x, d.y, d.z =normalize_v3(sub_v3v3(p, fp))
d[:] = p.x-fp.x, p.y-fp.y, p.z-fp.z
#print 'd', d, 'p', p, 'fp', fp
# the direction vector is simply the difference vector from the virtual camera's position
#to the unprojected (screenspace) point fp
# Do we want to return a direction in object's localspace?
if localMatrix:
localInvMatrix = Matrix(localMatrix)
localInvMatrix.invert()
localInvMatrix_notrans = localInvMatrix.rotationPart()
p = p * localInvMatrix
d = d * localInvMatrix # normalize_v3
# remove the translation from d
d.x -= localInvMatrix[3][0]
d.y -= localInvMatrix[3][1]
d.z -= localInvMatrix[3][2]
d.normalize()
'''
# Debugging
me = Blender.Mesh.New()
me.verts.extend([p[0:3]])
me.verts.extend([(p-d)[0:3]])
me.edges.extend([0,1])
ob = Blender.Scene.GetCurrent().objects.new(me)
'''
return True, p, d # Origin, Direction
# Mouse is not in any view, return None.
return False, None, None
# Constant function variables
mouseViewRay.d = Vector(0,0,0) # Perspective, 3d
mouseViewRay.p = Vector(0,0,0)
mouseViewRay.fp = Vector(0,0,0)
mouseViewRay.hms = Vector(0,0,0,0) # ortho only 4d
mouseViewRay.ortho_d = Vector(0,0,0,0) # ortho only 4d
LMB= Window.MButs['L']
def mouseup():
# Loop until click
mouse_buttons = Window.GetMouseButtons()
while not mouse_buttons & LMB:
Blender.sys.sleep(10)
mouse_buttons = Window.GetMouseButtons()
while mouse_buttons & LMB:
Blender.sys.sleep(10)
mouse_buttons = Window.GetMouseButtons()
if __name__=='__main__':
mouseup()
x,y= Window.GetMouseCoords()
isect, point, dir= mouseViewRay(x,y)
if isect:
scn= Blender.Scene.GetCurrent()
me = Blender.Mesh.New()
ob= Blender.Object.New('Mesh')
ob.link(me)
scn.link(ob)
ob.sel= 1
me.verts.extend([point, dir])
me.verts[0].sel= 1
print isect, point, dir
def spaceRect():
'''
Returns the space rect
xmin,ymin,width,height
'''
__UI_RECT__ = Blender.BGL.Buffer(Blender.BGL.GL_FLOAT, 4)
Blender.BGL.glGetFloatv(Blender.BGL.GL_SCISSOR_BOX, __UI_RECT__)
__UI_RECT__ = __UI_RECT__.list
__UI_RECT__ = int(__UI_RECT__[0]), int(__UI_RECT__[1]), int(__UI_RECT__[2])-1, int(__UI_RECT__[3])
return __UI_RECT__
def mouseRelativeLoc2d(__UI_RECT__= None):
if not __UI_RECT__:
__UI_RECT__ = spaceRect()
mco = Window.GetMouseCoords()
if mco[0] > __UI_RECT__[0] and\
mco[1] > __UI_RECT__[1] and\
mco[0] < __UI_RECT__[0] + __UI_RECT__[2] and\
mco[1] < __UI_RECT__[1] + __UI_RECT__[3]:
return (mco[0] - __UI_RECT__[0], mco[1] - __UI_RECT__[1])
else:
return None

View File

@@ -1,95 +0,0 @@
#!/usr/bin/python
# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
import struct
# In Blender, selecting scenes in the databrowser (shift+f4) will tag for rendering.
# This struct wont change according to ton.
# Note that the size differs on 32/64bit
'''
typedef struct BHead {
int code, len;
void *old;
int SDNAnr, nr;
} BHead;
'''
def read_blend_rend_chunk(path):
file = open(path, 'rb')
if file.read(len('BLENDER')) != 'BLENDER':
return []
#
if file.read(1) == '-':
is64bit = True
else: # '_'
is64bit = False
if file.read(1) == 'V':
isBigEndian = True # ppc
else: # 'V'
isBigEndian = False # x86
# Now read the bhead chunk!!!
file.read(3) # skip the version
scenes = []
while file.read(4) == 'REND':
if is64bit: sizeof_bhead = sizeof_bhead_left = 24 # 64bit
else: sizeof_bhead = sizeof_bhead_left = 20 # 32bit
sizeof_bhead_left -= 4
if isBigEndian: rend_length = struct.unpack('>i', file.read(4))[0]
else: rend_length = struct.unpack('<i', file.read(4))[0]
sizeof_bhead_left -= 4
# We dont care about the rest of the bhead struct
file.read(sizeof_bhead_left)
# Now we want the scene name, start and end frame. this is 32bites long
if isBigEndian: start_frame, end_frame = struct.unpack('>2i', file.read(8))
else: start_frame, end_frame = struct.unpack('<2i', file.read(8))
scene_name = file.read(24)
scene_name = scene_name[ : scene_name.index('\0') ]
scenes.append( (start_frame, end_frame, scene_name) )
return scenes
def main():
import sys
for arg in sys.argv[1:]:
if arg.lower().endswith('.blend'):
print read_blend_rend_chunk(arg)
if __name__ == '__main__':
main()

View File

@@ -1,941 +0,0 @@
# Default Doodad Set for Discombobulator
# by Evan J. Rosky, 2005
# GPL- http://www.gnu.org/copyleft/gpl.html
#
# $Id$
# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
# Copyright (C) 2005: Evan J. Rosky
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
#Run discombobulator.py, not this.
import Blender
from Blender import NMesh,Object,Material
from Blender.NMesh import Vert,Face
from Blender.Mathutils import *
import BPyMathutils
from BPyMathutils import genrand
a = BPyMathutils.sgenrand(4859)
#Create random numbers
def randnum(low,high):
num = genrand()
num = num*(high-low)
num = num+low
return num
face = Face()
xmin = Vector([0,0,0])
xmax = Vector([0,0,0])
ymin = Vector([0,0,0])
ymax = Vector([0,0,0])
mxmin = Vector([0,0,0])
mxmax = Vector([0,0,0])
mymin = Vector([0,0,0])
mymax = Vector([0,0,0])
doodadCenter = Vector([0,0,0])
orientation = 0
center = Vector([0,0,0])
tosel = 0
seltopsonly = 0
tempx = []
doodadMesh = NMesh.GetRaw()
global materialArray
global reassignMats
global thereAreMats
global currmat
global doodSideMat
global doodTopMat
#face is the face to add the doodad to.
#sizeX and sizeY are values from 0.0 to 1.0 that represents a percentage the face that is covered by the doodad.
#height is how tall the doodad is.
def settings(seltops,matArr,reasMats,therMats,sidemat,topmat):
global seltopsonly
global materialArray
global reassignMats
global thereAreMats
global currmat
global doodSideMat
global doodTopMat
materialArray = matArr
reassignMats = reasMats
thereAreMats = therMats
seltopsonly = seltops
doodSideMat = sidemat
doodTopMat = topmat
def setCurrMat(curma):
global currmat
currmat = curma
#Find center and orientation of doodad
def findDoodadCenter(sizeX, sizeY):
#globalizing junk
global face
global xmin
global xmax
global ymin
global ymax
global orientation
global doodadCenter
global center
global tosel
global mxmin
global mxmax
global mymin
global mymax
global tempx
global seltopsonly
#Find the center of the face
center = Vector([0,0,0])
for pt in face.v:
center = center + pt.co
center = divideVectorByInt(center,len(face.v))
#Find Temp Location Range by looking at the sizes
txmin = ((divideVectorByInt((face.v[0].co + face.v[3].co),2)) - center)*(1-sizeX) + center
txmax = ((divideVectorByInt((face.v[1].co + face.v[2].co),2)) - center)*(1-sizeX) + center
tymin = ((divideVectorByInt((face.v[0].co + face.v[1].co),2)) - center)*(1-sizeY) + center
tymax = ((divideVectorByInt((face.v[2].co + face.v[3].co),2)) - center)*(1-sizeY) + center
#Find Center of doodad
amtx = randnum(0.0,1.0)
amty = randnum(0.0,1.0)
thepoint = (((((txmin - txmax)*amtx + txmax) - ((tymin - tymax)*amty + tymax))*.5 + ((tymin - tymax)*amty + tymax)) - center)*2 + center
doodadCenter = Vector([thepoint[0],thepoint[1],thepoint[2]])
#Find Main Range by looking at the sizes
mxmin = divideVectorByInt((face.v[0].co + face.v[3].co),2)
mxmax = divideVectorByInt((face.v[1].co + face.v[2].co),2)
mymin = divideVectorByInt((face.v[0].co + face.v[1].co),2)
mymax = divideVectorByInt((face.v[2].co + face.v[3].co),2)
#Find x/y equivs for whole face
ve1 = (txmin - txmax)*amtx + txmax
ve1 = ve1 - mxmax
nax = ve1.length
ve1 = (mxmin - mxmax)
nax = nax/ve1.length
ve1 = (tymin - tymax)*amty + tymax
ve1 = ve1 - mymax
nay = ve1.length
ve1 = (mymin - mymax)
nay = nay/ve1.length
#Find new box thing
tempx = []
amtx = nax-sizeX/2
amty = nay-sizeY/2
tempx.append((((((mxmin - mxmax)*amtx + mxmax) - ((mymin - mymax)*amty + mymax))*.5 + ((mymin - mymax)*amty + mymax)) - center)*2 + center)
amtx = nax-sizeX/2
amty = nay+sizeY/2
tempx.append((((((mxmin - mxmax)*amtx + mxmax) - ((mymin - mymax)*amty + mymax))*.5 + ((mymin - mymax)*amty + mymax)) - center)*2 + center)
amtx = nax+sizeX/2
amty = nay+sizeY/2
tempx.append((((((mxmin - mxmax)*amtx + mxmax) - ((mymin - mymax)*amty + mymax))*.5 + ((mymin - mymax)*amty + mymax)) - center)*2 + center)
amtx = nax+sizeX/2
amty = nay-sizeY/2
tempx.append((((((mxmin - mxmax)*amtx + mxmax) - ((mymin - mymax)*amty + mymax))*.5 + ((mymin - mymax)*amty + mymax)) - center)*2 + center)
#Find New Location Range by looking at the sizes
xmin = divideVectorByInt((tempx[0] + tempx[3]),2)
xmax = divideVectorByInt((tempx[1] + tempx[2]),2)
ymin = divideVectorByInt((tempx[0] + tempx[1]),2)
ymax = divideVectorByInt((tempx[2] + tempx[3]),2)
#Make a point
def makePoint(x,y,z=0):
global xmin
global xmax
global ymin
global ymax
global doodadCenter
global tosel
global seltopsonly
global face
amtx = x
amty = y
thepoint = (((((xmin - xmax)*amtx + xmax) - ((ymin - ymax)*amty + ymax))*.5 + ((ymin - ymax)*amty + ymax)) - doodadCenter)*2 + doodadCenter
thepoint = thepoint + z*Vector(face.no)
tver = Vert(thepoint[0],thepoint[1],thepoint[2])
if tosel == 1 and seltopsonly == 0 and z == 0:
tver.sel = 1
return tver
#extrude ground-plane(s)
def extrudedoodad(vArray,heig):
global face
global doodadMesh
global tosel
topVArray = []
doodadMesh.verts.extend(vArray)
#Create array for extruded verts
for ind in range(0,(len(vArray))):
point = vArray[ind].co + heig*Vector(face.no)
ver = Vert(point[0],point[1],point[2])
if tosel == 1:
ver.sel = 1
topVArray.append(ver)
doodadMesh.verts.append(topVArray[ind])
#make faces around sides
for ind in range(0,(len(vArray) - 1)):
face = Face()
face.v.extend([vArray[ind],vArray[ind+1],topVArray[ind+1],topVArray[ind]])
if tosel == 1 and seltopsonly == 0: face.sel = 1
if thereAreMats == 1:
if reassignMats == 0 or doodSideMat == 0:
face.materialIndex = currmat
else:
face.materialIndex = doodSideMat-1
doodadMesh.faces.append(face)
face = Face()
face.v.extend([vArray[len(vArray) - 1],vArray[0],topVArray[0],topVArray[len(topVArray) - 1]])
if tosel == 1 and seltopsonly == 0:
face.sel = 1
if thereAreMats == 1:
if reassignMats == 0 or doodSideMat == 0:
face.materialIndex = currmat
else:
face.materialIndex = doodSideMat-1
doodadMesh.faces.append(face)
return topVArray
#For switching face vertices
def fixvertindex(ind):
if ind > 3:
indx = ind - 4
else:
indx = ind
return indx
#runs doodads
def createDoodad(indexArray,facec,minsi,maxsi,minhei,maxhei,selec,amtmin,amtmax,facpercent):
global doodadMesh
global seltopsonly
global tosel
doodadMesh = NMesh.GetRaw()
theamt = round(randnum(amtmin,amtmax),0)
theamt = int(theamt)
tosel = selec
for i in range(0,(theamt)):
if randnum(0,1) <= facpercent:
index = round(randnum(1,len(indexArray)),0)
index = indexArray[(int(index) - 1)]
Xsi = randnum(minsi,maxsi)
Ysi = randnum(minsi,maxsi)
hei = randnum(minhei,maxhei)
#Determine orientation
orient = int(round(randnum(0.0,3.0)))
#face to use as range
facer = Face()
facer.v.extend([facec.v[orient],facec.v[fixvertindex(1+orient)],facec.v[fixvertindex(2+orient)],facec.v[fixvertindex(3+orient)]])
if index == 1:
singleBox(facer,Xsi,Ysi,hei)
if index == 2:
doubleBox(facer,Xsi,Ysi,hei)
if index == 3:
tripleBox(facer,Xsi,Ysi,hei)
if index == 4:
LShape(facer,Xsi,Ysi,hei)
if index == 5:
TShape(facer,Xsi,Ysi,hei)
if index == 6:
if randnum(0.0,1.0) > .5:
SShape(facer,Xsi,Ysi,hei)
else:
ZShape(facer,Xsi,Ysi,hei)
return doodadMesh
def divideVectorByInt(thevect,theint):
thevect.x = thevect.x/theint
thevect.y = thevect.y/theint
thevect.z = thevect.z/theint
return thevect
#Single Box Doodad
def singleBox(facel, Xsize, Ysize, height):
#globaling junk
global face
global tosel
global doodadMesh
face = Face()
face = facel
findDoodadCenter(Xsize, Ysize)
vertArray = []
#place four points
vertArray.append(makePoint(0,0))
vertArray.append(makePoint(0,1))
vertArray.append(makePoint(1,1))
vertArray.append(makePoint(1,0))
topVertArray = extrudedoodad(vertArray,height)
face = Face()
face.v.extend(vertArray)
face.v.reverse()
doodadMesh.faces.append(face)
face = Face()
face.v.extend(topVertArray)
if tosel == 1:
face.sel = 1
if thereAreMats == 1:
if reassignMats == 0 or doodTopMat == 0:
face.materialIndex = currmat
else:
face.materialIndex = doodTopMat-1
doodadMesh.faces.append(face)
#Double Box Doodad
def doubleBox(facel, Xsize, Ysize, height):
#globaling junk
global face
global tosel
global doodadMesh
face = Face()
face = facel
findDoodadCenter(Xsize, Ysize)
vertArray = []
#place first box
vertArray.append(makePoint(0,0))
vertArray.append(makePoint(0,1))
vertArray.append(makePoint(0.45,1))
vertArray.append(makePoint(0.45,0))
topVertArray = extrudedoodad(vertArray,height)
face = Face()
face.v.extend(vertArray)
face.v.reverse()
doodadMesh.faces.append(face)
face = Face()
face.v.extend(topVertArray)
if tosel == 1:
face.sel = 1
if thereAreMats == 1:
if reassignMats == 0 or doodTopMat == 0:
face.materialIndex = currmat
else:
face.materialIndex = doodTopMat-1
doodadMesh.faces.append(face)
vertArray = []
#place second box
vertArray.append(makePoint(0.55,0))
vertArray.append(makePoint(0.55,1))
vertArray.append(makePoint(1,1))
vertArray.append(makePoint(1,0))
topVertArray = extrudedoodad(vertArray,height)
face = Face()
face.v.extend(vertArray)
face.v.reverse()
doodadMesh.faces.append(face)
face = Face()
face.v.extend(topVertArray)
if tosel == 1:
face.sel = 1
if thereAreMats == 1:
if reassignMats == 0 or doodTopMat == 0:
face.materialIndex = currmat
else:
face.materialIndex = doodTopMat-1
doodadMesh.faces.append(face)
#Triple Box Doodad
def tripleBox(facel, Xsize, Ysize, height):
#globaling junk
global face
global tosel
global doodadMesh
face = Face()
face = facel
findDoodadCenter(Xsize, Ysize)
vertArray = []
#place first box
vertArray.append(makePoint(0,0))
vertArray.append(makePoint(0,1))
vertArray.append(makePoint(0.3,1))
vertArray.append(makePoint(0.3,0))
topVertArray = extrudedoodad(vertArray,height)
face = Face()
face.v.extend(vertArray)
face.v.reverse()
doodadMesh.faces.append(face)
face = Face()
face.v.extend(topVertArray)
if tosel == 1:
face.sel = 1
if thereAreMats == 1:
if reassignMats == 0 or doodTopMat == 0:
face.materialIndex = currmat
else:
face.materialIndex = doodTopMat-1
doodadMesh.faces.append(face)
vertArray = []
#place second box
vertArray.append(makePoint(0.35,0))
vertArray.append(makePoint(0.35,1))
vertArray.append(makePoint(0.65,1))
vertArray.append(makePoint(0.65,0))
topVertArray = extrudedoodad(vertArray,height)
face = Face()
face.v.extend(vertArray)
face.v.reverse()
doodadMesh.faces.append(face)
face = Face()
face.v.extend(topVertArray)
if tosel == 1:
face.sel = 1
if thereAreMats == 1:
if reassignMats == 0 or doodTopMat == 0:
face.materialIndex = currmat
else:
face.materialIndex = doodTopMat-1
doodadMesh.faces.append(face)
vertArray = []
#place third box
vertArray.append(makePoint(0.7,0))
vertArray.append(makePoint(0.7,1))
vertArray.append(makePoint(1,1))
vertArray.append(makePoint(1,0))
topVertArray = extrudedoodad(vertArray,height)
face = Face()
face.v.extend(vertArray)
face.v.reverse()
doodadMesh.faces.append(face)
face = Face()
face.v.extend(topVertArray)
if tosel == 1:
face.sel = 1
if thereAreMats == 1:
if reassignMats == 0 or doodTopMat == 0:
face.materialIndex = currmat
else:
face.materialIndex = doodTopMat-1
doodadMesh.faces.append(face)
#The "L" Shape
def LShape(facel, Xsize, Ysize, height):
#globaling junk
global face
global tosel
global doodadMesh
face = Face()
face = facel
findDoodadCenter(Xsize, Ysize)
rcon1 = randnum(0.2,0.8)
rcon2 = randnum(0.2,0.8)
vertArray = []
#place L shape
vertArray.append(makePoint(0,0))
vertArray.append(makePoint(0,rcon1))
vertArray.append(makePoint(0,1))
vertArray.append(makePoint(rcon2,1))
vertArray.append(makePoint(rcon2,rcon1))
vertArray.append(makePoint(1,rcon1))
vertArray.append(makePoint(1,0))
vertArray.append(makePoint(rcon2,0))
topVertArray = extrudedoodad(vertArray,height)
#This fills in the bottom of doodad with faceness
face = Face()
face.v.extend([vertArray[0],vertArray[1],vertArray[4],vertArray[7]])
face.v.reverse()
if thereAreMats == 1:
if reassignMats == 0 or doodTopMat == 0:
face.materialIndex = currmat
else:
face.materialIndex = doodTopMat-1
doodadMesh.faces.append(face)
face = Face()
face.v.extend([vertArray[1],vertArray[2],vertArray[3],vertArray[4]])
face.v.reverse()
if thereAreMats == 1:
if reassignMats == 0 or doodTopMat == 0:
face.materialIndex = currmat
else:
face.materialIndex = doodTopMat-1
doodadMesh.faces.append(face)
face = Face()
face.v.extend([vertArray[4],vertArray[5],vertArray[6],vertArray[7]])
face.v.reverse()
if thereAreMats == 1:
if reassignMats == 0 or doodTopMat == 0:
face.materialIndex = currmat
else:
face.materialIndex = doodTopMat-1
doodadMesh.faces.append(face)
#This fills in the top with faceness
face = Face()
face.v.extend([topVertArray[0],topVertArray[1],topVertArray[4],topVertArray[7]])
if tosel == 1:
face.sel = 1
if thereAreMats == 1:
if reassignMats == 0 or doodTopMat == 0:
face.materialIndex = currmat
else:
face.materialIndex = doodTopMat-1
doodadMesh.faces.append(face)
face = Face()
face.v.extend([topVertArray[1],topVertArray[2],topVertArray[3],topVertArray[4]])
if tosel == 1:
face.sel = 1
if thereAreMats == 1:
if reassignMats == 0 or doodTopMat == 0:
face.materialIndex = currmat
else:
face.materialIndex = doodTopMat-1
doodadMesh.faces.append(face)
face = Face()
face.v.extend([topVertArray[4],topVertArray[5],topVertArray[6],topVertArray[7]])
if tosel == 1:
face.sel = 1
if thereAreMats == 1:
if reassignMats == 0 or doodTopMat == 0:
face.materialIndex = currmat
else:
face.materialIndex = doodTopMat-1
doodadMesh.faces.append(face)
#The "T" Shape
def TShape(facel, Xsize, Ysize, height):
#globaling junk
global face
global tosel
global doodadMesh
face = Face()
face = facel
findDoodadCenter(Xsize, Ysize)
rcony = randnum(0.25,0.75)
rconx1 = randnum(0.1,0.49)
rconx2 = randnum(0.51,0.9)
vertArray = []
#place T shape
vertArray.append(makePoint(0,0))
vertArray.append(makePoint(0,rcony))
vertArray.append(makePoint(rconx1,rcony))
vertArray.append(makePoint(rconx1,1))
vertArray.append(makePoint(rconx2,1))
vertArray.append(makePoint(rconx2,rcony))
vertArray.append(makePoint(1,rcony))
vertArray.append(makePoint(1,0))
vertArray.append(makePoint(rconx2,0))
vertArray.append(makePoint(rconx1,0))
topVertArray = extrudedoodad(vertArray,height)
#fills bottom with faceness
face = Face()
face.v.extend([vertArray[0],vertArray[1],vertArray[2],vertArray[9]])
face.v.reverse()
if thereAreMats == 1:
if reassignMats == 0 or doodTopMat == 0:
face.materialIndex = currmat
else:
face.materialIndex = doodTopMat-1
doodadMesh.faces.append(face)
face = Face()
face.v.extend([vertArray[2],vertArray[3],vertArray[4],vertArray[5]])
face.v.reverse()
if thereAreMats == 1:
if reassignMats == 0 or doodTopMat == 0:
face.materialIndex = currmat
else:
face.materialIndex = doodTopMat-1
doodadMesh.faces.append(face)
face = Face()
face.v.extend([vertArray[5],vertArray[6],vertArray[7],vertArray[8]])
face.v.reverse()
if thereAreMats == 1:
if reassignMats == 0 or doodTopMat == 0:
face.materialIndex = currmat
else:
face.materialIndex = doodTopMat-1
doodadMesh.faces.append(face)
face = Face()
face.v.extend([vertArray[8],vertArray[9],vertArray[2],vertArray[5]])
face.v.reverse()
if thereAreMats == 1:
if reassignMats == 0 or doodTopMat == 0:
face.materialIndex = currmat
else:
face.materialIndex = doodTopMat-1
doodadMesh.faces.append(face)
#fills top with faceness
face = Face()
face.v.extend([topVertArray[0],topVertArray[1],topVertArray[2],topVertArray[9]])
if tosel == 1:
face.sel = 1
if thereAreMats == 1:
if reassignMats == 0 or doodTopMat == 0:
face.materialIndex = currmat
else:
face.materialIndex = doodTopMat-1
doodadMesh.faces.append(face)
face = Face()
face.v.extend([topVertArray[2],topVertArray[3],topVertArray[4],topVertArray[5]])
if tosel == 1:
face.sel = 1
if thereAreMats == 1:
if reassignMats == 0 or doodTopMat == 0:
face.materialIndex = currmat
else:
face.materialIndex = doodTopMat-1
doodadMesh.faces.append(face)
face = Face()
face.v.extend([topVertArray[5],topVertArray[6],topVertArray[7],topVertArray[8]])
if tosel == 1:
face.sel = 1
if thereAreMats == 1:
if reassignMats == 0 or doodTopMat == 0:
face.materialIndex = currmat
else:
face.materialIndex = doodTopMat-1
doodadMesh.faces.append(face)
face = Face()
face.v.extend([topVertArray[8],topVertArray[9],topVertArray[2],topVertArray[5]])
if tosel == 1:
face.sel = 1
if thereAreMats == 1:
if reassignMats == 0 or doodTopMat == 0:
face.materialIndex = currmat
else:
face.materialIndex = doodTopMat-1
doodadMesh.faces.append(face)
#The "S" or "Z" Shapes
def SShape(facel, Xsize, Ysize, height):
#globaling junk
global face
global tosel
global doodadMesh
face = Face()
face = facel
findDoodadCenter(Xsize, Ysize)
rcony1 = randnum(0.1,0.49)
rcony2 = randnum(0.51,0.9)
rconx1 = randnum(0.1,0.49)
rconx2 = randnum(0.51,0.9)
vertArray = []
#place S shape
vertArray.append(makePoint(0,0))
vertArray.append(makePoint(0,rcony1))
vertArray.append(makePoint(rconx1,rcony1))
vertArray.append(makePoint(rconx1,rcony2))
vertArray.append(makePoint(rconx1,1))
vertArray.append(makePoint(rconx2,1))
vertArray.append(makePoint(1,1))
vertArray.append(makePoint(1,rcony2))
vertArray.append(makePoint(rconx2,rcony2))
vertArray.append(makePoint(rconx2,rcony1))
vertArray.append(makePoint(rconx2,0))
vertArray.append(makePoint(rconx1,0))
topVertArray = extrudedoodad(vertArray,height)
#fills bottom with faceness
face = Face()
face.v.extend([vertArray[0],vertArray[1],vertArray[2],vertArray[11]])
face.v.reverse()
if thereAreMats == 1:
if reassignMats == 0 or doodTopMat == 0:
face.materialIndex = currmat
else:
face.materialIndex = doodTopMat-1
doodadMesh.faces.append(face)
face = Face()
face.v.extend([vertArray[2],vertArray[9],vertArray[10],vertArray[11]])
face.v.reverse()
if thereAreMats == 1:
if reassignMats == 0 or doodTopMat == 0:
face.materialIndex = currmat
else:
face.materialIndex = doodTopMat-1
doodadMesh.faces.append(face)
face = Face()
face.v.extend([vertArray[2],vertArray[3],vertArray[8],vertArray[9]])
face.v.reverse()
if thereAreMats == 1:
if reassignMats == 0 or doodTopMat == 0:
face.materialIndex = currmat
else:
face.materialIndex = doodTopMat-1
doodadMesh.faces.append(face)
face = Face()
face.v.extend([vertArray[3],vertArray[4],vertArray[5],vertArray[8]])
face.v.reverse()
if thereAreMats == 1:
if reassignMats == 0 or doodTopMat == 0:
face.materialIndex = currmat
else:
face.materialIndex = doodTopMat-1
doodadMesh.faces.append(face)
face = Face()
face.v.extend([vertArray[5],vertArray[6],vertArray[7],vertArray[8]])
face.v.reverse()
if thereAreMats == 1:
if reassignMats == 0 or doodTopMat == 0:
face.materialIndex = currmat
else:
face.materialIndex = doodTopMat-1
doodadMesh.faces.append(face)
#fills top with faceness
face = Face()
face.v.extend([topVertArray[0],topVertArray[1],topVertArray[2],topVertArray[11]])
if tosel == 1:
face.sel = 1
if thereAreMats == 1:
if reassignMats == 0 or doodTopMat == 0:
face.materialIndex = currmat
else:
face.materialIndex = doodTopMat-1
doodadMesh.faces.append(face)
face = Face()
face.v.extend([topVertArray[2],topVertArray[9],topVertArray[10],topVertArray[11]])
if tosel == 1:
face.sel = 1
if thereAreMats == 1:
if reassignMats == 0 or doodTopMat == 0:
face.materialIndex = currmat
else:
face.materialIndex = doodTopMat-1
doodadMesh.faces.append(face)
face = Face()
face.v.extend([topVertArray[2],topVertArray[3],topVertArray[8],topVertArray[9]])
if tosel == 1:
face.sel = 1
if thereAreMats == 1:
if reassignMats == 0 or doodTopMat == 0:
face.materialIndex = currmat
else:
face.materialIndex = doodTopMat-1
doodadMesh.faces.append(face)
face = Face()
face.v.extend([topVertArray[3],topVertArray[4],topVertArray[5],topVertArray[8]])
if tosel == 1:
face.sel = 1
if thereAreMats == 1:
if reassignMats == 0 or doodTopMat == 0:
face.materialIndex = currmat
else:
face.materialIndex = doodTopMat-1
doodadMesh.faces.append(face)
face = Face()
face.v.extend([topVertArray[5],topVertArray[6],topVertArray[7],topVertArray[8]])
if tosel == 1:
face.sel = 1
if thereAreMats == 1:
if reassignMats == 0 or doodTopMat == 0:
face.materialIndex = currmat
else:
face.materialIndex = doodTopMat-1
doodadMesh.faces.append(face)
def ZShape(facel, Xsize, Ysize, height):
#globaling junk
global face
global tosel
global doodadMesh
face = Face()
face = facel
findDoodadCenter(Xsize, Ysize)
rcony1 = randnum(0.1,0.49)
rcony2 = randnum(0.51,0.9)
rconx1 = randnum(0.1,0.49)
rconx2 = randnum(0.51,0.9)
vertArray = []
#place Z shape
vertArray.append(makePoint(0,0))
vertArray.append(makePoint(0,rcony1))
vertArray.append(makePoint(0,rcony2))
vertArray.append(makePoint(rconx1,rcony2))
vertArray.append(makePoint(rconx2,rcony2))
vertArray.append(makePoint(rconx2,1))
vertArray.append(makePoint(1,1))
vertArray.append(makePoint(1,rcony2))
vertArray.append(makePoint(1,rcony1))
vertArray.append(makePoint(rconx2,rcony1))
vertArray.append(makePoint(rconx1,rcony1))
vertArray.append(makePoint(rconx1,0))
topVertArray = extrudedoodad(vertArray,height)
#fills bottom with faceness
face = Face()
face.v.extend([vertArray[0],vertArray[1],vertArray[10],vertArray[11]])
face.v.reverse()
if thereAreMats == 1:
if reassignMats == 0 or doodTopMat == 0:
face.materialIndex = currmat
else:
face.materialIndex = doodTopMat-1
doodadMesh.faces.append(face)
face = Face()
face.v.extend([vertArray[1],vertArray[2],vertArray[3],vertArray[10]])
face.v.reverse()
if thereAreMats == 1:
if reassignMats == 0 or doodTopMat == 0:
face.materialIndex = currmat
else:
face.materialIndex = doodTopMat-1
doodadMesh.faces.append(face)
face = Face()
face.v.extend([vertArray[3],vertArray[4],vertArray[9],vertArray[10]])
face.v.reverse()
if thereAreMats == 1:
if reassignMats == 0 or doodTopMat == 0:
face.materialIndex = currmat
else:
face.materialIndex = doodTopMat-1
doodadMesh.faces.append(face)
face = Face()
face.v.extend([vertArray[4],vertArray[7],vertArray[8],vertArray[9]])
face.v.reverse()
if thereAreMats == 1:
if reassignMats == 0 or doodTopMat == 0:
face.materialIndex = currmat
else:
face.materialIndex = doodTopMat-1
doodadMesh.faces.append(face)
face = Face()
face.v.extend([vertArray[4],vertArray[5],vertArray[6],vertArray[7]])
face.v.reverse()
if thereAreMats == 1:
if reassignMats == 0 or doodTopMat == 0:
face.materialIndex = currmat
else:
face.materialIndex = doodTopMat-1
doodadMesh.faces.append(face)
#fills top with faceness
face = Face()
face.v.extend([topVertArray[0],topVertArray[1],topVertArray[10],topVertArray[11]])
if tosel == 1:
face.sel = 1
if thereAreMats == 1:
if reassignMats == 0 or doodTopMat == 0:
face.materialIndex = currmat
else:
face.materialIndex = doodTopMat-1
doodadMesh.faces.append(face)
face = Face()
face.v.extend([topVertArray[1],topVertArray[2],topVertArray[3],topVertArray[10]])
if tosel == 1:
face.sel = 1
if thereAreMats == 1:
if reassignMats == 0 or doodTopMat == 0:
face.materialIndex = currmat
else:
face.materialIndex = doodTopMat-1
doodadMesh.faces.append(face)
face = Face()
face.v.extend([topVertArray[3],topVertArray[4],topVertArray[9],topVertArray[10]])
if tosel == 1:
face.sel = 1
if thereAreMats == 1:
if reassignMats == 0 or doodTopMat == 0:
face.materialIndex = currmat
else:
face.materialIndex = doodTopMat-1
doodadMesh.faces.append(face)
face = Face()
face.v.extend([topVertArray[4],topVertArray[7],topVertArray[8],topVertArray[9]])
if tosel == 1:
face.sel = 1
if thereAreMats == 1:
if reassignMats == 0 or doodTopMat == 0:
face.materialIndex = currmat
else:
face.materialIndex = doodTopMat-1
doodadMesh.faces.append(face)
face = Face()
face.v.extend([topVertArray[4],topVertArray[5],topVertArray[6],topVertArray[7]])
if tosel == 1:
face.sel = 1
if thereAreMats == 1:
if reassignMats == 0 or doodTopMat == 0:
face.materialIndex = currmat
else:
face.materialIndex = doodTopMat-1
doodadMesh.faces.append(face)

View File

@@ -1,282 +0,0 @@
# dictionary mapping AutoCAD color indexes with Blender colors
# --------------------------------------------------------------------------
# color_map.py Final by Ed Blake (AKA Kitsu)
# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
color_map = {
0:[0.0, 0.0, 0.0],
1:[0.99609375, 0.0, 0.0],
2:[0.99609375, 0.99609375, 0.0],
3:[0.0, 0.99609375, 0.0],
4:[0.0, 0.99609375, 0.99609375],
5:[0.0, 0.0, 0.99609375],
6:[0.99609375, 0.0, 0.99609375],
7:[0.99609375, 0.99609375, 0.99609375],
8:[0.25390625, 0.25390625, 0.25390625],
9:[0.5, 0.5, 0.5],
10:[0.99609375, 0.0, 0.0],
11:[0.99609375, 0.6640625, 0.6640625],
12:[0.73828125, 0.0, 0.0],
13:[0.73828125, 0.4921875, 0.4921875],
14:[0.50390625, 0.0, 0.0],
15:[0.50390625, 0.3359375, 0.3359375],
16:[0.40625, 0.0, 0.0],
17:[0.40625, 0.26953125, 0.26953125],
18:[0.30859375, 0.0, 0.0],
19:[0.30859375, 0.20703125, 0.20703125],
20:[0.99609375, 0.24609375, 0.0],
21:[0.99609375, 0.74609375, 0.6640625],
22:[0.73828125, 0.1796875, 0.0],
23:[0.73828125, 0.55078125, 0.4921875],
24:[0.50390625, 0.12109375, 0.0],
25:[0.50390625, 0.375, 0.3359375],
26:[0.40625, 0.09765625, 0.0],
27:[0.40625, 0.3046875, 0.26953125],
28:[0.30859375, 0.07421875, 0.0],
29:[0.30859375, 0.23046875, 0.20703125],
30:[0.99609375, 0.49609375, 0.0],
31:[0.99609375, 0.828125, 0.6640625],
32:[0.73828125, 0.3671875, 0.0],
33:[0.73828125, 0.61328125, 0.4921875],
34:[0.50390625, 0.25, 0.0],
35:[0.50390625, 0.41796875, 0.3359375],
36:[0.40625, 0.203125, 0.0],
37:[0.40625, 0.3359375, 0.26953125],
38:[0.30859375, 0.15234375, 0.0],
39:[0.30859375, 0.2578125, 0.20703125],
40:[0.99609375, 0.74609375, 0.0],
41:[0.99609375, 0.9140625, 0.6640625],
42:[0.73828125, 0.55078125, 0.0],
43:[0.73828125, 0.67578125, 0.4921875],
44:[0.50390625, 0.375, 0.0],
45:[0.50390625, 0.4609375, 0.3359375],
46:[0.40625, 0.3046875, 0.0],
47:[0.40625, 0.37109375, 0.26953125],
48:[0.30859375, 0.23046875, 0.0],
49:[0.30859375, 0.28515625, 0.20703125],
50:[0.99609375, 0.99609375, 0.0],
51:[0.99609375, 0.99609375, 0.6640625],
52:[0.73828125, 0.73828125, 0.0],
53:[0.73828125, 0.73828125, 0.4921875],
54:[0.50390625, 0.50390625, 0.0],
55:[0.50390625, 0.50390625, 0.3359375],
56:[0.40625, 0.40625, 0.0],
57:[0.40625, 0.40625, 0.26953125],
58:[0.30859375, 0.30859375, 0.0],
59:[0.30859375, 0.30859375, 0.20703125],
60:[0.74609375, 0.99609375, 0.0],
61:[0.9140625, 0.99609375, 0.6640625],
62:[0.55078125, 0.73828125, 0.0],
63:[0.67578125, 0.73828125, 0.4921875],
64:[0.375, 0.50390625, 0.0],
65:[0.4609375, 0.50390625, 0.3359375],
66:[0.3046875, 0.40625, 0.0],
67:[0.37109375, 0.40625, 0.26953125],
68:[0.23046875, 0.30859375, 0.0],
69:[0.28515625, 0.30859375, 0.20703125],
70:[0.49609375, 0.99609375, 0.0],
71:[0.828125, 0.99609375, 0.6640625],
72:[0.3671875, 0.73828125, 0.0],
73:[0.61328125, 0.73828125, 0.4921875],
74:[0.25, 0.50390625, 0.0],
75:[0.41796875, 0.50390625, 0.3359375],
76:[0.203125, 0.40625, 0.0],
77:[0.3359375, 0.40625, 0.26953125],
78:[0.15234375, 0.30859375, 0.0],
79:[0.2578125, 0.30859375, 0.20703125],
80:[0.24609375, 0.99609375, 0.0],
81:[0.74609375, 0.99609375, 0.6640625],
82:[0.1796875, 0.73828125, 0.0],
83:[0.55078125, 0.73828125, 0.4921875],
84:[0.12109375, 0.50390625, 0.0],
85:[0.375, 0.50390625, 0.3359375],
86:[0.09765625, 0.40625, 0.0],
87:[0.3046875, 0.40625, 0.26953125],
88:[0.07421875, 0.30859375, 0.0],
89:[0.23046875, 0.30859375, 0.20703125],
90:[0.0, 0.99609375, 0.0],
91:[0.6640625, 0.99609375, 0.6640625],
92:[0.0, 0.73828125, 0.0],
93:[0.4921875, 0.73828125, 0.4921875],
94:[0.0, 0.50390625, 0.0],
95:[0.3359375, 0.50390625, 0.3359375],
96:[0.0, 0.40625, 0.0],
97:[0.26953125, 0.40625, 0.26953125],
98:[0.0, 0.30859375, 0.0],
99:[0.20703125, 0.30859375, 0.20703125],
100:[0.0, 0.99609375, 0.24609375],
101:[0.6640625, 0.99609375, 0.74609375],
102:[0.0, 0.73828125, 0.1796875],
103:[0.4921875, 0.73828125, 0.55078125],
104:[0.0, 0.50390625, 0.12109375],
105:[0.3359375, 0.50390625, 0.375],
106:[0.0, 0.40625, 0.09765625],
107:[0.26953125, 0.40625, 0.3046875],
108:[0.0, 0.30859375, 0.07421875],
109:[0.20703125, 0.30859375, 0.23046875],
110:[0.0, 0.99609375, 0.49609375],
111:[0.6640625, 0.99609375, 0.828125],
112:[0.0, 0.73828125, 0.3671875],
113:[0.4921875, 0.73828125, 0.61328125],
114:[0.0, 0.50390625, 0.25],
115:[0.3359375, 0.50390625, 0.41796875],
116:[0.0, 0.40625, 0.203125],
117:[0.26953125, 0.40625, 0.3359375],
118:[0.0, 0.30859375, 0.15234375],
119:[0.20703125, 0.30859375, 0.2578125],
120:[0.0, 0.99609375, 0.74609375],
121:[0.6640625, 0.99609375, 0.9140625],
122:[0.0, 0.73828125, 0.55078125],
123:[0.4921875, 0.73828125, 0.67578125],
124:[0.0, 0.50390625, 0.375],
125:[0.3359375, 0.50390625, 0.4609375],
126:[0.0, 0.40625, 0.3046875],
127:[0.26953125, 0.40625, 0.37109375],
128:[0.0, 0.30859375, 0.23046875],
129:[0.20703125, 0.30859375, 0.28515625],
130:[0.0, 0.99609375, 0.99609375],
131:[0.6640625, 0.99609375, 0.99609375],
132:[0.0, 0.73828125, 0.73828125],
133:[0.4921875, 0.73828125, 0.73828125],
134:[0.0, 0.50390625, 0.50390625],
135:[0.3359375, 0.50390625, 0.50390625],
136:[0.0, 0.40625, 0.40625],
137:[0.26953125, 0.40625, 0.40625],
138:[0.0, 0.30859375, 0.30859375],
139:[0.20703125, 0.30859375, 0.30859375],
140:[0.0, 0.74609375, 0.99609375],
141:[0.6640625, 0.9140625, 0.99609375],
142:[0.0, 0.55078125, 0.73828125],
143:[0.4921875, 0.67578125, 0.73828125],
144:[0.0, 0.375, 0.50390625],
145:[0.3359375, 0.4609375, 0.50390625],
146:[0.0, 0.3046875, 0.40625],
147:[0.26953125, 0.37109375, 0.40625],
148:[0.0, 0.23046875, 0.30859375],
149:[0.20703125, 0.28515625, 0.30859375],
150:[0.0, 0.49609375, 0.99609375],
151:[0.6640625, 0.828125, 0.99609375],
152:[0.0, 0.3671875, 0.73828125],
153:[0.4921875, 0.61328125, 0.73828125],
154:[0.0, 0.25, 0.50390625],
155:[0.3359375, 0.41796875, 0.50390625],
156:[0.0, 0.203125, 0.40625],
157:[0.26953125, 0.3359375, 0.40625],
158:[0.0, 0.15234375, 0.30859375],
159:[0.20703125, 0.2578125, 0.30859375],
160:[0.0, 0.24609375, 0.99609375],
161:[0.6640625, 0.74609375, 0.99609375],
162:[0.0, 0.1796875, 0.73828125],
163:[0.4921875, 0.55078125, 0.73828125],
164:[0.0, 0.12109375, 0.50390625],
165:[0.3359375, 0.375, 0.50390625],
166:[0.0, 0.09765625, 0.40625],
167:[0.26953125, 0.3046875, 0.40625],
168:[0.0, 0.07421875, 0.30859375],
169:[0.20703125, 0.23046875, 0.30859375],
170:[0.0, 0.0, 0.99609375],
171:[0.6640625, 0.6640625, 0.99609375],
172:[0.0, 0.0, 0.73828125],
173:[0.4921875, 0.4921875, 0.73828125],
174:[0.0, 0.0, 0.50390625],
175:[0.3359375, 0.3359375, 0.50390625],
176:[0.0, 0.0, 0.40625],
177:[0.26953125, 0.26953125, 0.40625],
178:[0.0, 0.0, 0.30859375],
179:[0.20703125, 0.20703125, 0.30859375],
180:[0.24609375, 0.0, 0.99609375],
181:[0.74609375, 0.6640625, 0.99609375],
182:[0.1796875, 0.0, 0.73828125],
183:[0.55078125, 0.4921875, 0.73828125],
184:[0.12109375, 0.0, 0.50390625],
185:[0.375, 0.3359375, 0.50390625],
186:[0.09765625, 0.0, 0.40625],
187:[0.3046875, 0.26953125, 0.40625],
188:[0.07421875, 0.0, 0.30859375],
189:[0.23046875, 0.20703125, 0.30859375],
190:[0.49609375, 0.0, 0.99609375],
191:[0.828125, 0.6640625, 0.99609375],
192:[0.3671875, 0.0, 0.73828125],
193:[0.61328125, 0.4921875, 0.73828125],
194:[0.25, 0.0, 0.50390625],
195:[0.41796875, 0.3359375, 0.50390625],
196:[0.203125, 0.0, 0.40625],
197:[0.3359375, 0.26953125, 0.40625],
198:[0.15234375, 0.0, 0.30859375],
199:[0.2578125, 0.20703125, 0.30859375],
200:[0.74609375, 0.0, 0.99609375],
201:[0.9140625, 0.6640625, 0.99609375],
202:[0.55078125, 0.0, 0.73828125],
203:[0.67578125, 0.4921875, 0.73828125],
204:[0.375, 0.0, 0.50390625],
205:[0.4609375, 0.3359375, 0.50390625],
206:[0.3046875, 0.0, 0.40625],
207:[0.37109375, 0.26953125, 0.40625],
208:[0.23046875, 0.0, 0.30859375],
209:[0.28515625, 0.20703125, 0.30859375],
210:[0.99609375, 0.0, 0.99609375],
211:[0.99609375, 0.6640625, 0.99609375],
212:[0.73828125, 0.0, 0.73828125],
213:[0.73828125, 0.4921875, 0.73828125],
214:[0.50390625, 0.0, 0.50390625],
215:[0.50390625, 0.3359375, 0.50390625],
216:[0.40625, 0.0, 0.40625],
217:[0.40625, 0.26953125, 0.40625],
218:[0.30859375, 0.0, 0.30859375],
219:[0.30859375, 0.20703125, 0.30859375],
220:[0.99609375, 0.0, 0.74609375],
221:[0.99609375, 0.6640625, 0.9140625],
222:[0.73828125, 0.0, 0.55078125],
223:[0.73828125, 0.4921875, 0.67578125],
224:[0.50390625, 0.0, 0.375],
225:[0.50390625, 0.3359375, 0.4609375],
226:[0.40625, 0.0, 0.3046875],
227:[0.40625, 0.26953125, 0.37109375],
228:[0.30859375, 0.0, 0.23046875],
229:[0.30859375, 0.20703125, 0.28515625],
230:[0.99609375, 0.0, 0.49609375],
231:[0.99609375, 0.6640625, 0.828125],
232:[0.73828125, 0.0, 0.3671875],
233:[0.73828125, 0.4921875, 0.61328125],
234:[0.50390625, 0.0, 0.25],
235:[0.50390625, 0.3359375, 0.41796875],
236:[0.40625, 0.0, 0.203125],
237:[0.40625, 0.26953125, 0.3359375],
238:[0.30859375, 0.0, 0.15234375],
239:[0.30859375, 0.20703125, 0.2578125],
240:[0.99609375, 0.0, 0.24609375],
241:[0.99609375, 0.6640625, 0.74609375],
242:[0.73828125, 0.0, 0.1796875],
243:[0.73828125, 0.4921875, 0.55078125],
244:[0.50390625, 0.0, 0.12109375],
245:[0.50390625, 0.3359375, 0.375],
246:[0.40625, 0.0, 0.09765625],
247:[0.40625, 0.26953125, 0.3046875],
248:[0.30859375, 0.0, 0.07421875],
249:[0.30859375, 0.20703125, 0.23046875],
250:[0.19921875, 0.19921875, 0.19921875],
251:[0.3125, 0.3125, 0.3125],
252:[0.41015625, 0.41015625, 0.41015625],
253:[0.5078125, 0.5078125, 0.5078125],
254:[0.7421875, 0.7421875, 0.7421875],
255:[0.99609375, 0.99609375, 0.99609375],
}

View File

@@ -1,880 +0,0 @@
#dxfLibrary.py : provides functions for generating DXF files
# --------------------------------------------------------------------------
__version__ = "v1.33 - 2009.06.16"
__author__ = "Stani Michiels(Stani), Remigiusz Fiedler(migius)"
__license__ = "GPL"
__url__ = "http://wiki.blender.org/index.php/Scripts/Manual/Export/autodesk_dxf"
__bpydoc__ ="""The library to export geometry data to DXF format r12 version.
Copyright %s
Version %s
License %s
Homepage %s
See the homepage for documentation.
Dedicated thread on BlenderArtists: http://blenderartists.org/forum/showthread.php?t=136439
IDEAs:
-
TODO:
- add support for DXFr14 (needs extended file header)
- add support for SPLINEs (possible first in DXFr14 version)
- add user preset for floating point precision (3-16?)
History
v1.33 - 2009.06.16 by migius
- modif _point(): converts all coords to floats
- modif LineType class: implement elements
- added VPORT class, incl. defaults
- fix Insert class
v1.32 - 2009.06.06 by migius
- modif Style class: changed defaults to widthFactor=1.0, obliqueAngle=0.0
- modif Text class: alignment parameter reactivated
v1.31 - 2009.06.02 by migius
- modif _Entity class: added paperspace,elevation
v1.30 - 2009.05.28 by migius
- bugfix 3dPOLYLINE/POLYFACE: VERTEX needs x,y,z coordinates, index starts with 1 not 0
v1.29 - 2008.12.28 by Yorik
- modif POLYLINE to support bulge segments
v1.28 - 2008.12.13 by Steeve/BlenderArtists
- bugfix for EXTMIN/EXTMAX to suit Cycas-CAD
v1.27 - 2008.10.07 by migius
- beautifying output code: keys whitespace prefix
- refactoring DXF-strings format: NewLine moved to the end of
v1.26 - 2008.10.05 by migius
- modif POLYLINE to support POLYFACE
v1.25 - 2008.09.28 by migius
- modif FACE class for r12
v1.24 - 2008.09.27 by migius
- modif POLYLINE class for r12
- changing output format from r9 to r12(AC1009)
v1.1 (20/6/2005) by www.stani.be/python/sdxf
- Python library to generate dxf drawings
______________________________________________________________
""" % (__author__,__version__,__license__,__url__)
# --------------------------------------------------------------------------
# DXF Library: copyright (C) 2005 by Stani Michiels (AKA Stani)
# 2008/2009 modif by Remigiusz Fiedler (AKA migius)
# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
#import Blender
#from Blender import Mathutils, Window, Scene, sys, Draw
#import BPyMessages
try:
import copy
#from struct import pack
except:
copy = None
####1) Private (only for developpers)
_HEADER_POINTS=['insbase','extmin','extmax']
#---helper functions-----------------------------------
def _point(x,index=0):
"""Convert tuple to a dxf point"""
#print 'deb: _point=', x #-------------
return '\n'.join([' %s\n%s'%((i+1)*10+index,float(x[i])) for i in range(len(x))])
def _points(plist):
"""Convert a list of tuples to dxf points"""
out = '\n'.join([_point(plist[i],i)for i in range(len(plist))])
return out
#---base classes----------------------------------------
class _Call:
"""Makes a callable class."""
def copy(self):
"""Returns a copy."""
return copy.deepcopy(self)
def __call__(self,**attrs):
"""Returns a copy with modified attributes."""
copied=self.copy()
for attr in attrs:setattr(copied,attr,attrs[attr])
return copied
#-------------------------------------------------------
class _Entity(_Call):
"""Base class for _common group codes for entities."""
def __init__(self,paperspace=None,color=None,layer='0',
lineType=None,lineTypeScale=None,lineWeight=None,
extrusion=None,elevation=None,thickness=None,
parent=None):
"""None values will be omitted."""
self.paperspace = paperspace
self.color = color
self.layer = layer
self.lineType = lineType
self.lineTypeScale = lineTypeScale
self.lineWeight = lineWeight
self.extrusion = extrusion
self.elevation = elevation
self.thickness = thickness
#self.visible = visible
self.parent = parent
def _common(self):
"""Return common group codes as a string."""
if self.parent:parent=self.parent
else:parent=self
result =''
if parent.paperspace==1: result+=' 67\n1\n'
if parent.layer!=None: result+=' 8\n%s\n'%parent.layer
if parent.color!=None: result+=' 62\n%s\n'%parent.color
if parent.lineType!=None: result+=' 6\n%s\n'%parent.lineType
# TODO: if parent.lineWeight!=None: result+='370\n%s\n'%parent.lineWeight
# TODO: if parent.visible!=None: result+='60\n%s\n'%parent.visible
if parent.lineTypeScale!=None: result+=' 48\n%s\n'%parent.lineTypeScale
if parent.elevation!=None: result+=' 38\n%s\n'%parent.elevation
if parent.thickness!=None: result+=' 39\n%s\n'%parent.thickness
if parent.extrusion!=None: result+='%s\n'%_point(parent.extrusion,200)
return result
#--------------------------
class _Entities:
"""Base class to deal with composed objects."""
def __dxf__(self):
return []
def __str__(self):
return ''.join([str(x) for x in self.__dxf__()])
#--------------------------
class _Collection(_Call):
"""Base class to expose entities methods to main object."""
def __init__(self,entities=[]):
self.entities=copy.copy(entities)
#link entities methods to drawing
for attr in dir(self.entities):
if attr[0]!='_':
attrObject=getattr(self.entities,attr)
if callable(attrObject):
setattr(self,attr,attrObject)
####2) Constants
#---color values
BYBLOCK=0
BYLAYER=256
#---block-type flags (bit coded values, may be combined):
ANONYMOUS =1 # This is an anonymous block generated by hatching, associative dimensioning, other internal operations, or an application
NON_CONSTANT_ATTRIBUTES =2 # This block has non-constant attribute definitions (this bit is not set if the block has any attribute definitions that are constant, or has no attribute definitions at all)
XREF =4 # This block is an external reference (xref)
XREF_OVERLAY =8 # This block is an xref overlay
EXTERNAL =16 # This block is externally dependent
RESOLVED =32 # This is a resolved external reference, or dependent of an external reference (ignored on input)
REFERENCED =64 # This definition is a referenced external reference (ignored on input)
#---mtext flags
#attachment point
TOP_LEFT = 1
TOP_CENTER = 2
TOP_RIGHT = 3
MIDDLE_LEFT = 4
MIDDLE_CENTER = 5
MIDDLE_RIGHT = 6
BOTTOM_LEFT = 7
BOTTOM_CENTER = 8
BOTTOM_RIGHT = 9
#drawing direction
LEFT_RIGHT = 1
TOP_BOTTOM = 3
BY_STYLE = 5 #the flow direction is inherited from the associated text style
#line spacing style (optional):
AT_LEAST = 1 #taller characters will override
EXACT = 2 #taller characters will not override
#---polyline flags
CLOSED =1 # This is a closed polyline (or a polygon mesh closed in the M direction)
CURVE_FIT =2 # Curve-fit vertices have been added
SPLINE_FIT =4 # Spline-fit vertices have been added
POLYLINE_3D =8 # This is a 3D polyline
POLYGON_MESH =16 # This is a 3D polygon mesh
CLOSED_N =32 # The polygon mesh is closed in the N direction
POLYFACE_MESH =64 # The polyline is a polyface mesh
CONTINOUS_LINETYPE_PATTERN =128 # The linetype pattern is generated continuously around the vertices of this polyline
#---text flags
#horizontal
LEFT = 0
CENTER = 1
RIGHT = 2
ALIGNED = 3 #if vertical alignment = 0
MIDDLE = 4 #if vertical alignment = 0
FIT = 5 #if vertical alignment = 0
#vertical
BASELINE = 0
BOTTOM = 1
MIDDLE = 2
TOP = 3
####3) Classes
#---entitities -----------------------------------------------
#--------------------------
class Arc(_Entity):
"""Arc, angles in degrees."""
def __init__(self,center=(0,0,0),radius=1,
startAngle=0.0,endAngle=90,**common):
"""Angles in degrees."""
_Entity.__init__(self,**common)
self.center=center
self.radius=radius
self.startAngle=startAngle
self.endAngle=endAngle
def __str__(self):
return ' 0\nARC\n%s%s\n 40\n%s\n 50\n%s\n 51\n%s\n'%\
(self._common(),_point(self.center),
self.radius,self.startAngle,self.endAngle)
#-----------------------------------------------
class Circle(_Entity):
"""Circle"""
def __init__(self,center=(0,0,0),radius=1,**common):
_Entity.__init__(self,**common)
self.center=center
self.radius=radius
def __str__(self):
return ' 0\nCIRCLE\n%s%s\n 40\n%s\n'%\
(self._common(),_point(self.center),self.radius)
#-----------------------------------------------
class Face(_Entity):
"""3dface"""
def __init__(self,points,**common):
_Entity.__init__(self,**common)
while len(points)<4: #fix for r12 format
points.append(points[-1])
self.points=points
def __str__(self):
out = ' 0\n3DFACE\n%s%s\n' %(self._common(),_points(self.points))
#print 'deb:out=', out #-------------------
return out
#-----------------------------------------------
class Insert(_Entity):
"""Block instance."""
def __init__(self,name,point=(0,0,0),
xscale=None,yscale=None,zscale=None,
cols=None,colspacing=None,rows=None,rowspacing=None,
rotation=None,
**common):
_Entity.__init__(self,**common)
self.name=name
self.point=point
self.xscale=xscale
self.yscale=yscale
self.zscale=zscale
self.cols=cols
self.colspacing=colspacing
self.rows=rows
self.rowspacing=rowspacing
self.rotation=rotation
def __str__(self):
result=' 0\nINSERT\n 2\n%s\n%s%s\n'%\
(self.name,self._common(),_point(self.point))
if self.xscale!=None:result+=' 41\n%s\n'%self.xscale
if self.yscale!=None:result+=' 42\n%s\n'%self.yscale
if self.zscale!=None:result+=' 43\n%s\n'%self.zscale
if self.rotation:result+=' 50\n%s\n'%self.rotation
if self.cols!=None:result+=' 70\n%s\n'%self.cols
if self.colspacing!=None:result+=' 44\n%s\n'%self.colspacing
if self.rows!=None:result+=' 71\n%s\n'%self.rows
if self.rowspacing!=None:result+=' 45\n%s\n'%self.rowspacing
return result
#-----------------------------------------------
class Line(_Entity):
"""Line"""
def __init__(self,points,**common):
_Entity.__init__(self,**common)
self.points=points
def __str__(self):
return ' 0\nLINE\n%s%s\n' %(
self._common(), _points(self.points))
#-----------------------------------------------
class PolyLine(_Entity):
def __init__(self,points,org_point=[0,0,0],flag=0,width=None,**common):
#width = number, or width = list [width_start=None, width_end=None]
#for 2d-polyline: points = [ [x, y, z, width_start=None, width_end=None, bulge=0 or None], ...]
#for 3d-polyline: points = [ [x, y, z], ...]
#for polyface: points = [points_list, faces_list]
_Entity.__init__(self,**common)
self.points=points
self.org_point=org_point
self.flag=flag
self.polyface = False
self.polyline2d = False
self.faces = [] # dummy value
self.width= None # dummy value
if self.flag & POLYFACE_MESH:
self.polyface=True
self.points=points[0]
self.faces=points[1]
self.p_count=len(self.points)
self.f_count=len(self.faces)
elif not self.flag & POLYLINE_3D:
self.polyline2d = True
if width:
if type(width)!='list':
width=[width,width]
self.width=width
def __str__(self):
result= ' 0\nPOLYLINE\n%s 70\n%s\n' %(self._common(),self.flag)
result+=' 66\n1\n'
result+='%s\n' %_point(self.org_point)
if self.polyface:
result+=' 71\n%s\n' %self.p_count
result+=' 72\n%s\n' %self.f_count
elif self.polyline2d:
if self.width!=None: result+=' 40\n%s\n 41\n%s\n' %(self.width[0],self.width[1])
for point in self.points:
result+=' 0\nVERTEX\n'
result+=' 8\n%s\n' %self.layer
if self.polyface:
result+='%s\n' %_point(point[0:3])
result+=' 70\n192\n'
elif self.polyline2d:
result+='%s\n' %_point(point[0:2])
if len(point)>4:
width1, width2 = point[3], point[4]
if width1!=None: result+=' 40\n%s\n' %width1
if width2!=None: result+=' 41\n%s\n' %width2
if len(point)==6:
bulge = point[5]
if bulge: result+=' 42\n%s\n' %bulge
else:
result+='%s\n' %_point(point[0:3])
for face in self.faces:
result+=' 0\nVERTEX\n'
result+=' 8\n%s\n' %self.layer
result+='%s\n' %_point(self.org_point)
result+=' 70\n128\n'
result+=' 71\n%s\n' %face[0]
result+=' 72\n%s\n' %face[1]
result+=' 73\n%s\n' %face[2]
if len(face)==4: result+=' 74\n%s\n' %face[3]
result+=' 0\nSEQEND\n'
result+=' 8\n%s\n' %self.layer
return result
#-----------------------------------------------
class Point(_Entity):
"""Point."""
def __init__(self,points=None,**common):
_Entity.__init__(self,**common)
self.points=points
def __str__(self): # TODO:
return ' 0\nPOINT\n%s%s\n' %(self._common(),
_points(self.points)
)
#-----------------------------------------------
class Solid(_Entity):
"""Colored solid fill."""
def __init__(self,points=None,**common):
_Entity.__init__(self,**common)
self.points=points
def __str__(self):
return ' 0\nSOLID\n%s%s\n' %(self._common(),
_points(self.points[:2]+[self.points[3],self.points[2]])
)
#-----------------------------------------------
class Text(_Entity):
"""Single text line."""
def __init__(self,text='',point=(0,0,0),alignment=None,
flag=None,height=1,justifyhor=None,justifyver=None,
rotation=None,obliqueAngle=None,style=None,xscale=None,**common):
_Entity.__init__(self,**common)
self.text=text
self.point=point
self.alignment=alignment
self.flag=flag
self.height=height
self.justifyhor=justifyhor
self.justifyver=justifyver
self.rotation=rotation
self.obliqueAngle=obliqueAngle
self.style=style
self.xscale=xscale
def __str__(self):
result= ' 0\nTEXT\n%s%s\n 40\n%s\n 1\n%s\n'%\
(self._common(),_point(self.point),self.height,self.text)
if self.rotation: result+=' 50\n%s\n'%self.rotation
if self.xscale: result+=' 41\n%s\n'%self.xscale
if self.obliqueAngle: result+=' 51\n%s\n'%self.obliqueAngle
if self.style: result+=' 7\n%s\n'%self.style
if self.flag: result+=' 71\n%s\n'%self.flag
if self.justifyhor: result+=' 72\n%s\n'%self.justifyhor
if self.alignment: result+='%s\n'%_point(self.alignment,1)
if self.justifyver: result+=' 73\n%s\n'%self.justifyver
return result
#-----------------------------------------------
class Mtext(Text):
"""Surrogate for mtext, generates some Text instances."""
def __init__(self,text='',point=(0,0,0),width=250,spacingFactor=1.5,down=0,spacingWidth=None,**options):
Text.__init__(self,text=text,point=point,**options)
if down:spacingFactor*=-1
self.spacingFactor=spacingFactor
self.spacingWidth=spacingWidth
self.width=width
self.down=down
def __str__(self):
texts=self.text.replace('\r\n','\n').split('\n')
if not self.down:texts.reverse()
result=''
x=y=0
if self.spacingWidth:spacingWidth=self.spacingWidth
else:spacingWidth=self.height*self.spacingFactor
for text in texts:
while text:
result+='%s\n'%Text(text[:self.width],
point=(self.point[0]+x*spacingWidth,
self.point[1]+y*spacingWidth,
self.point[2]),
alignment=self.alignment,flag=self.flag,height=self.height,
justifyhor=self.justifyhor,justifyver=self.justifyver,
rotation=self.rotation,obliqueAngle=self.obliqueAngle,
style=self.style,xscale=self.xscale,parent=self
)
text=text[self.width:]
if self.rotation:x+=1
else:y+=1
return result[1:]
#-----------------------------------------------
##class _Mtext(_Entity):
## """Mtext not functioning for minimal dxf."""
## def __init__(self,text='',point=(0,0,0),attachment=1,
## charWidth=None,charHeight=1,direction=1,height=100,rotation=0,
## spacingStyle=None,spacingFactor=None,style=None,width=100,
## xdirection=None,**common):
## _Entity.__init__(self,**common)
## self.text=text
## self.point=point
## self.attachment=attachment
## self.charWidth=charWidth
## self.charHeight=charHeight
## self.direction=direction
## self.height=height
## self.rotation=rotation
## self.spacingStyle=spacingStyle
## self.spacingFactor=spacingFactor
## self.style=style
## self.width=width
## self.xdirection=xdirection
## def __str__(self):
## input=self.text
## text=''
## while len(input)>250:
## text+='3\n%s\n'%input[:250]
## input=input[250:]
## text+='1\n%s\n'%input
## result= '0\nMTEXT\n%s\n%s\n40\n%s\n41\n%s\n71\n%s\n72\n%s%s\n43\n%s\n50\n%s\n'%\
## (self._common(),_point(self.point),self.charHeight,self.width,
## self.attachment,self.direction,text,
## self.height,
## self.rotation)
## if self.style:result+='7\n%s\n'%self.style
## if self.xdirection:result+='%s\n'%_point(self.xdirection,1)
## if self.charWidth:result+='42\n%s\n'%self.charWidth
## if self.spacingStyle:result+='73\n%s\n'%self.spacingStyle
## if self.spacingFactor:result+='44\n%s\n'%self.spacingFactor
## return result
#---tables ---------------------------------------------------
#-----------------------------------------------
class Block(_Collection):
"""Use list methods to add entities, eg append."""
def __init__(self,name,layer='0',flag=0,base=(0,0,0),entities=[]):
self.entities=copy.copy(entities)
_Collection.__init__(self,entities)
self.layer=layer
self.name=name
self.flag=0
self.base=base
def __str__(self): # TODO:
e=''.join([str(x)for x in self.entities])
return ' 0\nBLOCK\n 8\n%s\n 2\n%s\n 70\n%s\n%s\n 3\n%s\n%s 0\nENDBLK\n'%\
(self.layer,self.name.upper(),self.flag,_point(self.base),self.name.upper(),e)
#-----------------------------------------------
class Layer(_Call):
"""Layer"""
def __init__(self,name='pydxf',color=7,lineType='continuous',flag=64):
self.name=name
self.color=color
self.lineType=lineType
self.flag=flag
def __str__(self):
return ' 0\nLAYER\n 2\n%s\n 70\n%s\n 62\n%s\n 6\n%s\n'%\
(self.name.upper(),self.flag,self.color,self.lineType)
#-----------------------------------------------
class LineType(_Call):
"""Custom linetype"""
def __init__(self,name='CONTINUOUS',description='Solid line',elements=[0.0],flag=0):
self.name=name
self.description=description
self.elements=copy.copy(elements)
self.flag=flag
def __str__(self):
result = ' 0\nLTYPE\n 2\n%s\n 70\n%s\n 3\n%s\n 72\n65\n'%\
(self.name.upper(),self.flag,self.description)
if self.elements:
elements = ' 73\n%s\n' %(len(self.elements)-1)
elements += ' 40\n%s\n' %(self.elements[0])
for e in self.elements[1:]:
elements += ' 49\n%s\n' %e
result += elements
return result
#-----------------------------------------------
class Style(_Call):
"""Text style"""
def __init__(self,name='standard',flag=0,height=0,widthFactor=1.0,obliqueAngle=0.0,
mirror=0,lastHeight=1,font='arial.ttf',bigFont=''):
self.name=name
self.flag=flag
self.height=height
self.widthFactor=widthFactor
self.obliqueAngle=obliqueAngle
self.mirror=mirror
self.lastHeight=lastHeight
self.font=font
self.bigFont=bigFont
def __str__(self):
return ' 0\nSTYLE\n 2\n%s\n 70\n%s\n 40\n%s\n 41\n%s\n 50\n%s\n 71\n%s\n 42\n%s\n 3\n%s\n 4\n%s\n'%\
(self.name.upper(),self.flag,self.flag,self.widthFactor,
self.obliqueAngle,self.mirror,self.lastHeight,
self.font.upper(),self.bigFont.upper())
#-----------------------------------------------
class VPort(_Call):
def __init__(self,name,flag=0,
leftBottom=(0.0,0.0),
rightTop=(1.0,1.0),
center=(0.5,0.5),
snap_base=(0.0,0.0),
snap_spacing=(0.1,0.1),
grid_spacing=(0.1,0.1),
direction=(0.0,0.0,1.0),
target=(0.0,0.0,0.0),
height=1.0,
ratio=1.0,
lens=50,
frontClipping=0,
backClipping=0,
snap_rotation=0,
twist=0,
mode=0,
circle_zoom=100,
fast_zoom=1,
ucsicon=1,
snap_on=0,
grid_on=0,
snap_style=0,
snap_isopair=0
):
self.name=name
self.flag=flag
self.leftBottom=leftBottom
self.rightTop=rightTop
self.center=center
self.snap_base=snap_base
self.snap_spacing=snap_spacing
self.grid_spacing=grid_spacing
self.direction=direction
self.target=target
self.height=float(height)
self.ratio=float(ratio)
self.lens=float(lens)
self.frontClipping=float(frontClipping)
self.backClipping=float(backClipping)
self.snap_rotation=float(snap_rotation)
self.twist=float(twist)
self.mode=mode
self.circle_zoom=circle_zoom
self.fast_zoom=fast_zoom
self.ucsicon=ucsicon
self.snap_on=snap_on
self.grid_on=grid_on
self.snap_style=snap_style
self.snap_isopair=snap_isopair
def __str__(self):
output = [' 0', 'VPORT',
' 2', self.name,
' 70', self.flag,
_point(self.leftBottom),
_point(self.rightTop,1),
_point(self.center,2), # View center point (in DCS)
_point(self.snap_base,3),
_point(self.snap_spacing,4),
_point(self.grid_spacing,5),
_point(self.direction,6), #view direction from target (in WCS)
_point(self.target,7),
' 40', self.height,
' 41', self.ratio,
' 42', self.lens,
' 43', self.frontClipping,
' 44', self.backClipping,
' 50', self.snap_rotation,
' 51', self.twist,
' 71', self.mode,
' 72', self.circle_zoom,
' 73', self.fast_zoom,
' 74', self.ucsicon,
' 75', self.snap_on,
' 76', self.grid_on,
' 77', self.snap_style,
' 78', self.snap_isopair
]
output_str = ''
for s in output:
output_str += '%s\n' %s
return output_str
#-----------------------------------------------
class View(_Call):
def __init__(self,name,flag=0,
width=1,
height=1,
center=(0.5,0.5),
direction=(0,0,1),
target=(0,0,0),
lens=50,
frontClipping=0,
backClipping=0,
twist=0,mode=0
):
self.name=name
self.flag=flag
self.width=float(width)
self.height=float(height)
self.center=center
self.direction=direction
self.target=target
self.lens=float(lens)
self.frontClipping=float(frontClipping)
self.backClipping=float(backClipping)
self.twist=float(twist)
self.mode=mode
def __str__(self):
output = [' 0', 'VIEW',
' 2', self.name,
' 70', self.flag,
' 40', self.height,
_point(self.center),
' 41', self.width,
_point(self.direction,1),
_point(self.target,2),
' 42', self.lens,
' 43', self.frontClipping,
' 44', self.backClipping,
' 50', self.twist,
' 71', self.mode
]
output_str = ''
for s in output:
output_str += '%s\n' %s
return output_str
#-----------------------------------------------
def ViewByWindow(name,leftBottom=(0,0),rightTop=(1,1),**options):
width=abs(rightTop[0]-leftBottom[0])
height=abs(rightTop[1]-leftBottom[1])
center=((rightTop[0]+leftBottom[0])*0.5,(rightTop[1]+leftBottom[1])*0.5)
return View(name=name,width=width,height=height,center=center,**options)
#---drawing
#-----------------------------------------------
class Drawing(_Collection):
"""Dxf drawing. Use append or any other list methods to add objects."""
def __init__(self,insbase=(0.0,0.0,0.0),extmin=(0.0,0.0,0.0),extmax=(0.0,0.0,0.0),
layers=[Layer()],linetypes=[LineType()],styles=[Style()],blocks=[],
views=[],vports=[],entities=None,fileName='test.dxf'):
# TODO: replace list with None,arial
if not entities:
entities=[]
_Collection.__init__(self,entities)
self.insbase=insbase
self.extmin=extmin
self.extmax=extmax
self.layers=copy.copy(layers)
self.linetypes=copy.copy(linetypes)
self.styles=copy.copy(styles)
self.views=copy.copy(views)
self.vports=copy.copy(vports)
self.blocks=copy.copy(blocks)
self.fileName=fileName
#private
#self.acadver='9\n$ACADVER\n1\nAC1006\n'
self.acadver=' 9\n$ACADVER\n 1\nAC1009\n'
"""DXF AutoCAD-Release format codes
AC1021 2008, 2007
AC1018 2006, 2005, 2004
AC1015 2002, 2000i, 2000
AC1014 R14,14.01
AC1012 R13
AC1009 R12,11
AC1006 R10
AC1004 R9
AC1002 R2.6
AC1.50 R2.05
"""
def _name(self,x):
"""Helper function for self._point"""
return ' 9\n$%s\n' %x.upper()
def _point(self,name,x):
"""Point setting from drawing like extmin,extmax,..."""
return '%s%s' %(self._name(name),_point(x))
def _section(self,name,x):
"""Sections like tables,blocks,entities,..."""
if x: xstr=''.join(x)
else: xstr=''
return ' 0\nSECTION\n 2\n%s\n%s 0\nENDSEC\n'%(name.upper(),xstr)
def _table(self,name,x):
"""Tables like ltype,layer,style,..."""
if x: xstr=''.join(x)
else: xstr=''
return ' 0\nTABLE\n 2\n%s\n 70\n%s\n%s 0\nENDTAB\n'%(name.upper(),len(x),xstr)
def __str__(self):
"""Returns drawing as dxf string."""
header=[self.acadver]+[self._point(attr,getattr(self,attr))+'\n' for attr in _HEADER_POINTS]
header=self._section('header',header)
tables=[self._table('vport',[str(x) for x in self.vports]),
self._table('ltype',[str(x) for x in self.linetypes]),
self._table('layer',[str(x) for x in self.layers]),
self._table('style',[str(x) for x in self.styles]),
self._table('view',[str(x) for x in self.views]),
]
tables=self._section('tables',tables)
blocks=self._section('blocks',[str(x) for x in self.blocks])
entities=self._section('entities',[str(x) for x in self.entities])
all=''.join([header,tables,blocks,entities,' 0\nEOF\n'])
return all
def saveas(self,fileName):
self.fileName=fileName
self.save()
def save(self):
test=open(self.fileName,'w')
test.write(str(self))
test.close()
#---extras
#-----------------------------------------------
class Rectangle(_Entity):
"""Rectangle, creates lines."""
def __init__(self,point=(0,0,0),width=1,height=1,solid=None,line=1,**common):
_Entity.__init__(self,**common)
self.point=point
self.width=width
self.height=height
self.solid=solid
self.line=line
def __str__(self):
result=''
points=[self.point,(self.point[0]+self.width,self.point[1],self.point[2]),
(self.point[0]+self.width,self.point[1]+self.height,self.point[2]),
(self.point[0],self.point[1]+self.height,self.point[2]),self.point]
if self.solid:
result+= Solid(points=points[:-1],parent=self.solid)
if self.line:
for i in range(4):
result+= Line(points=[points[i],points[i+1]],parent=self)
return result[1:]
#-----------------------------------------------
class LineList(_Entity):
"""Like polyline, but built of individual lines."""
def __init__(self,points=[],org_point=[0,0,0],closed=0,**common):
_Entity.__init__(self,**common)
self.closed=closed
self.points=copy.copy(points)
def __str__(self):
if self.closed:points=self.points+[self.points[0]]
else: points=self.points
result=''
for i in range(len(points)-1):
result+= Line(points=[points[i],points[i+1]],parent=self)
return result[1:]
#-----------------------------------------------------
def test():
#Blocks
b=Block('test')
b.append(Solid(points=[(0,0,0),(1,0,0),(1,1,0),(0,1,0)],color=1))
b.append(Arc(center=(1,0,0),color=2))
#Drawing
d=Drawing()
#tables
d.blocks.append(b) #table blocks
d.styles.append(Style()) #table styles
d.views.append(View('Normal')) #table view
d.views.append(ViewByWindow('Window',leftBottom=(1,0),rightTop=(2,1))) #idem
#entities
d.append(Circle(center=(1,1,0),color=3))
d.append(Face(points=[(0,0,0),(1,0,0),(1,1,0),(0,1,0)],color=4))
d.append(Insert('test',point=(3,3,3),cols=5,colspacing=2))
d.append(Line(points=[(0,0,0),(1,1,1)]))
d.append(Mtext('Click on Ads\nmultiple lines with mtext',point=(1,1,1),color=5,rotation=90))
d.append(Text('Please donate!',point=(3,0,1)))
#d.append(Rectangle(point=(2,2,2),width=4,height=3,color=6,solid=Solid(color=2)))
d.append(Solid(points=[(4,4,0),(5,4,0),(7,8,0),(9,9,0)],color=3))
#d.append(PolyLine(points=[(1,1,1),(2,1,1),(2,2,1),(1,2,1)],flag=1,color=1))
#d.saveas('c:\\test.dxf')
d.saveas('test.dxf')
#-----------------------------------------------------
if __name__=='__main__':
if not copy:
Draw.PupMenu('Error%t|This script requires a full python install')
else: test()

View File

@@ -1,381 +0,0 @@
"""This module provides a function for reading dxf files and parsing them into a useful tree of objects and data.
The convert function is called by the readDXF fuction to convert dxf strings into the correct data based
on their type code. readDXF expects a (full path) file name as input.
"""
# --------------------------------------------------------------------------
# DXF Reader v0.9 by Ed Blake (AKA Kitsu)
# 2008.05.08 modif.def convert() by Remigiusz Fiedler (AKA migius)
# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
#from dxfImportObjects import *
class Object:
"""Empty container class for dxf objects"""
def __init__(self, _type='', block=False):
"""_type expects a string value."""
self.type = _type
self.name = ''
self.data = []
def __str__(self):
if self.name:
return self.name
else:
return self.type
def __repr__(self):
return str(self.data)
def get_type(self, kind=''):
"""Despite the name, this method actually returns all objects of type 'kind' from self.data."""
if type:
objects = []
for item in self.data:
if type(item) != list and item.type == kind:
# we want this type of object
objects.append(item)
elif type(item) == list and item[0] == kind:
# we want this type of data
objects.append(item[1])
return objects
class InitializationError(Exception): pass
class StateMachine:
"""(finite) State Machine from the great David Mertz's great Charming Python article."""
def __init__(self):
self.handlers = []
self.startState = None
self.endStates = []
def add_state(self, handler, end_state=0):
"""All states and handlers are functions which return
a state and a cargo."""
self.handlers.append(handler)
if end_state:
self.endStates.append(handler)
def set_start(self, handler):
"""Sets the starting handler function."""
self.startState = handler
def run(self, cargo=None):
if not self.startState:
raise InitializationError,\
"must call .set_start() before .run()"
if not self.endStates:
raise InitializationError, \
"at least one state must be an end_state"
handler = self.startState
while 1:
(newState, cargo) = handler(cargo)
#print cargo
if newState in self.endStates:
return newState(cargo)
#break
elif newState not in self.handlers:
raise RuntimeError, "Invalid target %s" % newState
else:
handler = newState
def get_name(data):
"""Get the name of an object from its object data.
Returns a pair of (data_item, name) where data_item is the list entry where the name was found
(the data_item can be used to remove the entry from the object data). Be sure to check
name not None before using the returned values!
"""
value = None
for item in data:
if item[0] == 2:
value = item[1]
break
return item, value
def get_layer(data):
"""Expects object data as input.
Returns (entry, layer_name) where entry is the data item that provided the layer name.
"""
value = None
for item in data:
if item[0] == 8:
value = item[1]
break
return item, value
def convert(code, value):
"""Convert a string to the correct Python type based on its dxf code.
code types:
ints = 60-79, 170-179, 270-289, 370-389, 400-409, 1060-1070
longs = 90-99, 420-429, 440-459, 1071
floats = 10-39, 40-59, 110-139, 140-149, 210-239, 460-469, 1010-1059
hex = 105, 310-379, 390-399
strings = 0-9, 100, 102, 300-309, 410-419, 430-439, 470-479, 999, 1000-1009
"""
if 59 < code < 80 or 169 < code < 180 or 269 < code < 290 or 369 < code < 390 or 399 < code < 410 or 1059 < code < 1071:
value = int(float(value))
elif 89 < code < 100 or 419 < code < 430 or 439 < code < 460 or code == 1071:
value = long(float(value))
elif 9 < code < 60 or 109 < code < 150 or 209 < code < 240 or 459 < code < 470 or 1009 < code < 1060:
value = float(value)
elif code == 105 or 309 < code < 380 or 389 < code < 400:
value = int(value, 16) # should be left as string?
else: # it's already a string so do nothing
pass
return value
def findObject(infile, kind=''):
"""Finds the next occurance of an object."""
obj = False
while 1:
line = infile.readline()
if not line: # readline returns '' at eof
return False
if not obj: # We're still looking for our object code
if line.lower().strip() == '0':
obj = True # found it
else: # we are in an object definition
if kind: # if we're looking for a particular kind
if line.lower().strip() == kind:
obj = Object(line.lower().strip())
break
else: # otherwise take anything non-numeric
if line.lower().strip() not in string.digits:
obj = Object(line.lower().strip())
break
obj = False # whether we found one or not it's time to start over
return obj
def handleObject(infile):
"""Add data to an object until end of object is found."""
line = infile.readline()
if line.lower().strip() == 'section':
return 'section' # this would be a problem
elif line.lower().strip() == 'endsec':
return 'endsec' # this means we are done with a section
else: # add data to the object until we find a new object
obj = Object(line.lower().strip())
obj.name = obj.type
done = False
data = []
while not done:
line = infile.readline()
if not data:
if line.lower().strip() == '0':
#we've found an object, time to return
return obj
else:
# first part is always an int
data.append(int(line.lower().strip()))
else:
data.append(convert(data[0], line.strip()))
obj.data.append(data)
data = []
def handleTable(table, infile):
"""Special handler for dealing with nested table objects."""
item, name = get_name(table.data)
if name: # We should always find a name
table.data.remove(item)
table.name = name.lower()
# This next bit is from handleObject
# handleObject should be generalized to work with any section like object
while 1:
obj = handleObject(infile)
if obj.type == 'table':
print "Warning: previous table not closed!"
return table
elif obj.type == 'endtab':
return table # this means we are done with the table
else: # add objects to the table until one of the above is found
table.data.append(obj)
def handleBlock(block, infile):
"""Special handler for dealing with nested table objects."""
item, name = get_name(block.data)
if name: # We should always find a name
block.data.remove(item)
block.name = name
# This next bit is from handleObject
# handleObject should be generalized to work with any section like object
while 1:
obj = handleObject(infile)
if obj.type == 'block':
print "Warning: previous block not closed!"
return block
elif obj.type == 'endblk':
return block # this means we are done with the table
else: # add objects to the table until one of the above is found
block.data.append(obj)
"""These are the states/functions used in the State Machine.
states:
start - find first section
start_section - add data, find first object
object - add obj-data, watch for next obj (called directly by start_section)
end_section - look for next section or eof
end - return results
"""
def start(cargo):
"""Expects the infile as cargo, initializes the cargo."""
#print "Entering start state!"
infile = cargo
drawing = Object('drawing')
section = findObject(infile, 'section')
if section:
return start_section, (infile, drawing, section)
else:
return error, (infile, "Failed to find any sections!")
def start_section(cargo):
"""Expects [infile, drawing, section] as cargo, builds a nested section object."""
#print "Entering start_section state!"
infile = cargo[0]
drawing = cargo[1]
section = cargo[2]
# read each line, if it is an object declaration go to object mode
# otherwise create a [index, data] pair and add it to the sections data.
done = False
data = []
while not done:
line = infile.readline()
if not data: # if we haven't found a dxf code yet
if line.lower().strip() == '0':
# we've found an object
while 1: # no way out unless we find an end section or a new section
obj = handleObject(infile)
if obj == 'section': # shouldn't happen
print "Warning: failed to close previous section!"
return end_section, (infile, drawing)
elif obj == 'endsec': # This section is over, look for the next
drawing.data.append(section)
return end_section, (infile, drawing)
elif obj.type == 'table': # tables are collections of data
obj = handleTable(obj, infile) # we need to find all there contents
section.data.append(obj) # before moving on
elif obj.type == 'block': # the same is true of blocks
obj = handleBlock(obj, infile) # we need to find all there contents
section.data.append(obj) # before moving on
else: # found another sub-object
section.data.append(obj)
else:
data.append(int(line.lower().strip()))
else: # we have our code, now we just need to convert the data and add it to our list.
data.append(convert(data[0], line.strip()))
section.data.append(data)
data = []
def end_section(cargo):
"""Expects (infile, drawing) as cargo, searches for next section."""
#print "Entering end_section state!"
infile = cargo[0]
drawing = cargo[1]
section = findObject(infile, 'section')
if section:
return start_section, (infile, drawing, section)
else:
return end, (infile, drawing)
def end(cargo):
"""Expects (infile, drawing) as cargo, called when eof has been reached."""
#print "Entering end state!"
infile = cargo[0]
drawing = cargo[1]
#infile.close()
return drawing
def error(cargo):
"""Expects a (infile, string) as cargo, called when there is an error during processing."""
#print "Entering error state!"
infile = cargo[0]
err = cargo[1]
infile.close()
print "There has been an error:"
print err
return False
def readDXF(filename, objectify):
"""Given a file name try to read it as a dxf file.
Output is an object with the following structure
drawing
header
header data
classes
class data
tables
table data
blocks
block data
entities
entity data
objects
object data
where foo data is a list of sub-objects. True object data
is of the form [code, data].
"""
infile = open(filename)
sm = StateMachine()
sm.add_state(error, True)
sm.add_state(end, True)
sm.add_state(start_section)
sm.add_state(end_section)
sm.add_state(start)
sm.set_start(start)
try:
drawing = sm.run(infile)
if drawing:
drawing.name = filename
for obj in drawing.data:
item, name = get_name(obj.data)
if name:
obj.data.remove(item)
obj.name = name.lower()
setattr(drawing, name.lower(), obj)
# Call the objectify function to cast
# raw objects into the right types of object
obj.data = objectify(obj.data)
#print obj.name
finally:
infile.close()
return drawing
if __name__ == "__main__":
filename = r".\examples\block-test.dxf"
drawing = readDXF(filename)
for item in drawing.entities.data:
print item

View File

@@ -1,229 +0,0 @@
# This is not to be used directly, vertexGradientPick can be used externaly
import Blender
import BPyMesh
import BPyWindow
mouseViewRay= BPyWindow.mouseViewRay
from Blender import Mathutils, Window, Scene, Draw, sys
from Blender.Mathutils import Vector, Intersect, LineIntersect, AngleBetweenVecs
LMB= Window.MButs['L']
def mouseup():
# Loop until click
mouse_buttons = Window.GetMouseButtons()
while not mouse_buttons & LMB:
sys.sleep(10)
mouse_buttons = Window.GetMouseButtons()
while mouse_buttons & LMB:
sys.sleep(10)
mouse_buttons = Window.GetMouseButtons()
def mousedown_wait():
# If the menu has just been pressed dont use its mousedown,
mouse_buttons = Window.GetMouseButtons()
while mouse_buttons & LMB:
mouse_buttons = Window.GetMouseButtons()
eps= 0.0001
def vertexGradientPick(ob, MODE):
#MODE 0 == VWEIGHT, 1 == VCOL
me= ob.getData(mesh=1)
if not me.faceUV: me.faceUV= True
Window.DrawProgressBar (0.0, '')
mousedown_wait()
if MODE==0:
act_group= me.activeGroup
if act_group == None:
mousedown_wait()
Draw.PupMenu('Error, mesh has no active group.')
return
# Loop until click
Window.DrawProgressBar (0.25, 'Click to set gradient start')
mouseup()
obmat= ob.matrixWorld
screen_x, screen_y = Window.GetMouseCoords()
mouseInView, OriginA, DirectionA = mouseViewRay(screen_x, screen_y, obmat)
if not mouseInView or not OriginA:
return
# get the mouse weight
if MODE==0:
pickValA= BPyMesh.pickMeshGroupWeight(me, act_group, OriginA, DirectionA)
if MODE==1:
pickValA= BPyMesh.pickMeshGroupVCol(me, OriginA, DirectionA)
Window.DrawProgressBar (0.75, 'Click to set gradient end')
mouseup()
TOALPHA= Window.GetKeyQualifiers() & Window.Qual.SHIFT
screen_x, screen_y = Window.GetMouseCoords()
mouseInView, OriginB, DirectionB = mouseViewRay(screen_x, screen_y, obmat)
if not mouseInView or not OriginB:
return
if not TOALPHA: # Only get a second opaque value if we are not blending to alpha
if MODE==0: pickValB= BPyMesh.pickMeshGroupWeight(me, act_group, OriginB, DirectionB)
else:
pickValB= BPyMesh.pickMeshGroupVCol(me, OriginB, DirectionB)
else:
if MODE==0: pickValB= 0.0
else: pickValB= [0.0, 0.0, 0.0] # Dummy value
# Neither points touched a face
if pickValA == pickValB == None:
return
# clicking on 1 non face is fine. just set the weight to 0.0
if pickValA==None:
pickValA= 0.0
# swap A/B
OriginA, OriginB= OriginB, OriginA
DirectionA, DirectionB= DirectionB, DirectionA
pickValA, pickValB= pickValA, pickValB
TOALPHA= True
if pickValB==None:
pickValB= 0.0
TOALPHA= True
# set up 2 lines so we can measure their distances and calc the gradient
# make a line 90d to the grad in screenspace.
if (OriginA-OriginB).length <= eps: # Persp view. same origin different direction
cross_grad= DirectionA.cross(DirectionB)
ORTHO= False
else: # Ortho - Same direction, different origin
cross_grad= DirectionA.cross(OriginA-OriginB)
ORTHO= True
cross_grad.normalize()
cross_grad= cross_grad * 100
lineA= (OriginA, OriginA+(DirectionA*100))
lineB= (OriginB, OriginB+(DirectionB*100))
if not ORTHO:
line_angle= AngleBetweenVecs(lineA[1], lineB[1])/2
line_mid= (lineA[1]+lineB[1])*0.5
VSEL= [False] * (len(me.verts))
# Get the selected faces and apply the selection to the verts.
for f in me.faces:
if f.sel:
for v in f.v:
VSEL[v.index]= True
groupNames, vWeightDict= BPyMesh.meshWeight2Dict(me)
def grad_weight_from_co(v):
'''
Takes a vert and retuens its gradient radio between A and B
'''
if not VSEL[v.index]: # Not bart of a selected face?
return None, None
v_co= v.co
# make a line 90d to the 2 lines the user clicked.
vert_line= (v_co - cross_grad, v_co + cross_grad)
xA= LineIntersect(vert_line[0], vert_line[1], lineA[0], lineA[1])
xB= LineIntersect(vert_line[0], vert_line[1], lineB[0], lineB[1])
if not xA or not xB: # Should never happen but support it anyhow
return None, None
wA= (xA[0]-xA[1]).length
wB= (xB[0]-xB[1]).length
wTot= wA+wB
if not wTot: # lines are on the same point.
return None, None
'''
Get the length of the line between both intersections on the
2x view lines.
if the dist between lineA+VertLine and lineB+VertLine is
greater then the lenth between lineA and lineB intersection points, it means
that the verts are not inbetween the 2 lines.
'''
lineAB_length= (xA[1]-xB[1]).length
# normalzie
wA= wA/wTot
wB= wB/wTot
if ORTHO: # Con only use line length method with parelelle lines
if wTot > lineAB_length+eps:
# vert is outside the range on 1 side. see what side of the grad
if wA>wB: wA, wB= 1.0, 0.0
else: wA, wB= 0.0, 1.0
else:
# PERSP, lineA[0] is the same origin as lineB[0]
# Either xA[0] or xB[0] can be used instead of a possible x_mid between the 2
# as long as the point is inbetween lineA and lineB it dosent matter.
a= AngleBetweenVecs(lineA[0]-xA[0], line_mid)
if a>line_angle:
# vert is outside the range on 1 side. see what side of the grad
if wA>wB: wA, wB= 1.0, 0.0
else: wA, wB= 0.0, 1.0
return wA, wB
grad_weights= [grad_weight_from_co(v) for v in me.verts]
if MODE==0:
for v in me.verts:
i= v.index
if VSEL[i]:
wA, wB = grad_weights[i]
if wA != None: # and wB
if TOALPHA:
# Do alpha by using the exiting weight for
try: pickValB= vWeightDict[i][act_group]
except: pickValB= 0.0 # The weights not there? assume zero
# Mix2 2 opaque weights
vWeightDict[i][act_group]= pickValB*wA + pickValA*wB
else: # MODE==1 VCol
for f in me.faces:
if f.sel:
f_v= f.v
for i in xrange(len(f_v)):
v= f_v[i]
wA, wB = grad_weights[v.index]
c= f.col[i]
if TOALPHA:
pickValB= c.r, c.g, c.b
c.r = int(pickValB[0]*wA + pickValA[0]*wB)
c.g = int(pickValB[1]*wA + pickValA[1]*wB)
c.b = int(pickValB[2]*wA + pickValA[2]*wB)
# Copy weights back to the mesh.
BPyMesh.dict2MeshWeight(me, groupNames, vWeightDict)
Window.DrawProgressBar (1.0, '')

View File

@@ -1,355 +0,0 @@
# $Id$
#
# +---------------------------------------------------------+
# | Copyright (c) 2001 Anthony D'Agostino |
# | http://www.redrival.com/scorpius |
# | scorpius@netzero.com |
# | September 28, 2002 |
# +---------------------------------------------------------+
# | Common Functions & Global Variables For All IO Modules |
# +---------------------------------------------------------+
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
import Blender
import sys
show_progress = 1 # Set to 0 for faster performance
average_vcols = 1 # Off for per-face, On for per-vertex
overwrite_mesh_name = 0 # Set to 0 to increment object-name version
blender_version = Blender.Get('version')
blender_version_str = `blender_version`[0] + '.' + `blender_version`[1:]
try:
import operator
except:
msg = "Error: you need a full Python install to run this script."
meshtools.print_boxed(msg)
Blender.Draw.PupMenu("ERROR%t|"+msg)
# =================================
# === Append Faces To Face List ===
# =================================
def append_faces(mesh, faces, facesuv, uvcoords):
for i in xrange(len(faces)):
if not i%100 and show_progress: Blender.Window.DrawProgressBar(float(i)/len(faces), "Generating Faces")
numfaceverts=len(faces[i])
if numfaceverts == 2: #This is not a face is an edge
if mesh.edges == None: #first run
mesh.addEdgeData()
#rev_face = revert(cur_face)
i1 = faces[i][0]
i2 = faces[i][1]
ee = mesh.addEdge(mesh.verts[i1],mesh.verts[i2])
ee.flag |= Blender.NMesh.EdgeFlags.EDGEDRAW
ee.flag |= Blender.NMesh.EdgeFlags.EDGERENDER
elif numfaceverts in [3,4]: # This face is a triangle or quad
face = Blender.NMesh.Face()
for j in xrange(numfaceverts):
index = faces[i][j]
face.v.append(mesh.verts[index])
if len(uvcoords) > 1:
uvidx = facesuv[i][j]
face.uv.append(uvcoords[uvidx])
face.mode = 0
face.col = [Blender.NMesh.Col()]*4
mesh.faces.append(face)
else: # Triangulate n-sided convex polygon.
a, b, c = 0, 1, 2 # Indices of first triangle.
for j in xrange(numfaceverts-2): # Number of triangles in polygon.
face = Blender.NMesh.Face()
face.v.append(mesh.verts[faces[i][a]])
face.v.append(mesh.verts[faces[i][b]])
face.v.append(mesh.verts[faces[i][c]])
b = c; c += 1
mesh.faces.append(face)
#face.smooth = 1
# ===================================
# === Append Verts to Vertex List ===
# ===================================
def append_verts(mesh, verts, normals):
#print "Number of normals:", len(normals)
#print "Number of verts :", len(verts)
for i in xrange(len(verts)):
if not i%100 and show_progress: Blender.Window.DrawProgressBar(float(i)/len(verts), "Generating Verts")
x, y, z = verts[i]
mesh.verts.append(Blender.NMesh.Vert(x, y, z))
if normals:
mesh.verts[i].no[0] = normals[i][0]
mesh.verts[i].no[1] = normals[i][1]
mesh.verts[i].no[2] = normals[i][2]
# ===========================
# === Create Blender Mesh ===
# ===========================
def create_mesh(verts, faces, objname, facesuv=[], uvcoords=[], normals=[]):
if normals: normal_flag = 0
else: normal_flag = 1
mesh = Blender.NMesh.GetRaw()
append_verts(mesh, verts, normals)
append_faces(mesh, faces, facesuv, uvcoords)
if not overwrite_mesh_name:
objname = versioned_name(objname)
ob= Blender.NMesh.PutRaw(mesh, objname, normal_flag) # Name the Mesh
ob.name= objname # Name the Object
Blender.Redraw()
# ==============================
# === Increment Name Version ===
# ==============================
def versioned_name(objname):
existing_names = []
for object in Blender.Object.Get():
existing_names.append(object.name)
existing_names.append(object.getData(name_only=1))
if objname in existing_names: # don't over-write other names
try:
name, ext = objname.split('.')
except ValueError:
name, ext = objname, ''
try:
num = int(ext)
root = name
except ValueError:
root = objname
for i in xrange(1, 1000):
objname = "%s.%03d" % (root, i)
if objname not in existing_names:
break
return objname
# ===========================
# === Print Text In A Box ===
# ===========================
def print_boxed(text):
lines = text.splitlines()
maxlinelen = max(map(len, lines))
if sys.platform[:3] == "win":
print chr(218)+chr(196) + chr(196)*maxlinelen + chr(196)+chr(191)
for line in lines:
print chr(179) + ' ' + line.ljust(maxlinelen) + ' ' + chr(179)
print chr(192)+chr(196) + chr(196)*maxlinelen + chr(196)+chr(217)
else:
print '+-' + '-'*maxlinelen + '-+'
for line in lines: print '| ' + line.ljust(maxlinelen) + ' |'
print '+-' + '-'*maxlinelen + '-+'
print '\a\r', # beep when done
# ===============================================
# === Get euler angles from a rotation matrix ===
# ===============================================
def mat2euler(mat):
angle_y = -math.asin(mat[0][2])
c = math.cos(angle_y)
if math.fabs(c) > 0.005:
angle_x = math.atan2(mat[1][2]/c, mat[2][2]/c)
angle_z = math.atan2(mat[0][1]/c, mat[0][0]/c)
else:
angle_x = 0.0
angle_z = -math.atan2(mat[1][0], mat[1][1])
return (angle_x, angle_y, angle_z)
# ==========================
# === Transpose A Matrix ===
# ==========================
def transpose(A):
S = len(A)
T = len(A[0])
B = [[None]*S for i in xrange(T)]
for i in xrange(T):
for j in xrange(S):
B[i][j] = A[j][i]
return B
# =======================
# === Apply Transform ===
# =======================
def apply_transform(vertex, matrix):
x, y, z = vertex
xloc, yloc, zloc = matrix[3][0], matrix[3][1], matrix[3][2]
xcomponent = x*matrix[0][0] + y*matrix[1][0] + z*matrix[2][0] + xloc
ycomponent = x*matrix[0][1] + y*matrix[1][1] + z*matrix[2][1] + yloc
zcomponent = x*matrix[0][2] + y*matrix[1][2] + z*matrix[2][2] + zloc
vertex = [xcomponent, ycomponent, zcomponent]
return vertex
# =========================
# === Has Vertex Colors ===
# =========================
def has_vertex_colors(mesh):
# My replacement/workaround for hasVertexColours()
# The docs say:
# "Warning: If a mesh has both vertex colours and textured faces,
# this function will return False. This is due to the way Blender
# deals internally with the vertex colours array (if there are
# textured faces, it is copied to the textured face structure and
# the original array is freed/deleted)."
try:
return mesh.faces[0].col[0]
except:
return 0
# ===========================
# === Generate Edge Table ===
# ===========================
def generate_edgetable(mesh):
edge_table = {}
numfaces = len(mesh.faces)
for i in xrange(numfaces):
if not i%100 and show_progress:
Blender.Window.DrawProgressBar(float(i)/numfaces, "Generating Edge Table")
if len(mesh.faces[i].v) == 4: # Process Quadrilaterals
generate_entry_from_quad(mesh, i, edge_table)
elif len(mesh.faces[i].v) == 3: # Process Triangles
generate_entry_from_tri(mesh, i, edge_table)
else: # Skip This Face
print "Face #", i, "was skipped."
# === Sort Edge_Table Keys & Add Edge Indices ===
i = 0
keys = edge_table.keys()
keys.sort()
for key in keys:
edge_table[key][6] = i
i += 1
# === Replace Tuples With Indices ===
for key in keys:
for i in [2,3,4,5]:
if edge_table.has_key(edge_table[key][i]):
edge_table[key][i] = edge_table[edge_table[key][i]][6]
else:
keyrev = (edge_table[key][i][1], edge_table[key][i][0])
edge_table[key][i] = edge_table[keyrev][6]
return edge_table
# ================================
# === Generate Entry From Quad ===
# ================================
def generate_entry_from_quad(mesh, i, edge_table):
vertex4, vertex3, vertex2, vertex1 = mesh.faces[i].v
if has_vertex_colors(mesh):
vcolor4, vcolor3, vcolor2, vcolor1 = mesh.faces[i].col
Acol = (vcolor1.r/255.0, vcolor1.g/255.0, vcolor1.b/255.0)
Bcol = (vcolor2.r/255.0, vcolor2.g/255.0, vcolor2.b/255.0)
Ccol = (vcolor3.r/255.0, vcolor3.g/255.0, vcolor3.b/255.0)
Dcol = (vcolor4.r/255.0, vcolor4.g/255.0, vcolor4.b/255.0)
# === verts are upper case, edges are lower case ===
A, B, C, D = vertex1.index, vertex2.index, vertex3.index, vertex4.index
a, b, c, d = (A, B), (B, C), (C, D), (D, A)
if edge_table.has_key((B, A)):
edge_table[(B, A)][1] = i
edge_table[(B, A)][4] = d
edge_table[(B, A)][5] = b
if has_vertex_colors(mesh): edge_table[(B, A)][8] = Bcol
else:
if has_vertex_colors(mesh):
edge_table[(A, B)] = [i, None, d, b, None, None, None, Bcol, None]
else:
edge_table[(A, B)] = [i, None, d, b, None, None, None]
if edge_table.has_key((C, B)):
edge_table[(C, B)][1] = i
edge_table[(C, B)][4] = a
edge_table[(C, B)][5] = c
if has_vertex_colors(mesh): edge_table[(C, B)][8] = Ccol
else:
if has_vertex_colors(mesh):
edge_table[(B, C)] = [i, None, a, c, None, None, None, Ccol, None]
else:
edge_table[(B, C)] = [i, None, a, c, None, None, None]
if edge_table.has_key((D, C)):
edge_table[(D, C)][1] = i
edge_table[(D, C)][4] = b
edge_table[(D, C)][5] = d
if has_vertex_colors(mesh): edge_table[(D, C)][8] = Dcol
else:
if has_vertex_colors(mesh):
edge_table[(C, D)] = [i, None, b, d, None, None, None, Dcol, None]
else:
edge_table[(C, D)] = [i, None, b, d, None, None, None]
if edge_table.has_key((A, D)):
edge_table[(A, D)][1] = i
edge_table[(A, D)][4] = c
edge_table[(A, D)][5] = a
if has_vertex_colors(mesh): edge_table[(A, D)][8] = Acol
else:
if has_vertex_colors(mesh):
edge_table[(D, A)] = [i, None, c, a, None, None, None, Acol, None]
else:
edge_table[(D, A)] = [i, None, c, a, None, None, None]
# ====================================
# === Generate Entry From Triangle ===
# ====================================
def generate_entry_from_tri(mesh, i, edge_table):
vertex3, vertex2, vertex1 = mesh.faces[i].v
if has_vertex_colors(mesh):
vcolor3, vcolor2, vcolor1, _vcolor4_ = mesh.faces[i].col
Acol = (vcolor1.r/255.0, vcolor1.g/255.0, vcolor1.b/255.0)
Bcol = (vcolor2.r/255.0, vcolor2.g/255.0, vcolor2.b/255.0)
Ccol = (vcolor3.r/255.0, vcolor3.g/255.0, vcolor3.b/255.0)
# === verts are upper case, edges are lower case ===
A, B, C = vertex1.index, vertex2.index, vertex3.index
a, b, c = (A, B), (B, C), (C, A)
if edge_table.has_key((B, A)):
edge_table[(B, A)][1] = i
edge_table[(B, A)][4] = c
edge_table[(B, A)][5] = b
if has_vertex_colors(mesh): edge_table[(B, A)][8] = Bcol
else:
if has_vertex_colors(mesh):
edge_table[(A, B)] = [i, None, c, b, None, None, None, Bcol, None]
else:
edge_table[(A, B)] = [i, None, c, b, None, None, None]
if edge_table.has_key((C, B)):
edge_table[(C, B)][1] = i
edge_table[(C, B)][4] = a
edge_table[(C, B)][5] = c
if has_vertex_colors(mesh): edge_table[(C, B)][8] = Ccol
else:
if has_vertex_colors(mesh):
edge_table[(B, C)] = [i, None, a, c, None, None, None, Ccol, None]
else:
edge_table[(B, C)] = [i, None, a, c, None, None, None]
if edge_table.has_key((A, C)):
edge_table[(A, C)][1] = i
edge_table[(A, C)][4] = b
edge_table[(A, C)][5] = a
if has_vertex_colors(mesh): edge_table[(A, C)][8] = Acol
else:
if has_vertex_colors(mesh):
edge_table[(C, A)] = [i, None, b, a, None, None, None, Acol, None]
else:
edge_table[(C, A)] = [i, None, b, a, None, None, None]

View File

@@ -1,506 +0,0 @@
# -*- coding: latin-1 -*-
"""
paths_ai2obj.py
# ---------------------------------------------------------------
Copyright (c) jm soler juillet/novembre 2004-april 2007,
# ---------------------------------------------------------------
released under GNU Licence
for the Blender 2.45 Python Scripts Bundle.
Ce programme est libre, vous pouvez le redistribuer et/ou
le modifier selon les termes de la Licence Publique G<>n<EFBFBD>rale GNU
publi<EFBFBD>e par la Free Software Foundation (version 2 ou bien toute
autre version ult<6C>rieure choisie par vous).
Ce programme est distribu<62> car potentiellement utile, mais SANS
AUCUNE GARANTIE, ni explicite ni implicite, y compris les garanties
de commercialisation ou d'adaptation dans un but sp<73>cifique.
Reportez-vous <20> la Licence Publique G<>n<EFBFBD>rale GNU pour plus de d<>tails.
Vous devez avoir re<72>u une copie de la Licence Publique G<>n<EFBFBD>rale GNU
en m<>me temps que ce programme ; si ce n'est pas le cas, <20>crivez <20> la
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
MA 02111-1307, <20>tats-Unis.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
# ---------------------------------------------------------------
#----------------------------------------------
#
# Page officielle :
# http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_import_ai_en.htm
# Communiquer les problemes et erreurs sur:
# http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender
#----------------------------------------------
#Changelog
#----------------------------------------------
# 0.1.1 : 2004/08/03, bug in boundingbox reading when Value are negative
# 0.1.2 : 2005/06/12, gmove tranformation properties
# 0.1.3 : 2005/06/25, added a __name__ test to use the script alone
# 0.1.4 : 2005/06/25, closepath improvements
# 0.1.5 : 2005/06/25, ...
# 0.1.6 : 2005/06/26, warning for compacted file
compatibility increased up to AI 10.0 plain text
# 0.1.7 : 2005/06/25, two more closepath improvements
#
# 0.1.8 : 2006/07/03, two more closepath improvements
# 0.1.9 : 2007/05/06, modif on the method that gets the last object on
the list data
# 2008/03/12, Added character encoding line so french text
# does not break python interpreters.
"""
SHARP_IMPORT=0
SCALE=1
NOTHING_TODO=1
AI_VERSION=''
GSTACK = []
GSCALE = []
GTRANSLATE = []
import sys
#oldpath=sys.path
import Blender
BLversion=Blender.Get('version')
try:
import nt
os=nt
os.sep='\\'
except:
import posix
os=posix
os.sep='/'
def isdir(path):
try:
st = os.stat(path)
return 1
except:
return 0
def split(pathname):
if pathname.find(os.sep)!=-1:
k0=pathname.split(os.sep)
else:
if os.sep=='/':
k0=pathname.split('\\')
else:
k0=pathname.split('/')
directory=pathname.replace(k0[len(k0)-1],'')
Name=k0[len(k0)-1]
return directory, Name
def join(l0,l1):
return l0+os.sep+l1
os.isdir=isdir
os.split=split
os.join=join
def filtreFICHIER(nom):
f=open(nom,'rU')
t=f.readlines()
f.close()
if len(t)>1 and t[0].find('EPSF')==-1:
return t
else:
name = "OK?%t| Not a valid file or an empty file ... " # if no %xN int is set, indices start from 1
result = Blender.Draw.PupMenu(name)
return 'false'
#===============================
# Data
#===============================
#===============================
# Blender Curve Data
#===============================
objBEZIER=0
objSURFACE=5
typBEZIER3D=1 #3D
typBEZIER2D=9 #2D
class Bez:
def __init__(self):
self.co=[]
self.ha=[0,0]
self.tag=''
class ITEM:
def __init__(self):
self.type = typBEZIER3D,
self.pntsUV = [0,0]
self.resolUV = [32,0]
self.orderUV = [0,0]
self.flagUV = [0,0]
self.Origine = [0.0,0.0]
self.beziers_knot = []
class COURBE:
def __init__(self):
self.magic_number='3DG3'
self.type = objBEZIER
self.number_of_items = 0
self.ext1_ext2 = [0,0]
self.matrix = """0.0 0.0 1.0 0.0
0.0 1.0 0.0 0.0
0.0 0.0 1.0 0.0
0.0 0.0 0.0 1.0 """
self.ITEM = {}
courbes=COURBE()
PATTERN={}
BOUNDINGBOX={'rec':[],'coef':1.0}
npat=0
#=====================================================================
#======== name of the curve in teh courbes dictionnary ===============
#=====================================================================
n0=0
#=====================================================================
#====================== current Point ================================
#=====================================================================
CP=[0.0,0.0] #currentPoint
# modifs 12/06/2005
#=====================================================================
#====================== current transform ============================
#=====================================================================
class transform:
def __init__(self,matrix=[1,0,01],x=0.0,y=0.0):
self.matrix=matrix[:]
self.xy=[x,y]
def G_move(l,a):
global GSCALE, GTRANSLATE, GSTACK
#print GSCALE, GTRANSLATE, GSTACK
return str((float(l)+GTRANSLATE[a]+GSTACK[-1].xy[a])*GSCALE[a])
# modifs 12/06/2005
#=====================================================================
#===== to compare last position to the original move to displacement =
#===== needed for cyclic efinition =================================
#=====================================================================
def test_egalitedespositions(f1,f2):
if f1[0]==f2[0] and f1[1]==f2[1]:
return Blender.TRUE
else:
return Blender.FALSE
def Open_GEOfile(dir,nom):
if BLversion>=233:
in_editmode = Blender.Window.EditMode()
if in_editmode: Blender.Window.EditMode(0)
Blender.Load(dir+nom+'OOO.obj', 1)
BO=Blender.Scene.GetCurrent().objects.active
BO.RotY=0.0
BO.RotX=1.57
BO.makeDisplayList()
Blender.Window.RedrawAll()
else:
print "Not yet implemented"
def create_GEOtext(courbes):
global SCALE, B, BOUNDINGBOX
r=BOUNDINGBOX['rec']
if SCALE==1:
SCALE=1.0
elif SCALE==2:
SCALE=r[2]-r[0]
elif SCALE==3:
SCALE=r[3]-r[1]
t=[]
t.append(courbes.magic_number+'\n')
t.append(str(courbes.type)+'\n')
t.append(str(courbes.number_of_items)+'\n')
t.append(str(courbes.ext1_ext2[0])+' '+str(courbes.ext1_ext2[1])+'\n')
t.append(courbes.matrix+'\n')
for k in courbes.ITEM.keys():
if len(courbes.ITEM[k].beziers_knot)>1 :
t.append("%s\n"%courbes.ITEM[k].type)
t.append("%s %s \n"%(courbes.ITEM[k].pntsUV[0],courbes.ITEM[k].pntsUV[1]))
t.append("%s %s \n"%(courbes.ITEM[k].resolUV[0],courbes.ITEM[k].resolUV[1]))
t.append("%s %s \n"%(courbes.ITEM[k].orderUV[0],courbes.ITEM[k].orderUV[1]))
t.append("%s %s \n"%(courbes.ITEM[k].flagUV[0],courbes.ITEM[k].flagUV[1]))
flag =courbes.ITEM[k].flagUV[0]
for k2 in range(len(courbes.ITEM[k].beziers_knot)):
#print k2
k1 =courbes.ITEM[k].beziers_knot[k2]
t.append("%4f 0.0 %4f \n"%(float(k1.co[2])/SCALE,float(k1.co[3])/SCALE))
t.append("%4f 0.0 %4f \n"%(float(k1.co[4])/SCALE,float(k1.co[5])/SCALE))
t.append("%4f 0.0 %4f \n"%(float(k1.co[0])/SCALE,float(k1.co[1])/SCALE))
t.append(str(k1.ha[0])+' '+str(k1.ha[1])+'\n')
return t
def save_GEOfile(dir,nom,t):
f=open(dir+nom+'OOO.obj','w')
f.writelines(t)
f.close()
#warning = "REMINDER : %t | Do not forget to rename your blender file NOW ! %x1"
#result = Blender.Draw.PupMenu(warning)
#=====================================================================
#===== AI format : DEBUT =========================
#=====================================================================
def mouvement_vers(l,n0,CP):
if n0 in courbes.ITEM.keys():
n0+=1
CP=[l[-3].replace('d',''),l[-2]]
courbes.ITEM[n0]=ITEM()
courbes.ITEM[n0].Origine=[l[-3].replace('d',''),l[-2]]
B=Bez()
B.co=[CP[0],CP[1],CP[0],CP[1],CP[0],CP[1]]
B.ha=[0,0]
B.tag=l[-1]
courbes.ITEM[n0].beziers_knot.append(B)
return courbes,n0,CP
def courbe_vers_c(l,l2, n0,CP): #c,C
B=Bez()
B.co=[l[4],l[5],l[2],l[3],l[4],l[5]]
B.tag=l[-1]
B.ha=[0,0]
BP=courbes.ITEM[n0].beziers_knot[-1]
BP.co[0]=l[0]
BP.co[1]=l[1]
courbes.ITEM[n0].beziers_knot.append(B)
CP=[B.co[4],B.co[5]]
return courbes,n0,CP
def courbe_vers_v(l,n0,CP): #v-V
B=Bez()
B.tag=l[-1]
B.co=[l[2],l[3],l[0],l[1],l[2],l[3]]
B.ha=[0,0]
courbes.ITEM[n0].beziers_knot.append(B)
CP=[B.co[4],B.co[5]]
return courbes,n0,CP
def courbe_vers_y(l,n0,CP): #y
B=Bez()
B.tag=l[-1]
B.co=[l[2],l[3],l[2],l[3],l[2],l[3]]
B.ha=[0,0]
BP=courbes.ITEM[n0].beziers_knot[-1]
BP.co[0]=l[0]
BP.co[1]=l[1]
courbes.ITEM[n0].beziers_knot.append(B)
CP=[B.co[4],B.co[5]]
return courbes,n0,CP
def ligne_tracee_l(l,n0,CP):
B=Bez()
B.tag=l[-1]
B.co=[l[0],l[1],l[0],l[1],l[0],l[1]]
B.ha=[0,0]
BP=courbes.ITEM[n0].beziers_knot[-1]
courbes.ITEM[n0].beziers_knot.append(B)
CP=[B.co[4],B.co[5]]
return courbes,n0,CP
def ligne_fermee(l,n0,CP):
courbes.ITEM[n0].flagUV[0]=1
if len(courbes.ITEM[n0].beziers_knot)>1:
BP=courbes.ITEM[n0].beziers_knot[-1]
BP0=courbes.ITEM[n0].beziers_knot[0]
if BP.tag not in ['l','L']:
BP.co[0]=BP0.co[0] #4-5 point prec
BP.co[1]=BP0.co[1]
del courbes.ITEM[n0].beziers_knot[0]
return courbes,n0,CP
def passe(l,n0,CP):
return courbes,n0,CP
Actions= { "C" : courbe_vers_c,
"c" : courbe_vers_c,
"V" : courbe_vers_v,
"v" : courbe_vers_v,
"Y" : courbe_vers_y,
"y" : courbe_vers_y,
"m" : mouvement_vers,
"l" : ligne_tracee_l,
"L" : ligne_tracee_l,
"F" : passe,
"f" : ligne_fermee,
"B" : passe,
"b" : ligne_fermee,
"S" : passe,
"s" : ligne_fermee,
"N" : ligne_fermee,
"n" : passe,
}
TAGcourbe=Actions.keys()
def pik_pattern(t,l):
global npat, PATTERN, BOUNDINGBOX, AI_VERSION
while t[l].find('%%EndSetup')!=0:
if t[l].find('%%Creator: Adobe Illustrator(R)')!=-1:
print t[l]
AI_VERSION=t[l].split()[-1]
print AI_VERSION
if t[l].find('%%BoundingBox:')!=-1:
t[l]=t[l][t[l].find(':')+1:]
l0=t[l].split()
BOUNDINGBOX['rec']=[float(l0[-4]),float(l0[-3]),float(l0[-2]),float(l0[-1])]
r=BOUNDINGBOX['rec']
BOUNDINGBOX['coef']=(r[3]-r[1])/(r[2]-r[0])
#print l,
if t[l].find('BeginPattern')!=-1:
nomPattern=t[l][t[l].find('(')+1:t[l].find(')')]
PATTERN[nomPattern]={}
if t[l].find('BeginPatternLayer')!=-1:
npat+=1
PATTERN[nomPattern][npat]=[]
while t[l].find('EndPatternLayer')==-1:
#print t[l]
PATTERN[nomPattern][npat].append(l)
l+=1
if l+1<len(t):
l=l+1
else:
return 1,l
return 1,l
def scan_FILE(nom):
global CP, courbes, SCALE, NOTHING_TODO
dir,name=split(nom)
name=name.split('.')
n0=0
result=0
t=filtreFICHIER(nom)
if nom.upper().find('.AI')!=-1 and t!='false':
if not SHARP_IMPORT:
warning = "Select Size : %t| As is %x1 | Scale on Height %x2| Scale on Width %x3"
SCALE = Blender.Draw.PupMenu(warning)
npat=0
l=0
do=0
while l <len(t)-1 :
if not do:
do,l=pik_pattern(t,l)
#print 'len(t)',len(t)
t[l].replace('\n','')
if t[l].find('%%EOF')==0:
break
if t[l][0]!='%':
l0=t[l].split()
#print l0
if l0[0][0] in ['F','f','N','n','B','b']:
l3=l0[0][0]
courbes,n0,CP=Actions[l3](l3,n0,CP)
l0[0]=l0[1:]
if l0[-1] in TAGcourbe:
NOTHING_TODO=0
if l0[-1] in ['C','c']:
l2=t[l+1].split()
courbes,n0,CP=Actions[l0[-1]](l0,l2,n0,CP)
else:
courbes,n0,CP=Actions[l0[-1]](l0,n0,CP)
l=l+1; #print l
t=[]
courbes.number_of_items=len(courbes.ITEM.keys())
for k in courbes.ITEM.keys():
courbes.ITEM[k].pntsUV[0] =len(courbes.ITEM[k].beziers_knot)
if courbes.number_of_items>0:
if len(PATTERN.keys() )>0:
#print len(PATTERN.keys() )
warning = "Pattern list (for info not used): %t| "
p0=1
for P in PATTERN.keys():
warning+="%s %%x%s|"%(P,p0)
p0+=1
Padd = Blender.Draw.PupMenu(warning)
t=create_GEOtext(courbes)
save_GEOfile(dir,name[0],t)
# 0.1.8 ---------------------------------
# [O.select(0) for O in Blender.Scene.getCurrent().getChildren()]
# 0.1.8 ---------------------------------
Open_GEOfile(dir,name[0])
# 0.1.8 ---------------------------------
Blender.Object.Get()[-1].setName(name[0])
# 0.1.8 ---------------------------------
else:
pass
#=====================================================================
#====================== AI format mouvements =========================
#=====================================================================
#=========================================================
# une sorte de contournement qui permet d'utiliser la fonction
# et de documenter les variables Window.FileSelector
#=========================================================
def fonctionSELECT(nom):
global NOTHING_TODO,AI_VERSION
scan_FILE(nom)
if NOTHING_TODO==1:
warning = "AI %s compatible file "%AI_VERSION+" but nothing to do ? %t| Perhaps a compacted file ... "
NOTHING = Blender.Draw.PupMenu(warning)
if __name__=="__main__":
Blender.Window.FileSelector (fonctionSELECT, 'SELECT AI FILE')
#sys.path=oldpath

View File

@@ -1,452 +0,0 @@
#----------------------------------------------
# (c) jm soler juillet 2004-juin 2005 , released under Blender Artistic Licence
# for the Blender 2.34-2.37 Python Scripts Bundle.
#
# last update: 06/05/2007
#----------------------------------------------
# Page officielle :
# http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_import_eps.htm
# Communiquer les problemes et erreurs sur:
# http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender
#----------------------------------------------
SHARP_IMPORT = 0
SCALE = 1.0
scale = 1
import sys
#oldpath=sys.path
import Blender
from Blender import Draw
BLversion=Blender.Get('version')
try:
import nt
os=nt
os.sep='\\'
except:
import posix
os=posix
os.sep='/'
def isdir(path):
try:
st = os.stat(path)
return 1
except:
return 0
def split(pathname):
if pathname.find(os.sep)!=-1:
k0=pathname.split(os.sep)
else:
if os.sep=='/':
k0=pathname.split('\\')
else:
k0=pathname.split('/')
directory=pathname.replace(k0[len(k0)-1],'')
Name=k0[len(k0)-1]
return directory, Name
def join(l0,l1):
return l0+os.sep+l1
os.isdir=isdir
os.split=split
os.join=join
def filtreFICHIER(nom):
f=open(nom,'rU')
t=f.readlines()
f.close()
if len(t)==1 and t[0].find('\r'):
t=t[0].split('\r')
if len(t)>1 and t[0].find('PS-Adobe-3.0')==-1 and t[0].find('EPSF')==-1:
return t
else:
name = "OK?%t| Not a valid file or an empty file or... %x1| not a pure PS-Adobe-2.0 file %x2 "
result = Blender.Draw.PupMenu(name)
return 'false'
#===============================
# Data
#===============================
#===============================
# Blender Curve Data
#===============================
objBEZIER=0
objSURFACE=5
typBEZIER3D=1 #3D
typBEZIER2D=9 #2D
class Bez:
def __init__(self):
self.co=[]
self.ha=[0,0]
class ITEM:
def __init__(self):
self.type = typBEZIER3D,
self.pntsUV = [0,0]
self.resolUV = [32,0]
self.orderUV = [0,0]
self.flagUV = [0,0]
self.Origine = [0.0,0.0]
self.beziers_knot = []
class COURBE:
def __init__(self):
self.magic_number='3DG3'
self.type = objBEZIER
self.number_of_items = 0
self.ext1_ext2 = [0,0]
self.matrix = """0.0 0.0 1.0 0.0
0.0 1.0 0.0 0.0
0.0 0.0 1.0 0.0
0.0 0.0 0.0 1.0 """ #- right-handed object matrix. Used to determine position, rotation and size
self.ITEM = {}
courbes=COURBE()
PATTERN={}
BOUNDINGBOX={'rec':[],'coef':1.0}
npat=0
#=====================================================================
#======== name of the curve in teh courbes dictionnary ===============
#=====================================================================
n0=0
#=====================================================================
#====================== current Point ================================
#=====================================================================
CP=[0.0,0.0] #currentPoint
# modifs 12/06/2005
#=====================================================================
#====================== current transform ============================
#=====================================================================
class transform:
def __init__(self,matrix=[1,0,01],x=0.0,y=0.0):
self.matrix=matrix[:]
self.xy=[x,y]
GSTACK = []
stack=transform()
GSTACK.append(stack)
GSCALE = [1.0,1.0]
GTRANSLATE = [0.0,0.0]
def G_move(l,a):
global GSCALE, GTRANSLATE, GSTACK
#print GSCALE, GTRANSLATE, GSTACK
return str((float(l)+GTRANSLATE[a]+GSTACK[-1].xy[a])*GSCALE[a])
# modifs 12/06/2005
#=====================================================================
#===== to compare last position to the original move to displacement =
#===== needed for cyclic efinition =================================
#=====================================================================
def test_egalitedespositions(f1,f2):
if f1[0]==f2[0] and f1[1]==f2[1]:
return Blender.TRUE
else:
return Blender.FALSE
def Open_GEOfile(dir,nom):
global SCALE,BOUNDINGBOX, scale
if BLversion>=233:
Blender.Load(dir+nom+'OOO.obj', 1)
BO=Blender.Scene.GetCurrent().objects.active
BO.RotY=3.1416
BO.RotZ=3.1416
BO.RotX=3.1416/2.0
if scale==1:
BO.LocY+=BOUNDINGBOX['rec'][3]
else:
BO.LocY+=BOUNDINGBOX['rec'][3]/SCALE
BO.makeDisplayList()
Blender.Window.RedrawAll()
else:
print "Not yet implemented"
def create_GEOtext(courbes):
global SCALE, B, BOUNDINGBOX,scale
r=BOUNDINGBOX['rec']
if scale==1:
SCALE=1.0
elif scale==2:
SCALE=r[2]-r[0]
elif scale==3:
SCALE=r[3]-r[1]
t=[]
t.append(courbes.magic_number+'\n')
t.append(str(courbes.type)+'\n')
t.append(str(courbes.number_of_items)+'\n')
t.append(str(courbes.ext1_ext2[0])+' '+str(courbes.ext1_ext2[1])+'\n')
t.append(courbes.matrix+'\n')
for k in courbes.ITEM.keys():
t.append("%s\n"%courbes.ITEM[k].type)
t.append("%s %s \n"%(courbes.ITEM[k].pntsUV[0],courbes.ITEM[k].pntsUV[1]))
t.append("%s %s \n"%(courbes.ITEM[k].resolUV[0],courbes.ITEM[k].resolUV[1]))
t.append("%s %s \n"%(courbes.ITEM[k].orderUV[0],courbes.ITEM[k].orderUV[1]))
t.append("%s %s \n"%(courbes.ITEM[k].flagUV[0],courbes.ITEM[k].flagUV[1]))
flag =courbes.ITEM[k].flagUV[0]
for k2 in range(flag,len(courbes.ITEM[k].beziers_knot)):
k1 =courbes.ITEM[k].beziers_knot[k2]
t.append("%4f 0.0 %4f \n"%(float(k1.co[0])/SCALE,float(k1.co[1])/SCALE))
t.append("%4f 0.0 %4f \n"%(float(k1.co[2])/SCALE,float(k1.co[3])/SCALE))
t.append("%4f 0.0 %4f \n"%(float(k1.co[4])/SCALE,float(k1.co[5])/SCALE))
t.append(str(k1.ha[0])+' '+str(k1.ha[1])+'\n')
return t
def save_GEOfile(dir,nom,t):
f=open(dir+nom+'OOO.obj','w')
f.writelines(t)
f.close()
#name = "REMINDER : %t | Do not forget to rename your blender file NOW ! %x1"
#result = Blender.Draw.PupMenu(name)
#=====================================================================
#===== EPS format : DEBUT =========================
#=====================================================================
def mouvement_vers(l,n0,CP):
if n0 in courbes.ITEM.keys():
#if test_egalitedespositions(courbes.ITEM[n0].Origine,CP):
# courbes.ITEM[n0].flagUV[0]=1
n0+=1
CP=[l[-3].replace('d',''),l[-2]]
else:
CP=[l[-3].replace('d',''),l[-2]]
#i=
courbes.ITEM[n0]=ITEM()
courbes.ITEM[n0].Origine=[l[-3].replace('d',''),l[-2]]
B=Bez()
B.co=[G_move(CP[0],0),
G_move(CP[1],1),
G_move(CP[0],0),
G_move(CP[1],1),
G_move(CP[0],0),
G_move(CP[1],1)]
B.ha=[0,0]
courbes.ITEM[n0].beziers_knot.append(B)
return courbes,n0,CP
def rmouvement_vers(l,n0,CP):
if n0 in courbes.ITEM.keys():
#if test_egalitedespositions(courbes.ITEM[n0].Origine,CP):
# courbes.ITEM[n0].flagUV[0]=1
n0+=1
CP=["%4f"%(float(l[-3])+float(CP[0])),"%4f"%(float(l[-2])+float(CP[1]))]
else:
CP=["%4f"%(float(l[-3])+float(CP[0])),"%4f"%(float(l[-2])+float(CP[1]))]
#i=
courbes.ITEM[n0]=ITEM()
courbes.ITEM[n0].Origine=[l[-3].replace('d',''),l[-2]]
B=Bez()
B.co=[CP[0],CP[1],CP[0],CP[1],CP[0],CP[1]]
B.ha=[0,0]
courbes.ITEM[n0].beziers_knot.append(B)
return courbes,n0,CP
def courbe_vers_c(l, l2, n0,CP): #c,C
"""
B=Bez()
B.co=[l[0],l[1],l[2],l[3],l[4],l[5]]
B.ha=[0,0]
courbes.ITEM[n0].beziers_knot.append(B)
"""
B=Bez()
B.co=[G_move(l[2],0),
G_move(l[3],1),
G_move(l[4],0),
G_move(l[5],1),
G_move(l[0],0),
G_move(l[1],1)]
if len(courbes.ITEM[n0].beziers_knot)==1:
CP=[l[0],l[1]]
courbes.ITEM[n0].Origine=[l[0],l[1]]
if l[-1]=='C':
B.ha=[2,2]
else:
B.ha=[0,0]
courbes.ITEM[n0].beziers_knot.append(B)
if len(l2)>1 and l2[-1] in Actions.keys():
B.co[-2]=G_move(l2[0],0)
B.co[-1]=G_move(l2[1],1)
else:
B.co[-2]=G_move(CP[0],0)
B.co[-1]=G_move(CP[1],1)
return courbes,n0,CP
def ligne_tracee_l(l,n0,CP):
B=Bez()
B.co=[G_move(l[0],0),
G_move(l[1],1),
G_move(l[0],0),
G_move(l[1],1),
G_move(l[0],0),
G_move(l[1],1)]
B.ha=[0,0]
courbes.ITEM[n0].beziers_knot.append(B)
CP=[l[0],l[1]]
return courbes,n0,CP
def rligne_tracee_l(l,n0,CP):
B=Bez()
B.co=["%4f"%(float(l[0])+float(CP[0])),
"%4f"%(float(l[1])+float(CP[1])),
"%4f"%(float(l[0])+float(CP[0])),
"%4f"%(float(l[1])+float(CP[1])),
"%4f"%(float(l[0])+float(CP[0])),
"%4f"%(float(l[1])+float(CP[1]))]
B.ha=[0,0]
courbes.ITEM[n0].beziers_knot.append(B)
CP=[l[0],l[1]]
return courbes,n0,CP
Actions= { "curveto" : courbe_vers_c,
"curveto" : courbe_vers_c,
"moveto" : mouvement_vers,
"rmoveto" : mouvement_vers,
"lineto" : ligne_tracee_l,
"rlineto" : rligne_tracee_l
}
TAGcourbe=Actions.keys()
"""
def pik_pattern(t,l):
global npat, PATTERN, BOUNDINGBOX
while t[l].find('%%EndSetup')!=0:
if t[l].find('%%BoundingBox:')!=-1:
l0=t[l].split()
BOUNDINGBOX['rec']=[float(l0[-4]),float(l0[-3]),float(l0[-2]),float(l0[-1])]
r=BOUNDINGBOX['rec']
BOUNDINGBOX['coef']=(r[3]-r[1])/(r[2]-r[0])
print l,
if t[l].find('BeginPatternLayer')!=-1:
npat+=1
PATTERN[npat]=[]
while t[l].find('EndPatternLayer')==-1:
print t[l]
PATTERN[npat].append(l)
l+=1
if l+1<len(t):
l=l+1
else:
return 1,l
return 1,l
"""
def scan_FILE(nom):
global CP, courbes, SCALE, scale, GSTACK, GSCALE, GTRANSLATE
dir,name=split(nom)
name=name.split('.')
n0=0
result=0
t=filtreFICHIER(nom)
#print t
if t!='false' and (nom.upper().find('.EPS')!=-1 or nom.upper().find('.PS')!=-1 ):
if not SHARP_IMPORT:
warning = "Select Size : %t| As is %x1 | Scale on Height %x2| Scale on Width %x3"
scale = Blender.Draw.PupMenu(warning)
npat=0
l=0
do=0
while l <len(t)-1 :
if t[l].find('%%BoundingBox:')!=-1:
l0=t[l].split()
BOUNDINGBOX['rec']=[float(l0[-4]),float(l0[-3]),float(l0[-2]),float(l0[-1])]
r=BOUNDINGBOX['rec']
BOUNDINGBOX['coef']=(r[3]-r[1])/(r[2]-r[0])
"""
if not do:
do,l=pik_pattern(t,l)
"""
#print 'len(t)',len(t)
t[l].replace('\n','')
if t[l][0]!='%':
l0=t[l].split()
if l0!=[] and l0[-1] in TAGcourbe:
if l0[-1] in ['curveto']:
l2=t[l+1].split()
courbes,n0,CP=Actions[l0[-1]](l0,l2,n0,CP)
else:
courbes,n0,CP=Actions[l0[-1]](l0,n0,CP)
# modifs 10/06/2005
elif l0!=[] and l0[-1] in ['scale']:
GSCALE=[float(l0[-3]),float(l0[-2])]
elif l0!=[] and l0[-1] in ['translate']:
GTRANSLATE=[float(l0[-3]),float(l0[-2])]
elif l0!=[] and l0[-1] in ['concat'] and l0[0] in ['gsave']:
l0[1]=l0[1].replace('[','')
l0[-2]=l0[-2].replace(']','')
stack=transform([float(l0[1]),float(l0[2]),float(l0[3]),float(l0[4])],float(l0[5]),float(l0[6]))
GSTACK.append(stack)
#print GSTACK
elif l0!=[] and l0[-1] in ['concat'] and l0[0] in ['grestore']:
del GSTACK[-1]
# modifs 12/06/2005 : end
l=l+1#; print l
t=[]
if t!='false':
courbes.number_of_items=len(courbes.ITEM.keys())
for k in courbes.ITEM.keys():
courbes.ITEM[k].pntsUV[0] =len(courbes.ITEM[k].beziers_knot)
if test_egalitedespositions(courbes.ITEM[k].Origine,
[courbes.ITEM[k].beziers_knot[-1].co[-2],
courbes.ITEM[k].beziers_knot[-1].co[-1]]):
courbes.ITEM[k].flagUV[0]=1
courbes.ITEM[k].pntsUV[0] -=1
if courbes.number_of_items>0:
if len(PATTERN.keys() )>0:
#print len(PATTERN.keys() )
pass
t=create_GEOtext(courbes)
save_GEOfile(dir,name[0],t)
Open_GEOfile(dir,name[0])
# 03 juillet 2006 ----------------------
Blender.Object.Get()[-1].setName(name[0])
# 03 juillet 2006 ----------------------
else:
pass
#=====================================================================
#====================== EPS format mouvements =========================
#=====================================================================
#=========================================================
# une sorte de contournement qui permet d'utiliser la fonction
# et de documenter les variables Window.FileSelector
#=========================================================
def fonctionSELECT(nom):
scan_FILE(nom)
if __name__=="__main__":
Blender.Window.FileSelector (fonctionSELECT, 'SELECT EPS FILE')

View File

@@ -1,363 +0,0 @@
# -*- coding: latin-1 -*-
"""
#----------------------------------------------
# (c) jm soler juillet 2004,
#----------------------------------------------
released under GNU Licence
for the Blender 2.45 Python Scripts Bundle.
Ce programme est libre, vous pouvez le redistribuer et/ou
le modifier selon les termes de la Licence Publique G<>n<EFBFBD>rale GNU
publi<EFBFBD>e par la Free Software Foundation (version 2 ou bien toute
autre version ult<6C>rieure choisie par vous).
Ce programme est distribu<62> car potentiellement utile, mais SANS
AUCUNE GARANTIE, ni explicite ni implicite, y compris les garanties
de commercialisation ou d'adaptation dans un but sp<73>cifique.
Reportez-vous <20> la Licence Publique G<>n<EFBFBD>rale GNU pour plus de d<>tails.
Vous devez avoir re<72>u une copie de la Licence Publique G<>n<EFBFBD>rale GNU
en m<>me temps que ce programme ; si ce n'est pas le cas, <20>crivez <20> la
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
MA 02111-1307, <20>tats-Unis.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
# ---------------------------------------------------------------
# last update : 07/05/2007
#----------------------------------------------
# Page officielle :
# http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_import_gimp.htm
# Communiquer les problemes et erreurs sur:
# http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender
# Modification History:
# 2008-03-12 Added character encoding line so french text does not break
# python interpreters.
#---------------------------------------------
SHARP_IMPORT=0
SCALE=1
import sys
#oldpath=sys.path
import Blender
BLversion=Blender.Get('version')
try:
import nt
os=nt
os.sep='\\'
except:
import posix
os=posix
os.sep='/'
def isdir(path):
try:
st = os.stat(path)
return 1
except:
return 0
def split(pathname):
if pathname.find(os.sep)!=-1:
k0=pathname.split(os.sep)
else:
if os.sep=='/':
k0=pathname.split('\\')
else:
k0=pathname.split('/')
directory=pathname.replace(k0[len(k0)-1],'')
Name=k0[len(k0)-1]
return directory, Name
def join(l0,l1):
return l0+os.sep+l1
os.isdir=isdir
os.split=split
os.join=join
def filtreFICHIER(nom):
f=open(nom,'r')
t=f.readlines()
f.close()
if len(t)==1 and t[0].find('\r'):
t=t[0].split('\r')
if len(t)>1 and t[1].find('#POINTS:')==0:
return t
else:
warning = "OK?%t| Not a valid file or an empty file ... " # if no %xN int is set, indices start from 1
result = Blender.Draw.PupMenu(warning)
return "false"
#===============================
# Data
#===============================
#===============================
# Blender Curve Data
#===============================
objBEZIER=0
objSURFACE=5
typBEZIER3D=1 #3D
typBEZIER2D=9 #2D
class Bez:
def __init__(self):
self.co=[]
self.ha=[0,0]
def echo(self):
#print 'co = ', self.co
#print 'ha = ', self.ha
pass
class ITEM:
def __init__(self):
self.type = typBEZIER3D,
self.pntsUV = [0,0]
self.resolUV = [32,0]
self.orderUV = [0,0]
self.flagUV = [0,0]
self.Origine = [0.0,0.0]
self.beziers_knot = []
class COURBE:
def __init__(self):
self.magic_number='3DG3'
self.type = objBEZIER
self.number_of_items = 0
self.ext1_ext2 = [0,0]
self.matrix = """0.0 0.0 1.0 0.0
0.0 1.0 0.0 0.0
0.0 0.0 1.0 0.0
0.0 0.0 0.0 1.0 """ #- right-handed object matrix. Used to determine position, rotation and size
self.ITEM = {}
courbes=COURBE()
PATTERN={}
BOUNDINGBOX={'rec':[],'coef':1.0}
npat=0
#=====================================================================
#======== name of the curve in the courbes dictionnary ===============
#=====================================================================
n0=0
#=====================================================================
#====================== current Point ================================
#=====================================================================
CP=[0.0,0.0] #currentPoint
def MINMAX(b):
global BOUNDINGBOX
r=BOUNDINGBOX['rec']
for m in range(0,len(b)-2,2):
#print m, m+1 , len(b)-1
#print b[m], r, r[0]
if float(b[m])<r[0]:
r[0]=float(b[m])
if float(b[m])>r[2]: r[2]=float(b[m])
if float(b[m+1])<r[1]: r[1]=float(b[m+1])
if float(b[m+1])>r[3]: r[3]=float(b[m+1])
#=====================================================================
#===== to compare last position to the original move to displacement =
#===== needed for cyclic efinition =================================
#=====================================================================
def test_egalitedespositions(f1,f2):
if f1[0]==f2[0] and f1[1]==f2[1]:
return Blender.TRUE
else:
return Blender.FALSE
def Open_GEOfile(dir,nom):
if BLversion>=233:
Blender.Load(dir+nom+'OOO.obj', 1)
BO=Blender.Scene.GetCurrent().objects.active
BO.LocZ=1.0
BO.makeDisplayList()
Blender.Window.RedrawAll()
else:
print "Not yet implemented"
def create_GEOtext(courbes):
global SCALE, B, BOUNDINGBOX
r=BOUNDINGBOX['rec']
if SCALE==1:
SCALE=1.0
elif SCALE==2:
SCALE=r[2]-r[0]
elif SCALE==3:
SCALE=r[3]-r[1]
t=[]
t.append(courbes.magic_number+'\n')
t.append(str(courbes.type)+'\n')
t.append(str(courbes.number_of_items)+'\n')
t.append(str(courbes.ext1_ext2[0])+' '+str(courbes.ext1_ext2[1])+'\n')
t.append(courbes.matrix+'\n')
for k in courbes.ITEM.keys():
t.append("%s\n"%courbes.ITEM[k].type)
t.append("%s %s \n"%(courbes.ITEM[k].pntsUV[0],courbes.ITEM[k].pntsUV[1]))
t.append("%s %s \n"%(courbes.ITEM[k].resolUV[0],courbes.ITEM[k].resolUV[1]))
t.append("%s %s \n"%(courbes.ITEM[k].orderUV[0],courbes.ITEM[k].orderUV[1]))
t.append("%s %s \n"%(courbes.ITEM[k].flagUV[0],courbes.ITEM[k].flagUV[1]))
flag =0#courbes.ITEM[k].flagUV[0]
for k2 in range(flag,len(courbes.ITEM[k].beziers_knot)):
k1 =courbes.ITEM[k].beziers_knot[k2]
t.append("%4f 0.0 %4f \n"%(float(k1.co[0])/SCALE,float(k1.co[1])/SCALE))
t.append("%4f 0.0 %4f \n"%(float(k1.co[4])/SCALE,float(k1.co[5])/SCALE))
t.append("%4f 0.0 %4f \n"%(float(k1.co[2])/SCALE,float(k1.co[3])/SCALE))
t.append(str(k1.ha[0])+' '+str(k1.ha[1])+'\n')
return t
def save_GEOfile(dir,nom,t):
f=open(dir+nom+'OOO.obj','w')
f.writelines(t)
f.close()
#warning = "REMINDER : %t | Do not forget to rename your blender file NOW ! %x1"
#result = Blender.Draw.PupMenu(warning)
#=====================================================================
#===== GIMP format : DEBUT =========================
#=====================================================================
CLOSED=0
def mouvement_vers(l,l1,l2,n0):
global BOUNDINGBOX, CP
if l[1] == '3' :
n0+=1
courbes.ITEM[n0]=ITEM()
courbes.ITEM[n0].Origine=[l[-3],l[-1],]
courbes.ITEM[n0-1].beziers_knot[0].co[0]=CP[0]
courbes.ITEM[n0-1].beziers_knot[0].co[1]=CP[1]
CP=[l2[-3], l2[-1]]
elif l[1]=='1' and (n0 not in courbes.ITEM.keys()):
courbes.ITEM[n0]=ITEM()
courbes.ITEM[n0].Origine=[l[-3],l[-1],]
CP=[l2[-3], l2[-1]]
B=Bez()
B.co=[ CP[0],CP[1],
l1[-3], l1[-1],
l[-3], l[-1]]
CP=[l2[-3], l2[-1]]
if BOUNDINGBOX['rec']==[]:
BOUNDINGBOX['rec']=[float(l2[-3]), float(l2[-1]), float(l[-3]), float(l[-1])]
B.ha=[0,0]
"""
if len( courbes.ITEM[n0].beziers_knot)>=1:
courbes.ITEM[n0].beziers_knot[-1].co[2]=l1[-3]
courbes.ITEM[n0].beziers_knot[-1].co[3]=l1[-1]
"""
MINMAX(B.co)
courbes.ITEM[n0].beziers_knot.append(B)
return courbes,n0
Actions= { "1" : mouvement_vers,
"3" : mouvement_vers }
TAGcourbe=Actions.keys()
def scan_FILE(nom):
global CP, courbes, SCALE, MAX, MIN, CLOSED
dir,name=split(nom)
name=name.split('.')
#print name
n0=0
result=0
t=filtreFICHIER(nom)
if t!="false":
if not SHARP_IMPORT:
warning = "Select Size : %t| As is %x1 | Scale on Height %x2| Scale on Width %x3"
SCALE = Blender.Draw.PupMenu(warning)
npat=0
l=0
while l <len(t)-1 :
#print 'len(t)',len(t)
t[l].replace('\n','')
if t[l][0]!='%':
l0=t[l].split()
#print l0[0], l0[1]
if l0[0]=='TYPE:' and l0[1] in TAGcourbe:
#print l0[0], l0[1],
l1=t[l+1].split()
l2=t[l+2].split()
courbes,n0=Actions[l0[1]](l0,l1,l2,n0)
elif l0[0]=='#Point':
POINTS= int(l0[0])
elif l0[0]=='CLOSED:' and l0[1]=='1':
CLOSED=1
l=l+1;
courbes.number_of_items=len(courbes.ITEM.keys())
courbes.ITEM[n0].beziers_knot[0].co[0]=CP[0]
courbes.ITEM[n0].beziers_knot[0].co[1]=CP[1]
for k in courbes.ITEM.keys():
#print k
if CLOSED == 1:
B=Bez()
B.co=courbes.ITEM[k].beziers_knot[0].co[:]
B.ha=courbes.ITEM[k].beziers_knot[0].ha[:]
B.echo()
courbes.ITEM[k].beziers_knot.append(B)
courbes.ITEM[k].flagUV[0]=1
courbes.ITEM[k].pntsUV[0] =len(courbes.ITEM[k].beziers_knot)
if courbes.number_of_items>0:
t=create_GEOtext(courbes)
save_GEOfile(dir,name[0],t)
Open_GEOfile(dir,name[0])
# 0.1.8 ---------------------------------
Blender.Object.Get()[-1].setName(name[0])
# 0.1.8 ---------------------------------
else:
pass
#=====================================================================
#====================== GIMP Path format mouvements =========================
#=====================================================================
#=========================================================
# une sorte de contournement qui permet d'utiliser la fonction
# et de documenter les variables Window.FileSelector
#=========================================================
def fonctionSELECT(nom):
scan_FILE(nom)
if __name__=="__main__":
Blender.Window.FileSelector (fonctionSELECT, 'SELECT GIMP FILE')

File diff suppressed because it is too large Load Diff

View File

@@ -1,757 +0,0 @@
#!BPY
"""
Name: 'Motion Capture (.bvh)...'
Blender: 242
Group: 'Import'
Tip: 'Import a (.bvh) motion capture file'
"""
__author__ = "Campbell Barton"
__url__ = ("blender.org", "blenderartists.org")
__version__ = "1.90 06/08/01"
__bpydoc__ = """\
This script imports BVH motion capture data to Blender.
as empties or armatures.
"""
# --------------------------------------------------------------------------
# BVH Import v2.0 by Campbell Barton (AKA Ideasman)
# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
import Blender
import bpy
import BPyMessages
Vector= Blender.Mathutils.Vector
Euler= Blender.Mathutils.Euler
Matrix= Blender.Mathutils.Matrix
RotationMatrix = Blender.Mathutils.RotationMatrix
TranslationMatrix= Blender.Mathutils.TranslationMatrix
DEG2RAD = 0.017453292519943295
class bvh_node_class(object):
__slots__=(\
'name',# bvh joint name
'parent',# bvh_node_class type or None for no parent
'children',# a list of children of this type.
'rest_head_world',# worldspace rest location for the head of this node
'rest_head_local',# localspace rest location for the head of this node
'rest_tail_world',# # worldspace rest location for the tail of this node
'rest_tail_local',# # worldspace rest location for the tail of this node
'channels',# list of 6 ints, -1 for an unused channel, otherwise an index for the BVH motion data lines, lock triple then rot triple
'rot_order',# a triple of indicies as to the order rotation is applied. [0,1,2] is x/y/z - [None, None, None] if no rotation.
'anim_data',# a list one tuple's one for each frame. (locx, locy, locz, rotx, roty, rotz)
'has_loc',# Conveinience function, bool, same as (channels[0]!=-1 or channels[1]!=-1 channels[2]!=-1)
'has_rot',# Conveinience function, bool, same as (channels[3]!=-1 or channels[4]!=-1 channels[5]!=-1)
'temp')# use this for whatever you want
def __init__(self, name, rest_head_world, rest_head_local, parent, channels, rot_order):
self.name= name
self.rest_head_world= rest_head_world
self.rest_head_local= rest_head_local
self.rest_tail_world= None
self.rest_tail_local= None
self.parent= parent
self.channels= channels
self.rot_order= rot_order
# convenience functions
self.has_loc= channels[0] != -1 or channels[1] != -1 or channels[2] != -1
self.has_rot= channels[3] != -1 or channels[4] != -1 or channels[5] != -1
self.children= []
# list of 6 length tuples: (lx,ly,lz, rx,ry,rz)
# even if the channels arnt used they will just be zero
#
self.anim_data= [(0,0,0,0,0,0)]
def __repr__(self):
return 'BVH name:"%s", rest_loc:(%.3f,%.3f,%.3f), rest_tail:(%.3f,%.3f,%.3f)' %\
(self.name,\
self.rest_head_world.x, self.rest_head_world.y, self.rest_head_world.z,\
self.rest_head_world.x, self.rest_head_world.y, self.rest_head_world.z)
# Change the order rotation is applied.
MATRIX_IDENTITY_3x3 = Matrix([1,0,0],[0,1,0],[0,0,1])
MATRIX_IDENTITY_4x4 = Matrix([1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1])
def eulerRotate(x,y,z, rot_order):
# Clamp all values between 0 and 360, values outside this raise an error.
mats=[RotationMatrix(x%360,3,'x'), RotationMatrix(y%360,3,'y'), RotationMatrix(z%360,3,'z')]
# print rot_order
# Standard BVH multiplication order, apply the rotation in the order Z,X,Y
return (mats[rot_order[2]]*(mats[rot_order[1]]* (mats[rot_order[0]]* MATRIX_IDENTITY_3x3))).toEuler()
def read_bvh(file_path, GLOBAL_SCALE=1.0):
# File loading stuff
# Open the file for importing
file = open(file_path, 'rU')
# Seperate into a list of lists, each line a list of words.
file_lines = file.readlines()
# Non standard carrage returns?
if len(file_lines) == 1:
file_lines = file_lines[0].split('\r')
# Split by whitespace.
file_lines =[ll for ll in [ l.split() for l in file_lines] if ll]
# Create Hirachy as empties
if file_lines[0][0].lower() == 'hierarchy':
#print 'Importing the BVH Hierarchy for:', file_path
pass
else:
raise 'ERROR: This is not a BVH file'
bvh_nodes= {None:None}
bvh_nodes_serial = [None]
channelIndex = -1
lineIdx = 0 # An index for the file.
while lineIdx < len(file_lines) -1:
#...
if file_lines[lineIdx][0].lower() == 'root' or file_lines[lineIdx][0].lower() == 'joint':
# Join spaces into 1 word with underscores joining it.
if len(file_lines[lineIdx]) > 2:
file_lines[lineIdx][1] = '_'.join(file_lines[lineIdx][1:])
file_lines[lineIdx] = file_lines[lineIdx][:2]
# MAY NEED TO SUPPORT MULTIPLE ROOT's HERE!!!, Still unsure weather multiple roots are possible.??
# Make sure the names are unique- Object names will match joint names exactly and both will be unique.
name = file_lines[lineIdx][1]
#print '%snode: %s, parent: %s' % (len(bvh_nodes_serial) * ' ', name, bvh_nodes_serial[-1])
lineIdx += 2 # Incriment to the next line (Offset)
rest_head_local = Vector( GLOBAL_SCALE*float(file_lines[lineIdx][1]), GLOBAL_SCALE*float(file_lines[lineIdx][2]), GLOBAL_SCALE*float(file_lines[lineIdx][3]) )
lineIdx += 1 # Incriment to the next line (Channels)
# newChannel[Xposition, Yposition, Zposition, Xrotation, Yrotation, Zrotation]
# newChannel references indecies to the motiondata,
# if not assigned then -1 refers to the last value that will be added on loading at a value of zero, this is appended
# We'll add a zero value onto the end of the MotionDATA so this is always refers to a value.
my_channel = [-1, -1, -1, -1, -1, -1]
my_rot_order= [None, None, None]
rot_count= 0
for channel in file_lines[lineIdx][2:]:
channel= channel.lower()
channelIndex += 1 # So the index points to the right channel
if channel == 'xposition': my_channel[0] = channelIndex
elif channel == 'yposition': my_channel[1] = channelIndex
elif channel == 'zposition': my_channel[2] = channelIndex
elif channel == 'xrotation':
my_channel[3] = channelIndex
my_rot_order[rot_count]= 0
rot_count+=1
elif channel == 'yrotation':
my_channel[4] = channelIndex
my_rot_order[rot_count]= 1
rot_count+=1
elif channel == 'zrotation':
my_channel[5] = channelIndex
my_rot_order[rot_count]= 2
rot_count+=1
channels = file_lines[lineIdx][2:]
my_parent= bvh_nodes_serial[-1] # account for none
# Apply the parents offset accumletivly
if my_parent==None:
rest_head_world= Vector(rest_head_local)
else:
rest_head_world= my_parent.rest_head_world + rest_head_local
bvh_node= bvh_nodes[name]= bvh_node_class(name, rest_head_world, rest_head_local, my_parent, my_channel, my_rot_order)
# If we have another child then we can call ourselves a parent, else
bvh_nodes_serial.append(bvh_node)
# Account for an end node
if file_lines[lineIdx][0].lower() == 'end' and file_lines[lineIdx][1].lower() == 'site': # There is somtimes a name after 'End Site' but we will ignore it.
lineIdx += 2 # Incriment to the next line (Offset)
rest_tail = Vector( GLOBAL_SCALE*float(file_lines[lineIdx][1]), GLOBAL_SCALE*float(file_lines[lineIdx][2]), GLOBAL_SCALE*float(file_lines[lineIdx][3]) )
bvh_nodes_serial[-1].rest_tail_world= bvh_nodes_serial[-1].rest_head_world + rest_tail
bvh_nodes_serial[-1].rest_tail_local= rest_tail
# Just so we can remove the Parents in a uniform way- End end never has kids
# so this is a placeholder
bvh_nodes_serial.append(None)
if len(file_lines[lineIdx]) == 1 and file_lines[lineIdx][0] == '}': # == ['}']
bvh_nodes_serial.pop() # Remove the last item
if len(file_lines[lineIdx]) == 1 and file_lines[lineIdx][0].lower() == 'motion':
#print '\nImporting motion data'
lineIdx += 3 # Set the cursor to the first frame
break
lineIdx += 1
# Remove the None value used for easy parent reference
del bvh_nodes[None]
# Dont use anymore
del bvh_nodes_serial
bvh_nodes_list= bvh_nodes.values()
while lineIdx < len(file_lines):
line= file_lines[lineIdx]
for bvh_node in bvh_nodes_list:
#for bvh_node in bvh_nodes_serial:
lx= ly= lz= rx= ry= rz= 0.0
channels= bvh_node.channels
anim_data= bvh_node.anim_data
if channels[0] != -1:
lx= GLOBAL_SCALE * float( line[channels[0]] )
if channels[1] != -1:
ly= GLOBAL_SCALE * float( line[channels[1]] )
if channels[2] != -1:
lz= GLOBAL_SCALE * float( line[channels[2]] )
if channels[3] != -1 or channels[4] != -1 or channels[5] != -1:
rx, ry, rz = eulerRotate(float( line[channels[3]] ), float( line[channels[4]] ), float( line[channels[5]] ), bvh_node.rot_order)
#x,y,z = x/10.0, y/10.0, z/10.0 # For IPO's 36 is 360d
# Make interpolation not cross between 180d, thjis fixes sub frame interpolation and time scaling.
# Will go from (355d to 365d) rather then to (355d to 5d) - inbetween these 2 there will now be a correct interpolation.
while anim_data[-1][3] - rx > 180: rx+=360
while anim_data[-1][3] - rx < -180: rx-=360
while anim_data[-1][4] - ry > 180: ry+=360
while anim_data[-1][4] - ry < -180: ry-=360
while anim_data[-1][5] - rz > 180: rz+=360
while anim_data[-1][5] - rz < -180: rz-=360
# Done importing motion data #
anim_data.append( (lx, ly, lz, rx, ry, rz) )
lineIdx += 1
# Assign children
for bvh_node in bvh_nodes.itervalues():
bvh_node_parent= bvh_node.parent
if bvh_node_parent:
bvh_node_parent.children.append(bvh_node)
# Now set the tip of each bvh_node
for bvh_node in bvh_nodes.itervalues():
if not bvh_node.rest_tail_world:
if len(bvh_node.children)==0:
# could just fail here, but rare BVH files have childless nodes
bvh_node.rest_tail_world = Vector(bvh_node.rest_head_world)
bvh_node.rest_tail_local = Vector(bvh_node.rest_head_local)
elif len(bvh_node.children)==1:
bvh_node.rest_tail_world= Vector(bvh_node.children[0].rest_head_world)
bvh_node.rest_tail_local= Vector(bvh_node.children[0].rest_head_local)
else:
# allow this, see above
#if not bvh_node.children:
# raise 'error, bvh node has no end and no children. bad file'
# Removed temp for now
rest_tail_world= Vector(0,0,0)
rest_tail_local= Vector(0,0,0)
for bvh_node_child in bvh_node.children:
rest_tail_world += bvh_node_child.rest_head_world
rest_tail_local += bvh_node_child.rest_head_local
bvh_node.rest_tail_world= rest_tail_world * (1.0/len(bvh_node.children))
bvh_node.rest_tail_local= rest_tail_local * (1.0/len(bvh_node.children))
# Make sure tail isnt the same location as the head.
if (bvh_node.rest_tail_local-bvh_node.rest_head_local).length <= 0.001*GLOBAL_SCALE:
bvh_node.rest_tail_local.y= bvh_node.rest_tail_local.y + GLOBAL_SCALE/10
bvh_node.rest_tail_world.y= bvh_node.rest_tail_world.y + GLOBAL_SCALE/10
return bvh_nodes
def bvh_node_dict2objects(bvh_nodes, IMPORT_START_FRAME= 1, IMPORT_LOOP= False):
if IMPORT_START_FRAME<1:
IMPORT_START_FRAME= 1
scn= bpy.data.scenes.active
scn.objects.selected = []
objects= []
def add_ob(name):
ob = scn.objects.new('Empty')
objects.append(ob)
return ob
# Add objects
for name, bvh_node in bvh_nodes.iteritems():
bvh_node.temp= add_ob(name)
# Parent the objects
for bvh_node in bvh_nodes.itervalues():
bvh_node.temp.makeParent([ bvh_node_child.temp for bvh_node_child in bvh_node.children ], 1, 0) # ojbs, noninverse, 1 = not fast.
# Offset
for bvh_node in bvh_nodes.itervalues():
# Make relative to parents offset
bvh_node.temp.loc= bvh_node.rest_head_local
# Add tail objects
for name, bvh_node in bvh_nodes.iteritems():
if not bvh_node.children:
ob_end= add_ob(name + '_end')
bvh_node.temp.makeParent([ob_end], 1, 0) # ojbs, noninverse, 1 = not fast.
ob_end.loc= bvh_node.rest_tail_local
# Animate the data, the last used bvh_node will do since they all have the same number of frames
for current_frame in xrange(len(bvh_node.anim_data)):
Blender.Set('curframe', current_frame+IMPORT_START_FRAME)
for bvh_node in bvh_nodes.itervalues():
lx,ly,lz,rx,ry,rz= bvh_node.anim_data[current_frame]
rest_head_local= bvh_node.rest_head_local
bvh_node.temp.loc= rest_head_local.x+lx, rest_head_local.y+ly, rest_head_local.z+lz
bvh_node.temp.rot= rx*DEG2RAD,ry*DEG2RAD,rz*DEG2RAD
bvh_node.temp.insertIpoKey(Blender.Object.IpoKeyTypes.LOCROT)
scn.update(1)
return objects
def bvh_node_dict2armature(bvh_nodes, IMPORT_START_FRAME= 1, IMPORT_LOOP= False):
if IMPORT_START_FRAME<1:
IMPORT_START_FRAME= 1
# Add the new armature,
scn = bpy.data.scenes.active
scn.objects.selected = []
arm_data= bpy.data.armatures.new()
arm_ob = scn.objects.new(arm_data)
scn.objects.context = [arm_ob]
scn.objects.active = arm_ob
# Put us into editmode
arm_data.makeEditable()
# Get the average bone length for zero length bones, we may not use this.
average_bone_length= 0.0
nonzero_count= 0
for bvh_node in bvh_nodes.itervalues():
l= (bvh_node.rest_head_local-bvh_node.rest_tail_local).length
if l:
average_bone_length+= l
nonzero_count+=1
# Very rare cases all bones couldbe zero length???
if not average_bone_length:
average_bone_length = 0.1
else:
# Normal operation
average_bone_length = average_bone_length/nonzero_count
ZERO_AREA_BONES= []
for name, bvh_node in bvh_nodes.iteritems():
# New editbone
bone= bvh_node.temp= Blender.Armature.Editbone()
bone.name= name
arm_data.bones[name]= bone
bone.head= bvh_node.rest_head_world
bone.tail= bvh_node.rest_tail_world
# ZERO AREA BONES.
if (bone.head-bone.tail).length < 0.001:
if bvh_node.parent:
ofs= bvh_node.parent.rest_head_local- bvh_node.parent.rest_tail_local
if ofs.length: # is our parent zero length also?? unlikely
bone.tail= bone.tail+ofs
else:
bone.tail.y= bone.tail.y+average_bone_length
else:
bone.tail.y= bone.tail.y+average_bone_length
ZERO_AREA_BONES.append(bone.name)
for bvh_node in bvh_nodes.itervalues():
if bvh_node.parent:
# bvh_node.temp is the Editbone
# Set the bone parent
bvh_node.temp.parent= bvh_node.parent.temp
# Set the connection state
if not bvh_node.has_loc and\
bvh_node.parent and\
bvh_node.parent.temp.name not in ZERO_AREA_BONES and\
bvh_node.parent.rest_tail_local == bvh_node.rest_head_local:
bvh_node.temp.options= [Blender.Armature.CONNECTED]
# Replace the editbone with the editbone name,
# to avoid memory errors accessing the editbone outside editmode
for bvh_node in bvh_nodes.itervalues():
bvh_node.temp= bvh_node.temp.name
arm_data.update()
# Now Apply the animation to the armature
# Get armature animation data
pose= arm_ob.getPose()
pose_bones= pose.bones
action = Blender.Armature.NLA.NewAction("Action")
action.setActive(arm_ob)
#xformConstants= [ Blender.Object.Pose.LOC, Blender.Object.Pose.ROT ]
# Replace the bvh_node.temp (currently an editbone)
# With a tuple (pose_bone, armature_bone, bone_rest_matrix, bone_rest_matrix_inv)
for bvh_node in bvh_nodes.itervalues():
bone_name= bvh_node.temp # may not be the same name as the bvh_node, could have been shortened.
pose_bone= pose_bones[bone_name]
rest_bone= arm_data.bones[bone_name]
bone_rest_matrix = rest_bone.matrix['ARMATURESPACE'].rotationPart()
bone_rest_matrix_inv= Matrix(bone_rest_matrix)
bone_rest_matrix_inv.invert()
bone_rest_matrix_inv.resize4x4()
bone_rest_matrix.resize4x4()
bvh_node.temp= (pose_bone, bone, bone_rest_matrix, bone_rest_matrix_inv)
# Make a dict for fast access without rebuilding a list all the time.
xformConstants_dict={
(True,True): [Blender.Object.Pose.LOC, Blender.Object.Pose.ROT],\
(False,True): [Blender.Object.Pose.ROT],\
(True,False): [Blender.Object.Pose.LOC],\
(False,False): [],\
}
# KEYFRAME METHOD, SLOW, USE IPOS DIRECT
# Animate the data, the last used bvh_node will do since they all have the same number of frames
for current_frame in xrange(len(bvh_node.anim_data)-1): # skip the first frame (rest frame)
# print current_frame
#if current_frame==40: # debugging
# break
# Dont neet to set the current frame
for bvh_node in bvh_nodes.itervalues():
pose_bone, bone, bone_rest_matrix, bone_rest_matrix_inv= bvh_node.temp
lx,ly,lz,rx,ry,rz= bvh_node.anim_data[current_frame+1]
if bvh_node.has_rot:
# Set the rotation, not so simple
bone_rotation_matrix= Euler(rx,ry,rz).toMatrix()
bone_rotation_matrix.resize4x4()
pose_bone.quat= (bone_rest_matrix * bone_rotation_matrix * bone_rest_matrix_inv).toQuat()
if bvh_node.has_loc:
# Set the Location, simple too
pose_bone.loc= (\
TranslationMatrix(Vector(lx, ly, lz) - bvh_node.rest_head_local ) *\
bone_rest_matrix_inv).translationPart() # WHY * 10? - just how pose works
# Get the transform
xformConstants= xformConstants_dict[bvh_node.has_loc, bvh_node.has_rot]
if xformConstants:
# Insert the keyframe from the loc/quat
pose_bone.insertKey(arm_ob, current_frame+IMPORT_START_FRAME, xformConstants, True )
# First time, set the IPO's to linear
if current_frame==0:
for ipo in action.getAllChannelIpos().itervalues():
if ipo:
for cur in ipo:
cur.interpolation = Blender.IpoCurve.InterpTypes.LINEAR
if IMPORT_LOOP:
cur.extend = Blender.IpoCurve.ExtendTypes.CYCLIC
# END KEYFRAME METHOD
"""
# IPO KEYFRAME SETTING
# Add in the IPOs by adding keyframes, AFAIK theres no way to add IPOs to an action so I do this :/
for bvh_node in bvh_nodes.itervalues():
pose_bone, bone, bone_rest_matrix, bone_rest_matrix_inv= bvh_node.temp
# Get the transform
xformConstants= xformConstants_dict[bvh_node.has_loc, bvh_node.has_rot]
if xformConstants:
pose_bone.loc[:]= 0,0,0
pose_bone.quat[:]= 0,0,1,0
# Insert the keyframe from the loc/quat
pose_bone.insertKey(arm_ob, IMPORT_START_FRAME, xformConstants)
action_ipos= action.getAllChannelIpos()
for bvh_node in bvh_nodes.itervalues():
has_loc= bvh_node.has_loc
has_rot= bvh_node.has_rot
if not has_rot and not has_loc:
# No animation data
continue
ipo= action_ipos[bvh_node.temp[0].name] # posebones name as key
if has_loc:
curve_xloc= ipo[Blender.Ipo.PO_LOCX]
curve_yloc= ipo[Blender.Ipo.PO_LOCY]
curve_zloc= ipo[Blender.Ipo.PO_LOCZ]
curve_xloc.interpolation= \
curve_yloc.interpolation= \
curve_zloc.interpolation= \
Blender.IpoCurve.InterpTypes.LINEAR
if has_rot:
curve_wquat= ipo[Blender.Ipo.PO_QUATW]
curve_xquat= ipo[Blender.Ipo.PO_QUATX]
curve_yquat= ipo[Blender.Ipo.PO_QUATY]
curve_zquat= ipo[Blender.Ipo.PO_QUATZ]
curve_wquat.interpolation= \
curve_xquat.interpolation= \
curve_yquat.interpolation= \
curve_zquat.interpolation= \
Blender.IpoCurve.InterpTypes.LINEAR
# Get the bone
pose_bone, bone, bone_rest_matrix, bone_rest_matrix_inv= bvh_node.temp
def pose_rot(anim_data):
bone_rotation_matrix= Euler(anim_data[3], anim_data[4], anim_data[5]).toMatrix()
bone_rotation_matrix.resize4x4()
return tuple((bone_rest_matrix * bone_rotation_matrix * bone_rest_matrix_inv).toQuat()) # qw,qx,qy,qz
def pose_loc(anim_data):
return tuple((TranslationMatrix(Vector(anim_data[0], anim_data[1], anim_data[2])) * bone_rest_matrix_inv).translationPart())
last_frame= len(bvh_node.anim_data)+IMPORT_START_FRAME-1
if has_loc:
pose_locations= [pose_loc(anim_key) for anim_key in bvh_node.anim_data]
# Add the start at the end, we know the start is just 0,0,0 anyway
curve_xloc.append((last_frame, pose_locations[-1][0]))
curve_yloc.append((last_frame, pose_locations[-1][1]))
curve_zloc.append((last_frame, pose_locations[-1][2]))
if len(pose_locations) > 1:
ox,oy,oz= pose_locations[0]
x,y,z= pose_locations[1]
for i in xrange(1, len(pose_locations)-1): # from second frame to second last frame
nx,ny,nz= pose_locations[i+1]
xset= yset= zset= True # we set all these by default
if abs((ox+nx)/2 - x) < 0.00001: xset= False
if abs((oy+ny)/2 - y) < 0.00001: yset= False
if abs((oz+nz)/2 - z) < 0.00001: zset= False
if xset: curve_xloc.append((i+IMPORT_START_FRAME, x))
if yset: curve_yloc.append((i+IMPORT_START_FRAME, y))
if zset: curve_zloc.append((i+IMPORT_START_FRAME, z))
# Set the old and use the new
ox,oy,oz= x,y,z
x,y,z= nx,ny,nz
if has_rot:
pose_rotations= [pose_rot(anim_key) for anim_key in bvh_node.anim_data]
# Add the start at the end, we know the start is just 0,0,0 anyway
curve_wquat.append((last_frame, pose_rotations[-1][0]))
curve_xquat.append((last_frame, pose_rotations[-1][1]))
curve_yquat.append((last_frame, pose_rotations[-1][2]))
curve_zquat.append((last_frame, pose_rotations[-1][3]))
if len(pose_rotations) > 1:
ow,ox,oy,oz= pose_rotations[0]
w,x,y,z= pose_rotations[1]
for i in xrange(1, len(pose_rotations)-1): # from second frame to second last frame
nw, nx,ny,nz= pose_rotations[i+1]
wset= xset= yset= zset= True # we set all these by default
if abs((ow+nw)/2 - w) < 0.00001: wset= False
if abs((ox+nx)/2 - x) < 0.00001: xset= False
if abs((oy+ny)/2 - y) < 0.00001: yset= False
if abs((oz+nz)/2 - z) < 0.00001: zset= False
if wset: curve_wquat.append((i+IMPORT_START_FRAME, w))
if xset: curve_xquat.append((i+IMPORT_START_FRAME, x))
if yset: curve_yquat.append((i+IMPORT_START_FRAME, y))
if zset: curve_zquat.append((i+IMPORT_START_FRAME, z))
# Set the old and use the new
ow,ox,oy,oz= w,x,y,z
w,x,y,z= nw,nx,ny,nz
# IPO KEYFRAME SETTING
"""
pose.update()
return arm_ob
#=============#
# TESTING #
#=============#
#('/metavr/mocap/bvh/boxer.bvh')
#('/d/staggered_walk.bvh')
#('/metavr/mocap/bvh/dg-306-g.bvh') # Incompleate EOF
#('/metavr/mocap/bvh/wa8lk.bvh') # duplicate joint names, \r line endings.
#('/metavr/mocap/bvh/walk4.bvh') # 0 channels
'''
import os
DIR = '/metavr/mocap/bvh/'
for f in ('/d/staggered_walk.bvh',):
#for f in os.listdir(DIR)[5:6]:
#for f in os.listdir(DIR):
if f.endswith('.bvh'):
s = Blender.Scene.New(f)
s.makeCurrent()
#file= DIR + f
file= f
print f
bvh_nodes= read_bvh(file, 1.0)
bvh_node_dict2armature(bvh_nodes, 1)
'''
def load_bvh_ui(file, PREF_UI= True):
if BPyMessages.Error_NoFile(file):
return
Draw= Blender.Draw
IMPORT_SCALE = Draw.Create(0.1)
IMPORT_START_FRAME = Draw.Create(1)
IMPORT_AS_ARMATURE = Draw.Create(1)
IMPORT_AS_EMPTIES = Draw.Create(0)
IMPORT_LOOP = Draw.Create(0)
# Get USER Options
if PREF_UI:
pup_block = [\
('As Armature', IMPORT_AS_ARMATURE, 'Imports the BVH as an armature'),\
('As Empties', IMPORT_AS_EMPTIES, 'Imports the BVH as empties'),\
('Scale: ', IMPORT_SCALE, 0.001, 100.0, 'Scale the BVH, Use 0.01 when 1.0 is 1 metre'),\
('Start Frame: ', IMPORT_START_FRAME, 1, 30000, 'Frame to start BVH motion'),\
('Loop Animation', IMPORT_LOOP, 'Enable cyclic IPOs'),\
]
if not Draw.PupBlock('BVH Import...', pup_block):
return
print 'Attempting import BVH', file
IMPORT_SCALE = IMPORT_SCALE.val
IMPORT_START_FRAME = IMPORT_START_FRAME.val
IMPORT_AS_ARMATURE = IMPORT_AS_ARMATURE.val
IMPORT_AS_EMPTIES = IMPORT_AS_EMPTIES.val
IMPORT_LOOP = IMPORT_LOOP.val
if not IMPORT_AS_ARMATURE and not IMPORT_AS_EMPTIES:
Blender.Draw.PupMenu('No import option selected')
return
Blender.Window.WaitCursor(1)
# Get the BVH data and act on it.
t1= Blender.sys.time()
print '\tparsing bvh...',
bvh_nodes= read_bvh(file, IMPORT_SCALE)
print '%.4f' % (Blender.sys.time()-t1)
t1= Blender.sys.time()
print '\timporting to blender...',
if IMPORT_AS_ARMATURE: bvh_node_dict2armature(bvh_nodes, IMPORT_START_FRAME, IMPORT_LOOP)
if IMPORT_AS_EMPTIES: bvh_node_dict2objects(bvh_nodes, IMPORT_START_FRAME, IMPORT_LOOP)
print 'Done in %.4f\n' % (Blender.sys.time()-t1)
Blender.Window.WaitCursor(0)
def main():
Blender.Window.FileSelector(load_bvh_ui, 'Import BVH', '*.bvh')
if __name__ == '__main__':
#def foo():
main()
'''
scn = bpy.data.scenes.active
for ob in list(scn.objects):
if ob.name!='arm__':
scn.objects.unlink(ob)
load_bvh_ui('/test.bvh', False)
'''

File diff suppressed because it is too large Load Diff

View File

@@ -1,121 +0,0 @@
#!BPY
""" Registration info for Blender menus: <- these words are ignored
Name: 'Camera Changer'
Blender: 234
Group: 'Animation'
Tip: 'Create script link to change cameras (based on their names) during an animation'
"""
__author__ = '3R - R3gis'
__version__ = '1.2'
__url__ = ["Author's site , http://cybercreator.free.fr", "French Blender support forum, http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender"]
__email__=["3R, r3gis@free.fr"]
__bpydoc__ = """\
This script creates an script link to change cameras during an animation.
The created script link (a Blender Text) is linked to Scene Frame Changed events.
Usage:
Run the script, then name the camera Object with the number of the frame(s)
where you want this camera to become active.
For example:<br>
- a camera called "10" will become active at frame 10.<br>
- a camera called "10,25,185" will become active at frames 10, 25 and 185.
Notes:<br>
- This script creates another script named camera.py, which is linked to the current scene.<br>
- If there is already a text called "camera.py", but it's from an old version or is not recognized,
you can choose if you want to rename or overwrite it.
- Script inspired by Jean-Michel (jms) Soler's:<br>
http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_changerdecamera.htm
"""
# $Id$
#
# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
# Copyright (C) 2004-2005: Regis Montoya
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
#Script inspired of the idea of this one :
#http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_changerdecamera.htm
#
#----------------------------------------------
# R3gis Montoya (3R)
#
# Pout tout probleme a:
# cybercreator@free.fr
# ---------------------------------------------
import Blender
from Blender import *
import string
header = '# camera.py 1.3 scriptlink'
camera_change_scriptlink = header + \
'''
import Blender
def main():
scn = Blender.Scene.GetCurrent()
frame = str(Blender.Get('curframe'))
# change the camera if it has the current frame
for ob_cam in [ob for ob in scn.objects if ob.type == 'Camera']:
for number in ob_cam.name.split(','):
if number == frame:
scn.setCurrentCamera(ob_cam)
return
main()
'''
def main():
# Get the text
try: cam_text = Blender.Text.Get('camera.py')
except: cam_text = None
if cam_text:
if cam_text.asLines()[0] != header:
ret = Blender.Draw.PupMenu("WARNING: An old camera.py exists%t|Overwrite|Rename old version text")
if ret == -1: return # EXIT DO NOTHING
elif ret == 1: Text.unlink(cam_text)
elif ret == 2: cam_text.name = 'old_camera.txt'
cam_text = None
if not cam_text:
scripting=Blender.Text.New('camera.py')
scripting.write(camera_change_scriptlink)
scn=Scene.GetCurrent()
scriptlinks = scn.getScriptLinks('FrameChanged')
if not scriptlinks or ('camera.py' not in scriptlinks):
scn.addScriptLink('camera.py','FrameChanged')
Blender.Draw.PupMenu('FrameChange Scriptlink Added%t|Name camera objects to their activation frame numbers(s) seperated by commas|valid names are "1,10,46" or "1,10,200" or "200" (without quotation marks)')
Blender.Window.RedrawAll()
if __name__ == '__main__':
main()

View File

@@ -1,801 +0,0 @@
#!BPY
"""
Name: 'Scripts Config Editor'
Blender: 236
Group: 'System'
Tooltip: 'View and edit available scripts configuration data'
"""
__author__ = "Willian P. Germano"
__version__ = "0.1 2005/04/14"
__email__ = ('scripts', 'Author, wgermano:ig*com*br')
__url__ = ('blender', 'blenderartists.org')
__bpydoc__ ="""\
This script can be used to view and edit configuration data stored
by other scripts.
Technical: this data is saved as dictionary keys with the
Blender.Registry module functions. It is persistent while Blender is
running and, if the script's author chose to, is also saved to a file
in the scripts config data dir.
Usage:
- Start Screen:
To access any available key, select it from (one of) the menu(s).
Hotkeys:<br>
ESC or Q: [Q]uit<br>
H: [H]elp
- Keys Config Screen:
This screen exposes the configuration data for the chosen script key. If the
buttons don't fit completely on the screen, you can scroll up or down with
arrow keys or a mouse wheel. Leave the mouse pointer over any button to get
a tooltip about that option.
Any change can be reverted -- unless you have already applied it.
If the key is already stored in a config file, there will be a toggle button
(called 'file') that controls whether the changes will be written back to
the file or not. If you just want to change the configuration for the current
session, simply unset that button. Note, though, that data from files has
precedence over those keys already loaded in Blender, so if you re-run this
config editor, unsaved changes will not be seen.
Hotkeys:<br>
ESC: back to Start Screen<br>
Q: [Q]uit<br>
U: [U]ndo changes<br>
ENTER: apply changes (can't be reverted, then)<br>
UP, DOWN Arrows and mouse wheel: scroll text up / down
Notes:
a) Available keys are determined by which scripts you use. If the key you
expect isn't available (or maybe there are none or too few keys), either the
related script doesn't need or still doesn't support this feature or the key
has not been stored yet, in which case you just need to run that script once
to make its config data available.
b) There are two places where config data files can be saved: the
bpydata/config/ dir (1) inside the default scripts dir or (2) inside the user
defined Python scripts dir
(User Preferences window -> File Paths tab -> Python path). If available,
(2) is the default and also the recommended option, because then fresh Blender
installations won't delete your config data. To use this option, simply set a
dir for Python scripts at the User Preferences window and make sure this dir
has the subdirs bpydata/ and bpydata/config/ inside it.
c) The key called "General" in the "Other" menu has general config options.
All scripts where that data is relevant are recommended to access it and set
behaviors accordingly.
"""
# $Id$
#
# --------------------------------------------------------------------------
# config.py version 0.1 2005/04/08
# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
# Copyright (C) 2004: Willian P. Germano, wgermano _at_ ig.com.br
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
import Blender
from Blender import Draw, BGL, Registry, Window, sys as bsys
from Blender.Window import Theme
from BPyRegistry import LoadConfigData, SaveConfigData, HasConfigData,\
BPY_KEY_IN_FILE
MAX_STR_LEN = 300 # max length for a string
MAX_ITEMS_NUM = 100 # max number for each type of button
# ---
# The "General" configure options key is managed from this script.
verbose = True
confirm_overwrite = True
tooltips = {
'verbose': 'print script messages (info, warnings, errors) to the console',
'confirm_overwrite': 'scripts should always confirm before overwriting files'
}
CFG_LIST = ['verbose', 'confirm_overwrite', 'tooltips']
KEY_NAME = 'General'
def update_registry():
rd = {}
for var in CFG_LIST:
exec("rd['%s']=%s" % (var, var))
Registry.SetKey(KEY_NAME, rd, True)
rd = Registry.GetKey('General', True)
if rd:
try:
for var in CFG_LIST[:-1]: # no need to update tooltips
exec("%s=rd['%s']" % (var, var))
except: update_registry()
else:
update_registry()
# ---
# script globals:
CFGKEY = ''
LABELS = []
GD = {} # groups dict (includes "Other" for unmapped keys)
INDEX = 0 # to pass button indices to fs callbacks
FREEKEY_IDX = 0 # index of set of keys not mapped to a script name
KEYMENUS = []
ALL_SCRIPTS = {}
ALL_GROUPS = []
START_SCREEN = 0
CONFIG_SCREEN = 1
DISK_UPDATE = True # write changed data to its config file
ACCEPTED_TYPES = [bool, int, float, str, unicode]
SCREEN = START_SCREEN
SCROLL_DOWN = 0
# events:
BEVT_START = 50
BEVT_EXIT = 0 + BEVT_START
BEVT_BACK = 1 + BEVT_START
BEVT_DISK = 2 + BEVT_START
BEVT_CANCEL = 3 + BEVT_START
BEVT_APPLY = 4 + BEVT_START
BEVT_HELP = 5 + BEVT_START
BEVT_DEL = 6 + BEVT_START
BEVT_KEYMENU = []
BUT_KEYMENU = []
BEVT_BOOL = 100
BEVT_INT = BEVT_BOOL + MAX_ITEMS_NUM
BEVT_FLOAT = BEVT_BOOL + 2*MAX_ITEMS_NUM
BEVT_STR = BEVT_BOOL + 3*MAX_ITEMS_NUM
BEVT_BROWSEDIR = BEVT_BOOL + 4*MAX_ITEMS_NUM
BEVT_BROWSEFILE = BEVT_BOOL + 5*MAX_ITEMS_NUM
BUT_TYPES = {
bool: 0,
int: 0,
float: 0,
str: 0
}
# Function definitions:
def get_keys():
LoadConfigData() # loads all data from files in (u)scripts/bpydata/config/
return [k for k in Registry.Keys() if k[0] != "_"]
def show_help(script = 'config.py'):
Blender.ShowHelp(script)
def fs_dir_callback(pathname):
global CFGKEY, INDEX
pathname = bsys.dirname(pathname)
datatypes = CFGKEY.sorteddata
datatypes[str][INDEX][1] = pathname
def fs_file_callback(pathname):
global CFGKEY, INDEX
datatypes = CFGKEY.sorteddata
datatypes[str][INDEX][1] = pathname
# parse Bpymenus file to get all script filenames
# (used to show help for a given key)
def fill_scripts_dict():
global ALL_SCRIPTS, ALL_GROUPS
group = ''
group_len = 0
sep = bsys.sep
home = Blender.Get('homedir')
if not home:
errmsg = """
Can't find Blender's home dir and so can't find the
Bpymenus file automatically stored inside it, which
is needed by this script. Please run the
Help -> System -> System Information script to get
information about how to fix this.
"""
raise SystemError, errmsg
fname = bsys.join(home, 'Bpymenus')
if not bsys.exists(fname): return False
f = file(fname, 'r')
lines = f.readlines()
f.close()
for l in lines:
if l.rfind('{') > 0:
group = l.split()[0]
ALL_GROUPS.append(group)
group_len += 1
continue
elif l[0] != "'": continue
fields = l.split("'")
if len(fields) > 2:
menuname = fields[1].replace('...','')
fields = fields[2].split()
if len(fields) > 1:
fname = fields[1].split(sep)[-1]
i = 1
while not fname.endswith('.py'):
i += 1
fname = "%s %s" % (fname, fields[i])
ALL_SCRIPTS[fname] = (menuname, group_len - 1)
return True
def map_to_registered_script(name):
global ALL_SCRIPTS
if not name.endswith('.py'):
name = "%s.py" % name
if ALL_SCRIPTS.has_key(name):
return ALL_SCRIPTS[name] # == (menuname, group index)
return None
def reset():
global LABELS, GD, KEYMENUS, KEYS
# init_data is recalled when a key is deleted, so:
LABELS = []
GD = {}
KEYMENUS = []
KEYS = get_keys()
# gather all script info, fill gui menus
def init_data():
global KEYS, GD, ALL_GROUPS, ALL_SCRIPTS, KEYMENUS, LABELS
global BUT_KEYMENU, BEVT_KEYMENU, FREEKEY_IDX
for k in ALL_GROUPS:
GD[k] = []
GD[None] = []
for k in KEYS:
res = map_to_registered_script(k)
if res:
GD[ALL_GROUPS[res[1]]].append((k, res[0]))
else: GD[None].append((k, k))
for k in GD.keys():
if not GD[k]: GD.pop(k)
if GD.has_key(None):
GD['Other'] = GD[None]
GD.pop(None)
FREEKEY_IDX = -1
BUT_KEYMENU = range(len(GD))
for k in GD.keys():
kmenu = ['Configuration Keys: %s%%t' % k]
for j in GD[k]:
kmenu.append(j[1])
kmenu = "|".join(kmenu)
KEYMENUS.append(kmenu)
LABELS.append(k)
if FREEKEY_IDX < 0:
FREEKEY_IDX = LABELS.index('Other')
length = len(KEYMENUS)
BEVT_KEYMENU = range(1, length + 1)
BUT_KEYMENU = range(length)
# for theme colors:
def float_colors(cols):
return map(lambda x: x / 255.0, cols)
class Config:
def __init__(self, key, has_group = True):
global DISK_UPDATE
self.key = key
self.has_group = has_group
self.name = key
self.fromdisk = HasConfigData(key) & BPY_KEY_IN_FILE
if not self.fromdisk: DISK_UPDATE = False
else: DISK_UPDATE = True
self.origdata = Registry.GetKey(key, True)
data = self.data = self.origdata.copy()
if not data:
Draw.PupMenu('ERROR: couldn\'t find requested data')
self.data = None
return
keys = data.keys()
nd = {}
for k in keys:
nd[k.lower()] = k
if nd.has_key('tooltips'):
ndval = nd['tooltips']
self.tips = data[ndval]
data.pop(ndval)
else: self.tips = 0
if nd.has_key('limits'):
ndval = nd['limits']
self.limits = data[ndval]
data.pop(ndval)
else: self.limits = 0
if self.has_group:
scriptname = key
if not scriptname.endswith('.py'):
scriptname = "%s.py" % scriptname
elif nd.has_key('script'):
ndval = nd['script']
scriptname = data[ndval]
data.pop(ndval)
if not scriptname.endswith('.py'):
scriptname = "%s.py" % scriptname
else: scriptname = None
self.scriptname = scriptname
self.sort()
def needs_update(self): # check if user changed data
data = self.data
new = self.sorteddata
for vartype in new.keys():
for i in new[vartype]:
if data[i[0]] != i[1]: return 1
return 0 # no changes
def update(self): # update original key
global DISK_UPDATE
data = self.data
odata = self.origdata
new = self.sorteddata
for vartype in new.keys():
for i in new[vartype]:
if data[i[0]] != i[1]: data[i[0]] = i[1]
if odata[i[0]] != i[1]: odata[i[0]] = i[1]
if DISK_UPDATE: Registry.SetKey(self.key, odata, True)
def delete(self):
global DISK_UPDATE
delmsg = 'OK?%t|Delete key from memory'
if DISK_UPDATE:
delmsg = "%s and from disk" % delmsg
if Draw.PupMenu(delmsg) == 1:
Registry.RemoveKey(self.key, DISK_UPDATE)
return True
return False
def revert(self): # revert to original key
data = self.data
new = self.sorteddata
for vartype in new.keys():
for i in new[vartype]:
if data[i[0]] != i[1]: i[1] = data[i[0]]
def sort(self): # create a new dict with types as keys
global ACCEPTED_TYPES, BUT_TYPES
data = self.data
datatypes = {}
keys = [k for k in data.keys() if k[0] != '_']
for k in keys:
val = data[k]
tval = type(val)
if tval not in ACCEPTED_TYPES: continue
if not datatypes.has_key(tval):
datatypes[tval] = []
datatypes[type(val)].append([k, val])
if datatypes.has_key(unicode):
if not datatypes.has_key(str): datatypes[str] = datatypes[unicode]
else:
for i in datatypes[unicode]: datatypes[str].append(i)
datatypes.pop(unicode)
for k in datatypes.keys():
dk = datatypes[k]
dk.sort()
dk.reverse()
BUT_TYPES[k] = range(len(dk))
self.sorteddata = datatypes
# GUI:
# gui callbacks:
def gui(): # drawing the screen
global SCREEN, START_SCREEN, CONFIG_SCREEN, KEYMENUS, LABELS
global BEVT_KEYMENU, BUT_KEYMENU, CFGKEY
global BUT_TYPES, SCROLL_DOWN, VARS_NUM
WIDTH, HEIGHT = Window.GetAreaSize()
theme = Theme.Get()[0]
tui = theme.get('ui')
ttxt = theme.get('text')
COL_BG = float_colors(ttxt.back)
COL_TXT = ttxt.text
COL_TXTHI = ttxt.text_hi
BGL.glClearColor(COL_BG[0],COL_BG[1],COL_BG[2],COL_BG[3])
BGL.glClear(BGL.GL_COLOR_BUFFER_BIT)
BGL.glColor3ub(COL_TXT[0],COL_TXT[1], COL_TXT[2])
if SCREEN == START_SCREEN:
x = 10
y = 10
h = 20
w = 90
BGL.glRasterPos2i(x, y)
Draw.Text('Select a configuration key to access it. Press Q or ESC to leave.')
km_len = len(KEYMENUS)
km_columns = (WIDTH - x) / w
if km_columns == 0: km_rows = km_len
else:
km_rows = km_len / km_columns
if (km_len % km_columns): km_rows += 1
if km_rows == 0: km_rows = 1
ystart = y + 2*h*km_rows
if ystart > (HEIGHT - 70): ystart = HEIGHT - 70
y = ystart
column = 1
for i, km in enumerate(KEYMENUS):
column += 1
BGL.glRasterPos2i(x + 2, y + h + 5)
Draw.Text(LABELS[i])
BUT_KEYMENU[i] = Draw.Menu(km, BEVT_KEYMENU[i],
x, y, w - 10, h, 0, 'Choose a key to access its configuration data')
if column > km_columns:
column = 1
y -= 2*h
if y < 35: break
x = 10
else: x += w
x = 10
y = 50 + ystart
BGL.glColor3ub(COL_TXTHI[0], COL_TXTHI[1], COL_TXTHI[2])
BGL.glRasterPos2i(x, y)
Draw.Text('Scripts Configuration Editor')
Draw.PushButton('help', BEVT_HELP, x, 22, 45, 16,
'View help information about this script (hotkey: H)')
elif SCREEN == CONFIG_SCREEN:
x = y = 10
h = 18
data = CFGKEY.sorteddata
tips = CFGKEY.tips
fromdisk = CFGKEY.fromdisk
limits = CFGKEY.limits
VARS_NUM = 0
for k in data.keys():
VARS_NUM += len(data[k])
lines = VARS_NUM + 5 # to account for header and footer
y = lines*h
if y > HEIGHT - 20: y = HEIGHT - 20
BGL.glColor3ub(COL_TXTHI[0],COL_TXTHI[1], COL_TXTHI[2])
BGL.glRasterPos2i(x, y)
Draw.Text('Scripts Configuration Editor')
y -= 20
BGL.glColor3ub(COL_TXT[0],COL_TXT[1], COL_TXT[2])
txtsize = 10
if HEIGHT < lines*h:
BGL.glRasterPos2i(10, 5)
txtsize += Draw.Text('Arrow keys or mouse wheel to scroll, ')
BGL.glRasterPos2i(txtsize, 5)
Draw.Text('Q or ESC to return.')
BGL.glRasterPos2i(x, y)
Draw.Text('Key: "%s"' % CFGKEY.name)
bh = 16
bw = 45
by = 16
i = -1
if CFGKEY.scriptname:
i = 0
Draw.PushButton('help', BEVT_HELP, x, by, bw, bh,
'Show documentation for the script that owns this key (hotkey: H)')
Draw.PushButton('back', BEVT_BACK, x + (1+i)*bw, by, bw, bh,
'Back to config keys selection screen (hotkey: ESC)')
Draw.PushButton('exit', BEVT_EXIT, x + (2+i)*bw, by, bw, bh,
'Exit from Scripts Config Editor (hotkey: Q)')
Draw.PushButton('revert', BEVT_CANCEL, x + (3+i)*bw, by, bw, bh,
'Revert data to original values (hotkey: U)')
Draw.PushButton('apply', BEVT_APPLY, x + (4+i)*bw, by, bw, bh,
'Apply changes, if any (hotkey: ENTER)')
delmsg = 'Delete this data key from memory'
if fromdisk: delmsg = "%s and from disk" % delmsg
Draw.PushButton('delete', BEVT_DEL, x + (5+i)*bw, by, bw, bh,
'%s (hotkey: DELETE)' % delmsg)
if fromdisk:
Draw.Toggle("file", BEVT_DISK, x + 3 + (6+i)*bw, by, bw, bh, DISK_UPDATE,
'Update also the file where this config key is stored')
i = -1
top = -1
y -= 20
yend = 30
if data.has_key(bool) and y > 0:
lst = data[bool]
for l in lst:
top += 1
i += 1
if top < SCROLL_DOWN: continue
y -= h
if y < yend: break
w = 20
tog = data[bool][i][1]
if tips and tips.has_key(l[0]): tooltip = tips[l[0]]
else: tooltip = "click to toggle"
BUT_TYPES[bool][i] = Draw.Toggle("", BEVT_BOOL + i,
x, y, w, h, tog, tooltip)
BGL.glRasterPos2i(x + w + 3, y + 5)
Draw.Text(l[0].lower().replace('_', ' '))
i = -1
y -= 5
if data.has_key(int) and y > 0:
lst = data[int]
for l in lst:
w = 70
top += 1
i += 1
if top < SCROLL_DOWN: continue
y -= h
if y < yend: break
val = data[int][i][1]
if limits: min, max = limits[l[0]]
else: min, max = 0, 10
if tips and tips.has_key(l[0]): tooltip = tips[l[0]]
else: tooltip = "click / drag to change"
BUT_TYPES[int][i] = Draw.Number("", BEVT_INT + i,
x, y, w, h, val, min, max, tooltip)
BGL.glRasterPos2i(x + w + 3, y + 3)
Draw.Text(l[0].lower().replace('_', ' '))
i = -1
y -= 5
if data.has_key(float) and y > 0:
lst = data[float]
for l in lst:
w = 70
top += 1
i += 1
if top < SCROLL_DOWN: continue
y -= h
if y < yend: break
val = data[float][i][1]
if limits: min, max = limits[l[0]]
else: min, max = 0.0, 1.0
if tips and tips.has_key(l[0]): tooltip = tips[l[0]]
else: tooltip = "click and drag to change"
BUT_TYPES[float][i] = Draw.Number("", BEVT_FLOAT + i,
x, y, w, h, val, min, max, tooltip)
BGL.glRasterPos2i(x + w + 3, y + 3)
Draw.Text(l[0].lower().replace('_', ' '))
i = -1
y -= 5
if data.has_key(str) and y > 0:
lst = data[str]
for l in lst:
top += 1
i += 1
if top < SCROLL_DOWN: continue
y -= h
if y < yend: break
name = l[0].lower()
is_dir = is_file = False
if name.find('_dir', -4) > 0: is_dir = True
elif name.find('_file', -5) > 0: is_file = True
w = WIDTH - 20
wbrowse = 50
if is_dir and w > wbrowse: w -= wbrowse
if tips and tips.has_key(l[0]): tooltip = tips[l[0]]
else: tooltip = "click to write a new string"
name = name.replace('_',' ') + ': '
if len(l[1]) > MAX_STR_LEN:
l[1] = l[1][:MAX_STR_LEN]
BUT_TYPES[str][i] = Draw.String(name, BEVT_STR + i,
x, y, w, h, l[1], MAX_STR_LEN, tooltip)
if is_dir:
Draw.PushButton('browse', BEVT_BROWSEDIR + i, x+w+1, y, wbrowse, h,
'click to open a file selector (pick any file in the desired dir)')
elif is_file:
Draw.PushButton('browse', BEVT_BROWSEFILE + i, x + w + 1, y, 50, h,
'click to open a file selector')
def fit_scroll():
global SCROLL_DOWN, VARS_NUM
max = VARS_NUM - 1 # so last item is always visible
if SCROLL_DOWN > max:
SCROLL_DOWN = max
elif SCROLL_DOWN < 0:
SCROLL_DOWN = 0
def event(evt, val): # input events
global SCREEN, START_SCREEN, CONFIG_SCREEN
global SCROLL_DOWN, CFGKEY
if not val: return
if evt == Draw.ESCKEY:
if SCREEN == START_SCREEN: Draw.Exit()
else:
if CFGKEY.needs_update():
if Draw.PupMenu('UPDATE?%t|Data was changed') == 1:
CFGKEY.update()
SCREEN = START_SCREEN
SCROLL_DOWN = 0
Draw.Redraw()
return
elif evt == Draw.QKEY:
if SCREEN == CONFIG_SCREEN and CFGKEY.needs_update():
if Draw.PupMenu('UPDATE?%t|Data was changed') == 1:
CFGKEY.update()
Draw.Exit()
return
elif evt == Draw.HKEY:
if SCREEN == START_SCREEN: show_help()
elif CFGKEY.scriptname: show_help(CFGKEY.scriptname)
return
elif SCREEN == CONFIG_SCREEN:
if evt in [Draw.DOWNARROWKEY, Draw.WHEELDOWNMOUSE]:
SCROLL_DOWN += 1
fit_scroll()
elif evt in [Draw.UPARROWKEY, Draw.WHEELUPMOUSE]:
SCROLL_DOWN -= 1
fit_scroll()
elif evt == Draw.UKEY:
if CFGKEY.needs_update():
CFGKEY.revert()
elif evt == Draw.RETKEY or evt == Draw.PADENTER:
if CFGKEY.needs_update():
CFGKEY.update()
elif evt == Draw.DELKEY:
if CFGKEY.delete():
reset()
init_data()
SCREEN = START_SCREEN
SCROLL_DOWN = 0
else: return
Draw.Redraw()
def button_event(evt): # gui button events
global SCREEN, START_SCREEN, CONFIG_SCREEN, CFGKEY, DISK_UPDATE
global BEVT_KEYMENU, BUT_KEYMENU, BUT_TYPES, SCROLL_DOWN, GD, INDEX
global BEVT_EXIT, BEVT_BACK, BEVT_APPLY, BEVT_CANCEL, BEVT_HELP, FREEKEY_IDX
if SCREEN == START_SCREEN:
for e in BEVT_KEYMENU:
if evt == e:
index = e - 1
k = BUT_KEYMENU[index].val - 1
CFGKEY = Config(GD[LABELS[index]][k][0], index != FREEKEY_IDX)
if CFGKEY.data:
SCREEN = CONFIG_SCREEN
Draw.Redraw()
return
if evt == BEVT_EXIT:
Draw.Exit()
elif evt == BEVT_HELP:
show_help()
return
elif SCREEN == CONFIG_SCREEN:
datatypes = CFGKEY.sorteddata
if evt >= BEVT_BROWSEFILE:
INDEX = evt - BEVT_BROWSEFILE
Window.FileSelector(fs_file_callback, 'Choose file')
elif evt >= BEVT_BROWSEDIR:
INDEX = evt - BEVT_BROWSEDIR
Window.FileSelector(fs_dir_callback, 'Choose any file')
elif evt >= BEVT_STR:
var = BUT_TYPES[str][evt - BEVT_STR].val
datatypes[str][evt - BEVT_STR][1] = var
elif evt >= BEVT_FLOAT:
var = BUT_TYPES[float][evt - BEVT_FLOAT].val
datatypes[float][evt - BEVT_FLOAT][1] = var
elif evt >= BEVT_INT:
var = BUT_TYPES[int][evt - BEVT_INT].val
datatypes[int][evt - BEVT_INT][1] = var
elif evt >= BEVT_BOOL:
var = datatypes[bool][evt - BEVT_BOOL][1]
if var == True: var = False
else: var = True
datatypes[bool][evt - BEVT_BOOL][1] = var
elif evt == BEVT_BACK:
if SCREEN == CONFIG_SCREEN:
SCREEN = START_SCREEN
SCROLL_DOWN = 0
Draw.Redraw()
elif evt == BEVT_EXIT:
if CFGKEY.needs_update():
if Draw.PupMenu('UPDATE?%t|Data was changed') == 1:
CFGKEY.update()
Draw.Exit()
return
elif evt == BEVT_APPLY:
if CFGKEY.needs_update():
CFGKEY.update()
elif evt == BEVT_CANCEL:
if CFGKEY.needs_update():
CFGKEY.revert()
elif evt == BEVT_DEL:
if CFGKEY.delete():
reset()
init_data()
SCREEN = START_SCREEN
SCROLL_DOWN = 0
elif evt == BEVT_DISK:
if DISK_UPDATE: DISK_UPDATE = False
else: DISK_UPDATE = True
elif evt == BEVT_HELP:
show_help(CFGKEY.scriptname)
return
else:
return
Draw.Redraw()
# End of definitions
KEYS = get_keys()
if not KEYS:
Draw.PupMenu("NO DATA: please read this help screen")
Blender.ShowHelp('config.py')
else:
fill_scripts_dict()
init_data()
Draw.Register(gui, event, button_event)

View File

@@ -1,861 +0,0 @@
#!BPY
"""
Name: 'Interactive Python Console'
Blender: 245
Group: 'System'
Tooltip: 'Interactive Python Console'
"""
__author__ = "Campbell Barton aka ideasman42"
__url__ = ["www.blender.org", "blenderartists.org", "www.python.org"]
__bpydoc__ = """\
This is an interactive console, similar to Python's own command line interpreter. Since it is embedded in Blender, it has access to all Blender Python modules.
Those completely new to Python are recommended to check the link button above
that points to its official homepage, with news, downloads and documentation.
Usage:<br>
Type your code and hit "Enter" to get it executed.<br>
- Right mouse click: Console Menu (Save output, etc);<br>
- Mousewheel: Scroll text
- Arrow keys: command history and cursor;<br>
- Shift + Backspace: Backspace whole word;<br>
- Shift + Arrow keys: jump words;<br>
- Ctrl + (+/- or mousewheel): Zoom text size;<br>
- Ctrl + Enter: auto compleate based on variable names and modules loaded -- multiple choices popup a menu;<br>
- Shift + Enter: multiline functions -- delays executing code until only Enter is pressed.
"""
# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
import Blender
import bpy
from Blender import *
import sys as python_sys
import StringIO
# Constants
__DELIMETERS__ = '. ,=+-*/%<>&~][{}():\t'
__VARIABLE_DELIMETERS__ = ' ,=+-*/%<>&~{}():\t'
__LINE_HISTORY__ = 500
global __FONT_SIZE__
__FONT_SIZES__ = ( ('tiny', 10), ('small', 12), ('normalfix', 14), ('large', 16) )
__FONT_SIZE__ = 2 # index for the list above, normal default.
global __CONSOLE_LINE_OFFSET__
__CONSOLE_LINE_OFFSET__ = 0
cmdBuffer = [] # dosnt need to be global
'''
# Generic Blender functions
def getActScriptWinRect():
area = Window.GetAreaSize()
area = (area[0]-1, area[1]-1)
for scrInfo in Window.GetScreenInfo(Window.Types['SCRIPT'], 'win', ''):
if scrInfo['vertices'][2]-scrInfo['vertices'][0] == area[0]:
if scrInfo['vertices'][3]-scrInfo['vertices'][1] == area[1]:
return scrInfo['vertices']
return None
'''
# menuText, # per group
def PupMenuLess(menu, groupSize=35):
more = [' more...']
less = [' less...']
menuList= menu.split('|')
# No Less Needed, just call.
if len(menuList) < groupSize:
return Draw.PupMenu(menu)
title = menuList[0].split('%t')[0]
# Split the list into groups
menuGroups = [[]]
for li in menuList[1:]:
if len(menuGroups[-1]) < groupSize:
menuGroups[-1].append(li)
else:
menuGroups.append([li])
# Stores teh current menu group we are looking at
groupIdx = 0
while 1:
# Give us a title with the menu number
numTitle = [ ' '.join([title, str(groupIdx + 1), 'of', str(len(menuGroups)), '%t'])]
if groupIdx == 0:
menuString = '|'.join(numTitle + menuGroups[groupIdx] + more)
elif groupIdx == len(menuGroups)-1:
menuString = '|'.join(numTitle + less + menuGroups[groupIdx])
else: # In the middle somewhere so Show a more and less
menuString = '|'.join(numTitle + less + menuGroups[groupIdx] + more)
result = Draw.PupMenu(menuString)
# User Exit
if result == -1:
return -1
if groupIdx == 0: # First menu
if result-1 < groupSize:
return result
else: # must be more
groupIdx +=1
elif groupIdx == len(menuGroups): # Last Menu
if result == 1: # Must be less
groupIdx -= 1
else: # Must be a choice
return result + (groupIdx*groupSize)
else:
if result == 1: # Must be less
groupIdx -= 1
elif result-2 == groupSize:
groupIdx +=1
else:
return result - 1 + (groupIdx*groupSize)
# Use newstyle classes, Im not bothering with inheretence
# but slots are faster.
class cmdLine(object):
__slots__ = [\
'cmd', # is the command string, or any other message
'type',# type: 0:user input 1:program feedback 2:error message. 3:option feedback
'exe' # 0- not yet executed 1:executed
]
def __init__(self, cmd, type, exe):
self.cmd = cmd
self.type = type
self.exe = exe
# Include external file with internal namespace
def include(filename):
file = open(filename, 'r')
filedata = file.read()
file.close()
return compile(filedata, filename, 'exec')
# Writes command line data to a blender text file.
def writeCmdData(type):
newText = Text.New('command_output.py', 1)
if type == 3: newText.write('\n'.join( [ myCmd.cmd for myCmd in cmdBuffer ] ))
else: newText.write('\n'.join( [ myCmd.cmd for myCmd in cmdBuffer if myCmd.type is type] ))
Draw.PupMenu('%s written' % newText.name)
def insertCmdData():
texts = list(bpy.data.texts)
textNames = [tex.name for tex in texts]
if textNames:
choice = Draw.PupMenu('|'.join(textNames))
if choice != -1:
text = texts[choice-1]
# Add the text!
for l in text.asLines():
cmdBuffer.append(cmdLine('%s ' % l, 0, 0))
Draw.Redraw()
COLLECTED_VAR_NAMES = {} # a list of keys, each key has a list of absolute paths
# Pain and simple recursice dir(), accepts a string
unused_types = str, dict, list, float, int, str, type, tuple, type(dir), type(None)
def rdir(dirString, depth=0):
#print ' ' * depth, dirString
# MAX DEPTH SET HERE
if depth > 5:
# print 'maxdepoth reached.'
return
global COLLECTED_VAR_NAMES
dirStringSplit = dirString.split('.')
exec('value=' + dirString)
if type(value) in unused_types:
# print 'bad type'
return
dirList = dir(value)
for dirItem in dirList:
if dirItem.startswith('_'):
continue
dirData = None
try:
# Rare cases this can mess up, material.shader was a problem.
exec('dirData = %s.%s' % (dirString, dirItem))
#print dirData
except:
# Dont bother with this data.
continue
#print 'HEY', dirData, dirItem
#if type(dirItem) != str:
# print dirItem, type(dirItem)
if dirItem not in COLLECTED_VAR_NAMES: # .keys()
COLLECTED_VAR_NAMES[dirItem] = []
# Add the string
# splitD = dirString.split('"')[-2]
# Example of dirString
# __CONSOLE_VAR_DICT__["Main"].scenes.active.render
# Works but can be faster
# splitD = dirString.replace('__CONSOLE_VAR_DICT__["', '').replace('"]', '')
splitD = dirString[22:].replace('"]', '')
if splitD not in COLLECTED_VAR_NAMES[dirItem]:
# print dirItem, dirString, splitD,
COLLECTED_VAR_NAMES[dirItem].append(splitD)
# Stops recursice stuff, overlooping
#print type(dirItem)
#if type(dirData) == types.ClassType or \
# type(dirData) == types.ModuleType:
type_dirData = type(dirData)
if type_dirData not in unused_types:
# print type(dirData), dirItem
# Dont loop up dirs for strings ints etc.
if dirItem not in dirStringSplit:
rdir( '%s.%s' % (dirString, dirItem), depth+1)
'''
elif depth == 0: # Add local variables
# print type(dirData), dirItem
# Dont loop up dirs for strings ints etc.
if dirItem not in dirStringSplit:
rdir( '%s.%s' % (dirString, dirItem), depth+1)
'''
def recursive_dir():
global COLLECTED_VAR_NAMES
for name in __CONSOLE_VAR_DICT__: # .keys()
if not name.startswith('_'): # Dont pick names like __name__
rdir('__CONSOLE_VAR_DICT__["%s"]' % name)
#print COLLECTED_VAR_NAMES
COLLECTED_VAR_NAMES[name] = ['']
return COLLECTED_VAR_NAMES
# Runs the code line(s) the user has entered and handle errors
# As well as feeding back the output into the blender window.
def runUserCode(__USER_CODE_STRING__):
global __CONSOLE_VAR_DICT__ # We manipulate the variables here. loading and saving from localspace to this global var.
# Open A File like object to write all output to, that would useually be printed.
python_sys.stdout.flush() # Get rid of whatever came before
__FILE_LIKE_STRING__ = StringIO.StringIO() # make a new file like string, this saves up from making a file.
__STD_OUTPUT__ = python_sys.stdout # we need to store the normal output.
python_sys.stdout=__FILE_LIKE_STRING__ # Now anything printed will be written to the file like string.
# Try and run the user entered line(s)
try:
# Load all variabls from global dict to local space.
__TMP_VAR_NAME__ = __TMP_VAR__ = '' # so as not to raise an error when del'ing
for __TMP_VAR_NAME__, __TMP_VAR__ in __CONSOLE_VAR_DICT__.items():
exec('%s%s' % (__TMP_VAR_NAME__,'=__TMP_VAR__'))
del __TMP_VAR_NAME__
del __TMP_VAR__
# Now all the vars are loaded, execute the code. # Newline thanks to phillip,
exec(compile(__USER_CODE_STRING__, 'blender_cmd.py', 'single')) #exec(compile(__USER_CODE_STRING__, 'blender_cmd.py', 'exec'))
# Flush global dict, allow the user to remove items.
__CONSOLE_VAR_DICT__ = {}
__TMP_VAR_NAME__ = '' # so as not to raise an error when del'ing
# Write local veriables to global __CONSOLE_VAR_DICT__
for __TMP_VAR_NAME__ in dir():
if __TMP_VAR_NAME__ != '__FILE_LIKE_STRING__' and\
__TMP_VAR_NAME__ != '__STD_OUTPUT__' and\
__TMP_VAR_NAME__ != '__TMP_VAR_NAME__' and\
__TMP_VAR_NAME__ != '__USER_CODE_STRING__':
# Execute the local > global coversion.
exec('%s%s' % ('__CONSOLE_VAR_DICT__[__TMP_VAR_NAME__]=', __TMP_VAR_NAME__))
del __TMP_VAR_NAME__
except: # Prints the REAL exception.
error = '%s: %s' % (python_sys.exc_type, python_sys.exc_value)
for errorLine in error.split('\n'):
cmdBuffer.append(cmdLine(errorLine, 2, None)) # new line to type into
python_sys.stdout = __STD_OUTPUT__ # Go back to output to the normal blender console
# Copy all new output to cmdBuffer
__FILE_LIKE_STRING__.seek(0) # the readline function requires that we go back to the start of the file.
for line in __FILE_LIKE_STRING__.readlines():
cmdBuffer.append(cmdLine(line, 1, None))
cmdBuffer.append(cmdLine(' ', 0, 0)) # new line to type into
python_sys.stdout=__STD_OUTPUT__
__FILE_LIKE_STRING__.close()
#------------------------------------------------------------------------------#
# event handling code #
#------------------------------------------------------------------------------#
def handle_event(evt, val):
# Insert Char into the cammand line
def insCh(ch): # Instert a char
global cursor
# Later account for a cursor variable
cmdBuffer[-1].cmd = ('%s%s%s' % ( cmdBuffer[-1].cmd[:cursor], ch, cmdBuffer[-1].cmd[cursor:]))
#------------------------------------------------------------------------------#
# Define Complex Key Actions #
#------------------------------------------------------------------------------#
def actionEnterKey():
global histIndex, cursor
def getIndent(string):
# Gather white space to add in the previous line
# Ignore the last char since its padding.
whiteSpace = ''
#for i in range(len(cmdBuffer[-1].cmd)):
for i in xrange(len(string)-1):
if cmdBuffer[-1].cmd[i] == ' ' or cmdBuffer[-1].cmd[i] == '\t':
whiteSpace += string[i]
else:
break
return whiteSpace
# Autocomplete
if Window.GetKeyQualifiers() & Window.Qual.CTRL:
actionAutoCompleate()
return
# Are we in the middle of a multiline part or not?
# try be smart about it
if cmdBuffer[-1].cmd.split('#')[0].rstrip().endswith(':'):
# : indicates an indent is needed
cmdBuffer.append(cmdLine('\t%s ' % getIndent(cmdBuffer[-1].cmd), 0, 0))
print ': indicates an indent is needed'
elif cmdBuffer[-1].cmd[0] in [' ', '\t'] and len(cmdBuffer[-1].cmd) > 1 and cmdBuffer[-1].cmd.split():
# white space at the start means he havnt finished the multiline.
cmdBuffer.append(cmdLine('%s ' % getIndent(cmdBuffer[-1].cmd), 0, 0))
print 'white space at the start means he havnt finished the multiline.'
elif Window.GetKeyQualifiers() & Window.Qual.SHIFT:
# Crtl forces multiline
cmdBuffer.append(cmdLine('%s ' % getIndent(cmdBuffer[-1].cmd), 0, 0))
print 'Crtl forces multiline'
else: # Execute multiline code block
# Multiline code will still run with 1 line,
multiLineCode = ['if 1:'] # End of the multiline first.
# Seek the start of the file multiline
i = 1
while cmdBuffer[-i].exe == 0:
i+=1
while i > 1:
i-=1
if cmdBuffer[-i].cmd == ' ':# Tag as an output type so its not used in the key history
cmdBuffer[-i].type = 1
else: # Tab added at the start for added if 1: statement
multiLineCode.append('\t%s' % cmdBuffer[-i].cmd )
# Mark as executed
cmdBuffer[-i].exe = 1
multiLineCode.append('\tpass') # reverse will make this the start.
# Dubug, print the code that is executed.
#for m in multiLineCode: print m
runUserCode('\n'.join(multiLineCode))
# Clear the output based on __LINE_HISTORY__
if len(cmdBuffer) > __LINE_HISTORY__:
cmdBuffer[:__LINE_HISTORY__] = []
histIndex = cursor = -1 # Reset cursor and history
def actionUpKey():
global histIndex
if abs(histIndex)+1 >= len(cmdBuffer):
histIndex = -1
# When wrapping allow 1 plank lines
if cmdBuffer[-1].cmd != ' ':
cmdBuffer[-1].cmd = ' '
return
histIndex_orig = histIndex
histIndex -= 1
while (cmdBuffer[histIndex].type != 0 and abs(histIndex) < len(cmdBuffer)) or \
( cmdBuffer[histIndex].cmd == cmdBuffer[histIndex_orig].cmd):
histIndex -= 1
if cmdBuffer[histIndex].type == 0: # we found one
cmdBuffer[-1].cmd = cmdBuffer[histIndex].cmd
def actionDownKey():
global histIndex
if histIndex >= -2:
histIndex = -len(cmdBuffer)
# When wrapping allow 1 plank lines
if cmdBuffer[-1].cmd != ' ':
cmdBuffer[-1].cmd = ' '
return
histIndex_orig = histIndex
histIndex += 1
while (cmdBuffer[histIndex].type != 0 and histIndex != -2) or \
( cmdBuffer[histIndex].cmd == cmdBuffer[histIndex_orig].cmd):
histIndex += 1
if cmdBuffer[histIndex].type == 0: # we found one
cmdBuffer[-1].cmd = cmdBuffer[histIndex].cmd
def actionRightMouse():
global __FONT_SIZE__
choice = Draw.PupMenu('Console Menu%t|Write Input Data (white)|Write Output Data (blue)|Write Error Data (red)|Write All Text|%l|Insert Blender text|%l|Font Size|%l|Clear Output|Quit')
if choice == 1:
writeCmdData(0) # type 0 user
elif choice == 2:
writeCmdData(1) # type 1 user output
elif choice == 3:
writeCmdData(2) # type 2 errors
elif choice == 4:
writeCmdData(3) # All
elif choice == 6:
insertCmdData() # Insert text from Blender and run it.
elif choice == 8:
# Fontsize.
font_choice = Draw.PupMenu('Font Size%t|Large|Normal|Small|Tiny')
if font_choice != -1:
if font_choice == 1:
__FONT_SIZE__ = 3
elif font_choice == 2:
__FONT_SIZE__ = 2
elif font_choice == 3:
__FONT_SIZE__ = 1
elif font_choice == 4:
__FONT_SIZE__ = 0
Draw.Redraw()
elif choice == 10: # Clear all output
cmdBuffer[:] = [cmd for cmd in cmdBuffer if cmd.type == 0] # keep user input
Draw.Redraw()
elif choice == 11: # Exit
Draw.Exit()
# Auto compleating, quite complex- use recutsice dir for the moment.
def actionAutoCompleate(): # Ctrl + Tab
if not cmdBuffer[-1].cmd[:cursor].split():
return
RECURSIVE_DIR = recursive_dir()
# get last name of user input
editVar = cmdBuffer[-1].cmd[:cursor]
# Split off spaces operators etc from the staryt of the command so we can use the startswith function.
for splitChar in __VARIABLE_DELIMETERS__:
editVar = editVar[:-1].split(splitChar)[-1] + editVar[-1]
# Now we should have the var by its self
if editVar:
possibilities = []
for __TMP_VAR_NAME__ in RECURSIVE_DIR: #.keys():
#print '\t', __TMP_VAR_NAME__
if __TMP_VAR_NAME__ == editVar:
# print 'ADITVAR IS A VAR'
pass
'''
elif __TMP_VAR_NAME__.startswith( editVar ):
print __TMP_VAR_NAME__, 'aaa'
possibilities.append( __TMP_VAR_NAME__ )
'''
possibilities.append( __TMP_VAR_NAME__ )
if len(possibilities) == 1:
cmdBuffer[-1].cmd = ('%s%s%s' % (cmdBuffer[-1].cmd[:cursor - len(editVar)], possibilities[0], cmdBuffer[-1].cmd[cursor:]))
elif possibilities: # If its not just []
# -1 with insert is the second last.
# Text choice
#cmdBuffer.insert(-1, cmdLine('options: %s' % ' '.join(possibilities), 3, None))
menuList = [] # A lits of tuples- ABSOLUTE, RELATIVE
for __TMP_VAR_NAME__ in possibilities:
for usage in RECURSIVE_DIR[__TMP_VAR_NAME__]:
# Account for non absolute (variables for eg.)
if usage: # not ''
absName = '%s.%s' % (usage, __TMP_VAR_NAME__)
if __TMP_VAR_NAME__.startswith(editVar):
menuList.append( # Used for names and can be entered when pressing shift.
(absName, # Absolute name
__TMP_VAR_NAME__) # Relative name, non shift
)
#else:
# if absName.find(editVar) != -1:
# menuList.append((__TMP_VAR_NAME__, __TMP_VAR_NAME__)) # Used for names and can be entered when pressing shift.
# No items to display? no menu
if not menuList:
return
menuList.sort()
choice = PupMenuLess( # Menu for the user to choose the autocompleate
'Choices (Shift for local name, Ctrl for Docs)%t|' + # Title Text
'|'.join(['%s, %s' % m for m in menuList])) # Use Absolute names m[0]
if choice != -1:
if Window.GetKeyQualifiers() & Window.Qual.CTRL: # Help
cmdBuffer[-1].cmd = ('help(%s%s) ' % (cmdBuffer[-1].cmd[:cursor - len(editVar)], menuList[choice-1][0]))
elif Window.GetKeyQualifiers() & Window.Qual.SHIFT: # Put in the long name
cmdBuffer[-1].cmd = ('%s%s%s' % (cmdBuffer[-1].cmd[:cursor - len(editVar)], menuList[choice-1][1], cmdBuffer[-1].cmd[cursor:]))
else: # Only paste in the Short name
cmdBuffer[-1].cmd = ('%s%s%s' % (cmdBuffer[-1].cmd[:cursor - len(editVar)], menuList[choice-1][0], cmdBuffer[-1].cmd[cursor:]))
else:
# print 'NO EDITVAR'
return
# ------------------end------------------ #
# Quit from menu only
#if (evt == Draw.ESCKEY and not val):
# Draw.Exit()
if evt == Draw.MOUSEX or evt == Draw.MOUSEY: # AVOID TOO MANY REDRAWS.
return
global cursor
global histIndex
global __FONT_SIZE__
global __CONSOLE_LINE_OFFSET__
ascii = Blender.event
resetScroll = True
#------------------------------------------------------------------------------#
# key codes and key handling #
#------------------------------------------------------------------------------#
# UP DOWN ARROW KEYS, TO TRAVERSE HISTORY
if (evt == Draw.UPARROWKEY and val): actionUpKey()
elif (evt == Draw.DOWNARROWKEY and val): actionDownKey()
elif (evt == Draw.RIGHTARROWKEY and val):
if Window.GetKeyQualifiers() & Window.Qual.SHIFT:
wordJump = False
newCursor = cursor+1
while newCursor<0:
if cmdBuffer[-1].cmd[newCursor] not in __DELIMETERS__:
newCursor+=1
else:
wordJump = True
break
if wordJump: # Did we find a new cursor pos?
cursor = newCursor
else:
cursor = -1 # end of line
else:
cursor +=1
if cursor > -1:
cursor = -1
elif (evt == Draw.LEFTARROWKEY and val):
if Window.GetKeyQualifiers() & Window.Qual.SHIFT:
wordJump = False
newCursor = cursor-1
while abs(newCursor) < len(cmdBuffer[-1].cmd):
if cmdBuffer[-1].cmd[newCursor] not in __DELIMETERS__ or\
newCursor == cursor:
newCursor-=1
else:
wordJump = True
break
if wordJump: # Did we find a new cursor pos?
cursor = newCursor
else:
cursor = -len(cmdBuffer[-1].cmd) # Start of line
else:
if len(cmdBuffer[-1].cmd) > abs(cursor):
cursor -=1
elif (evt == Draw.HOMEKEY and val):
cursor = -len(cmdBuffer[-1].cmd)
elif (evt == Draw.ENDKEY and val):
cursor = -1
elif (evt == Draw.TABKEY and val):
insCh('\t')
elif (evt == Draw.BACKSPACEKEY and val):
if Window.GetKeyQualifiers() & Window.Qual.SHIFT:
i = -1
for d in __DELIMETERS__:
i = max(i, cmdBuffer[-1].cmd[:cursor-1].rfind(d))
if i == -1:
i=0
cmdBuffer[-1].cmd = ('%s%s' % (cmdBuffer[-1].cmd[:i] , cmdBuffer[-1].cmd[cursor:]))
else:
# Normal backspace.
cmdBuffer[-1].cmd = ('%s%s' % (cmdBuffer[-1].cmd[:cursor-1] , cmdBuffer[-1].cmd[cursor:]))
elif (evt == Draw.DELKEY and val) and cursor < -1:
cmdBuffer[-1].cmd = cmdBuffer[-1].cmd[:cursor] + cmdBuffer[-1].cmd[cursor+1:]
cursor +=1
elif ((evt == Draw.RETKEY or evt == Draw.PADENTER) and val):
actionEnterKey()
elif (evt == Draw.RIGHTMOUSE and not val): actionRightMouse(); return
elif (evt == Draw.PADPLUSKEY or evt == Draw.EQUALKEY or evt == Draw.WHEELUPMOUSE) and val and Window.GetKeyQualifiers() & Window.Qual.CTRL:
__FONT_SIZE__ += 1
__FONT_SIZE__ = min(len(__FONT_SIZES__)-1, __FONT_SIZE__)
elif (evt == Draw.PADMINUS or evt == Draw.MINUSKEY or evt == Draw.WHEELDOWNMOUSE) and val and Window.GetKeyQualifiers() & Window.Qual.CTRL:
__FONT_SIZE__ -=1
__FONT_SIZE__ = max(0, __FONT_SIZE__)
elif evt == Draw.WHEELUPMOUSE and val:
__CONSOLE_LINE_OFFSET__ += 1
__CONSOLE_LINE_OFFSET__ = min(len(cmdBuffer)-2, __CONSOLE_LINE_OFFSET__)
resetScroll = False
elif evt == Draw.WHEELDOWNMOUSE and val:
__CONSOLE_LINE_OFFSET__ -= 1
__CONSOLE_LINE_OFFSET__ = max(0, __CONSOLE_LINE_OFFSET__)
resetScroll = False
elif ascii:
insCh(chr(ascii))
else:
return # dont redraw.
# If the user types in anything then scroll to bottom.
if resetScroll:
__CONSOLE_LINE_OFFSET__ = 0
Draw.Redraw()
def draw_gui():
# Get the bounds from ObleGL directly
__CONSOLE_RECT__ = BGL.Buffer(BGL.GL_FLOAT, 4)
BGL.glGetFloatv(BGL.GL_SCISSOR_BOX, __CONSOLE_RECT__)
__CONSOLE_RECT__= __CONSOLE_RECT__.list
# Clear the screen
BGL.glClearColor(0.0, 0.0, 0.0, 1.0)
BGL.glClear(BGL.GL_COLOR_BUFFER_BIT) # use it to clear the color buffer
# Fixed margin. use a margin since 0 margin can be hard to seewhen close to a crt's edge.
margin = 4
# Convenience
FNT_NAME, FNT_HEIGHT = __FONT_SIZES__[__FONT_SIZE__]
# Draw cursor location colour
if __CONSOLE_LINE_OFFSET__ == 0:
cmd2curWidth = Draw.GetStringWidth(cmdBuffer[-1].cmd[:cursor], FNT_NAME)
BGL.glColor3f(0.8, 0.2, 0.2)
if cmd2curWidth == 0:
BGL.glRecti(margin,2,margin+2, FNT_HEIGHT+2)
else:
BGL.glRecti(margin + cmd2curWidth-2,2, margin+cmd2curWidth, FNT_HEIGHT+2)
BGL.glColor3f(1,1,1)
# Draw the set of cammands to the buffer
consoleLineIdx = __CONSOLE_LINE_OFFSET__ + 1
wrapLineIndex = 0
while consoleLineIdx < len(cmdBuffer) and __CONSOLE_RECT__[3] > (consoleLineIdx - __CONSOLE_LINE_OFFSET__) * FNT_HEIGHT:
if cmdBuffer[-consoleLineIdx].type == 0:
BGL.glColor3f(1, 1, 1)
elif cmdBuffer[-consoleLineIdx].type == 1:
BGL.glColor3f(.3, .3, 1)
elif cmdBuffer[-consoleLineIdx].type == 2:
BGL.glColor3f(1.0, 0, 0)
elif cmdBuffer[-consoleLineIdx].type == 3:
BGL.glColor3f(0, 0.8, 0)
else:
BGL.glColor3f(1, 1, 0)
if consoleLineIdx == 1: # user input
BGL.glRasterPos2i(margin, (FNT_HEIGHT * (consoleLineIdx-__CONSOLE_LINE_OFFSET__)) - 8)
Draw.Text(cmdBuffer[-consoleLineIdx].cmd, FNT_NAME)
else: # WRAP
lwid = Draw.GetStringWidth(cmdBuffer[-consoleLineIdx].cmd, FNT_NAME)
if margin + lwid > __CONSOLE_RECT__[2]:
wrapLineList = []
wtext = cmdBuffer[-consoleLineIdx].cmd
wlimit = len(wtext)
chunksz = int(( __CONSOLE_RECT__[2] - margin ) / (lwid / len(wtext)))
lstart = 0
fsize = FNT_NAME
while lstart < wlimit:
lend = min(lstart+chunksz,wlimit)
ttext = wtext[lstart:lend]
while lend < wlimit and Draw.GetStringWidth(ttext, fsize) + margin < __CONSOLE_RECT__[2]:
lend += 1
ttext = wtext[lstart:lend]
while lend > lstart+1 and Draw.GetStringWidth(ttext, fsize) + margin > __CONSOLE_RECT__[2]:
lend -= 1
ttext = wtext[lstart:lend]
wrapLineList.append(ttext)
lstart = lend
# Now we have a list of lines, draw them (OpenGLs reverse ordering requires this odd change)
wrapLineList.reverse()
for wline in wrapLineList:
BGL.glRasterPos2i(margin, (FNT_HEIGHT*((consoleLineIdx-__CONSOLE_LINE_OFFSET__) + wrapLineIndex)) - 8)
Draw.Text(wline, FNT_NAME)
wrapLineIndex += 1
wrapLineIndex-=1 # otherwise we get a silly extra line.
else: # no wrapping.
BGL.glRasterPos2i(margin, (FNT_HEIGHT * ((consoleLineIdx-__CONSOLE_LINE_OFFSET__)+wrapLineIndex)) - 8)
Draw.Text(cmdBuffer[-consoleLineIdx].cmd, FNT_NAME)
consoleLineIdx += 1
# This recieves the event index, call a function from here depending on the event.
def handle_button_event(evt):
pass
# Run the console
__CONSOLE_VAR_DICT__ = {} # Initialize var dict
# Print Startup lines, add __bpydoc__ to the console startup.
for l in __bpydoc__.split('<br>'):
cmdBuffer.append( cmdLine(l, 1, None) )
histIndex = cursor = -1 # How far back from the first letter are we? - in current CMD line, history if for moving up and down lines.
# Autoexec, startup code.
scriptDir = Get('scriptsdir')
console_autoexec = None
if scriptDir:
if not scriptDir.endswith(Blender.sys.sep):
scriptDir += Blender.sys.sep
console_autoexec = '%s%s' % (scriptDir, 'console_autoexec.py')
if not sys.exists(console_autoexec):
# touch the file
try:
open(console_autoexec, 'w').close()
cmdBuffer.append(cmdLine('...console_autoexec.py not found, making new in scripts dir', 1, None))
except:
cmdBuffer.append(cmdLine('...console_autoexec.py could not write, this is ok', 1, None))
scriptDir = None # make sure we only use this for console_autoexec.py
if not sys.exists(console_autoexec):
console_autoexec = None
else:
cmdBuffer.append(cmdLine('...Using existing console_autoexec.py in scripts dir', 1, None))
#-Autoexec---------------------------------------------------------------------#
# Just use the function to jump into local naming mode.
# This is so we can loop through all of the autoexec functions / vars and add them to the __CONSOLE_VAR_DICT__
def include_console(includeFile):
global __CONSOLE_VAR_DICT__ # write autoexec vars to this.
# Execute an external py file as if local
exec(include(includeFile))
def standard_imports():
# Write local to global __CONSOLE_VAR_DICT__ for reuse,
exec('%s%s' % ('__CONSOLE_VAR_DICT__["bpy"]=', 'bpy'))
exec('%s%s' % ('__CONSOLE_VAR_DICT__["Blender"]=', 'Blender'))
for ls in (dir(), dir(Blender)):
for __TMP_VAR_NAME__ in ls:
# Execute the local > global coversion.
exec('%s%s' % ('__CONSOLE_VAR_DICT__[__TMP_VAR_NAME__]=', __TMP_VAR_NAME__))
# Add dummy imports to input so output scripts to a text file work as expected
cmdBuffer.append(cmdLine('import bpy', 0, 1))
cmdBuffer.append(cmdLine('import Blender', 0, 1)) # pretend we have been executed, as we kindof have.
cmdBuffer.append(cmdLine('from Blender import *', 0, 1))
if scriptDir and console_autoexec:
include_console(console_autoexec) # pass the blender module
standard_imports() # import Blender and bpy
#-end autoexec-----------------------------------------------------------------#
# Append new line to write to
cmdBuffer.append(cmdLine(' ', 0, 0))
#------------------------------------------------------------------------------#
# register the event handling code, GUI #
#------------------------------------------------------------------------------#
def main():
Draw.Register(draw_gui, handle_event, handle_button_event)
if __name__ == '__main__':
main()

File diff suppressed because it is too large Load Diff

View File

@@ -1,174 +0,0 @@
#!BPY
"""
Name: 'Envelope Symmetry'
Blender: 234
Group: 'Animation'
Tooltip: 'Make envelope symmetrical'
"""
__author__ = "Jonas Petersen"
__url__ = ("blender", "blenderartists.org", "Script's homepage, http://www.mindfloaters.de/blender/", "thread at blender.org, http://www.blender.org/modules.php?op=modload&name=phpBB2&file=viewtopic&t=4858 ")
__version__ = "0.9 2004-11-10"
__doc__ = """\
This script creates perfectly symmetrical envelope sets. It is part of the
envelop assignment tools.
"Envelopes" are Mesh objects with names following this naming convention:
<bone name>:<float value>
Please check the script's homepage and the thread at blender.org (last link button above) for more info.
For this version users need to edit the script code to change default options.
"""
# --------------------------------------------------------------------------
# "Envelope Symmetry" by Jonas Petersen
# Version 0.9 - 10th November 2004 - first public release
# --------------------------------------------------------------------------
#
# A script for creating perfectly symmetrical envelope sets. It is
# part of the envelope assignment tool.
#
# It is available in Object Mode via the menu item:
#
# Object -> Scripts -> Envelope Symmetry
#
# With default settings it will:
#
# - Look for bones
#
# Find the latest version at: http://www.mindfloaters.de/blender/
#
# --------------------------------------------------------------------------
# $Id$
# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
# Copyright (C) 2004: Jonas Petersen, jonas at mindfloaters dot de
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
# CONFIGURATION
# --------------------------------------------------------------------------
# Note: Theses values will later be editable via a gui interface
# within Blender.
# The suffix for the reference and opposite envelope.
# The configuration of of the opposite envelope will be overwritten by
# the configuration of the reference envelope (shape, position, bone, weight).
# The default is REF_SUFFIX = '.L' and OPP_SUFFIX = '.R'.
REF_SUFFIX = '.R'
OPP_SUFFIX = '.L'
# MIRROR_AXIS defines the axis in which bones are mirrored/aligned.
# Values:
# 0 for X (default)
# 1 for Y
# 2 for Z
MIRROR_AXIS = 0
# SEPARATOR is the character used to delimit the bone name and the weight
# in the envelope name.
SEPARATOR = ":"
# --------------------------------------------------------------------------
# END OF CONFIGURATION
# --------------------------------------------------------------------------
import Blender, math, sys
from Blender import Mathutils
from BPyNMesh import *
def flipFace(v):
if len(v) == 3: v[0], v[1], v[2] = v[2], v[1], v[0]
elif len(v) == 4: v[0], v[1], v[2], v[3] = v[3], v[2], v[1], v[0]
# return object with given object name (with variable parts) and mesh name
def getObjectByName(obj_name, mesh_name):
for obj in Blender.Scene.GetCurrent().objects:
if obj.type == "Mesh":
# if obj.getName()[0:len(obj_name)] == obj_name and obj.getData().name == mesh_name:
# use only mesh_name so bone name and weight (in the envelope name)
# can be changed by the user and mirrored by the script.
if obj.getData(name_only=1) == mesh_name:
return obj
return False
SUFFIX_LEN = len(REF_SUFFIX);
Blender.Window.EditMode(0)
count = 0
for obj in Blender.Scene.GetCurrent().objects:
if obj.type != 'Mesh':
continue
count += 1
name = obj.name
pos = name.find(SEPARATOR)
if (pos > -1):
ApplySizeAndRotation(obj)
base_name = name[0:pos-SUFFIX_LEN]
suffix = name[pos-SUFFIX_LEN:pos]
weight = name[pos:len(name)] # the SEPARATOR following a float value
if suffix == REF_SUFFIX:
mesh = obj.getData()
mirror_name = base_name + OPP_SUFFIX + weight
mirror_mesh_name = mesh.name + ".mirror"
mirror_obj = getObjectByName(base_name + OPP_SUFFIX, mirror_mesh_name)
if mirror_obj:
# update vertices
mirror_mesh = mirror_obj.getData()
for i in xrange(len(mesh.verts)):
org = mesh.verts[i]
mir = mirror_mesh.verts[i]
mir.co[0], mir.co[1], mir.co[2] = org.co[0], org.co[1], org.co[2]
mir.co[MIRROR_AXIS] *= -1
mirror_mesh.update()
else:
# create mirror object
mirror_mesh = obj.data
for face in mirror_mesh.faces:
flipFace(face.v)
for vert in mirror_mesh.verts:
vert.co[MIRROR_AXIS] *= -1
mirror_obj = Blender.NMesh.PutRaw(mirror_mesh, mirror_mesh_name)
# update name, drawType and location
mirror_obj.setName(mirror_name)
mirror_obj.drawType = obj.drawType
loc = [obj.LocX, obj.LocY, obj.LocZ]
loc[MIRROR_AXIS] *= -1
mirror_obj.setLocation(loc)
Blender.Window.EditMode(0)

View File

@@ -1,304 +0,0 @@
#!BPY
"""
Name: 'OpenInventor (.iv)...'
Blender: 236
Group: 'Export'
Tip: 'Export to OpenInventor file format. (.iv)'
"""
__author__ = ("Radek Barton")
__url__ = ["http://blackhex.no-ip.org/"]
__email__ = ["scripts"]
__version__ = "0.1"
__bpydoc__ = """\
This script exports to the Open Inventor format.
Usage:
Run this script from "File->Export" menu.
Note:
"""
# ***** BEGIN GPL LICENSE BLOCK *****
#
# Script copyright (C) Radek Barton
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
#
import Blender
math_pi= 3.1415926535897931
def WriteHeader(file):
file.write("#Inventor V2.1 ascii\n\n")
file.write("Separator\n")
file.write("{\n")
file.write(" ShapeHints\n")
file.write(" {\n")
file.write(" vertexOrdering COUNTERCLOCKWISE\n")
file.write(" }\n")
def WriteFooter(file):
file.write("}\n")
def WriteMesh(file, ob):
file.write(" Separator\n")
file.write(" {\n")
file.write(" # %s\n" % ob.name)
WriteMatrix(file, ob)
mesh = ob.getData()
WriteMaterials(file, mesh)
WriteTexture(file, mesh)
WriteNormals(file, mesh)
WriteVertices(file, mesh)
WriteFaces(file, mesh)
file.write(" }\n")
def WriteMatrix(file, ob):
matrix = ob.getMatrix()
file.write(" MatrixTransform\n")
file.write(" {\n")
file.write(" matrix\n")
for line in matrix:
file.write(" %.6f %.6f %.6f %.6f\n" % (line[0], line[1], line[2], line[3]))
file.write(" }\n")
def WriteColors(file, mesh):
file.write(" vertexProperty VertexProperty\n")
file.write(" {\n")
file.write(" orderedRGBA\n")
file.write(" [\n")
for face in mesh.faces:
for I in xrange(len(face)):
file.write(" 0x%02x%02x%02x%02x,\n" % (face.col[I].r,
face.col[I].g, face.col[I].b, face.col[I].a))
file.write(" ]\n")
file.write(" materialBinding PER_VERTEX\n")
file.write(" }\n")
def WriteMaterials(file, mesh):
if mesh.materials:
file.write(" Material\n")
file.write(" {\n")
file.write(" ambientColor\n")
file.write(" [\n")
for mat in mesh.materials:
file.write(" %.6f %.6f %.6f,\n" % (mat.mirCol[0], mat.mirCol[1],
mat.mirCol[2]))
file.write(" ]\n")
file.write(" diffuseColor\n")
file.write(" [\n")
for mat in mesh.materials:
file.write(" %.6f %.6f %.6f,\n" % (mat.rgbCol[0], mat.rgbCol[1],
mat.rgbCol[2]))
file.write(" ]\n")
file.write(" specularColor\n")
file.write(" [\n")
for mat in mesh.materials:
file.write(" %.6f %.6f %.6f,\n" % (mat.specCol[0] * mat.spec / 2.0,
mat.specCol[1] * mat.spec / 2.0, mat.specCol[2] * mat.spec / 2.0))
file.write(" ]\n")
file.write(" emissiveColor\n")
file.write(" [\n")
for mat in mesh.materials:
file.write(" %.6f %.6f %.6f,\n" % (mat.rgbCol[0] * mat.emit,
mat.rgbCol[1] * mat.emit, mat.rgbCol[0] * mat.emit))
file.write(" ]\n")
file.write(" shininess\n")
file.write(" [\n")
for mat in mesh.materials:
file.write(" %.6f,\n" % (mat.hard / 255.0))
file.write(" ]\n")
file.write(" transparency\n")
file.write(" [\n")
for mat in mesh.materials:
file.write(" %.6f,\n" % (1.0 - mat.alpha))
file.write(" ]\n")
file.write(" }\n")
file.write(" MaterialBinding\n")
file.write(" {\n")
file.write(" value PER_FACE_INDEXED\n")
file.write(" }\n")
def WriteTexture(file, mesh):
texture = mesh.faces[0].image # BAD Ju Ju
if texture:
file.write(" Texture2\n")
file.write(" {\n")
file.write(' filename "%s"\n' % texture.getName())
file.write(" }\n")
file.write(" TextureCoordinate2\n")
file.write(" {\n")
file.write(" point\n")
file.write(" [\n")
if mesh.hasVertexUV():
for vert in mesh.verts:
file.write(" %s %s,\n" % (vert.uvco[0], vert.uvco[1]))
file.write(" ]\n")
file.write(" }\n")
file.write(" TextureCoordinateBinding\n")
file.write(" {\n")
file.write(" value PER_VERTEX_INDEXED\n")
file.write(" }\n")
elif mesh.hasFaceUV():
for face in mesh.faces:
for uv in face.uv:
file.write(" %.6f %.6f,\n" % (uv[0], uv[1]))
file.write(" ]\n")
file.write(" }\n")
file.write(" TextureCoordinateBinding\n")
file.write(" {\n")
file.write(" value PER_VERTEX\n")
file.write(" }\n")
def WriteVertices(file, mesh):
file.write(" Coordinate3\n")
file.write(" {\n")
file.write(" point\n")
file.write(" [\n")
for vert in mesh.verts:
file.write(" %.6f %.6f %.6f,\n" % (vert[0], vert[1], vert[2]))
file.write(" ]\n")
file.write(" }\n")
def WriteNormals(file, mesh):
file.write(" Normal\n")
file.write(" {\n")
file.write(" vector\n")
file.write(" [\n")
# make copy of vertex normals
normals = []
for face in mesh.faces:
if len(face.v) in [3, 4]:
if face.smooth:
for v in face.v:
normals.append(v.no)
else:
for v in face.v:
normals.append(face.no)
# write normals
for no in normals:
file.write(" %.6f %.6f %.6f,\n" % (no[0], no[1], no[2]))
file.write(" ]\n")
file.write(" }\n")
# write way how normals are binded
file.write(" NormalBinding\n")
file.write(" {\n")
file.write(" value PER_VERTEX\n")
file.write(" }\n")
def WriteFaces(file, mesh):
file.write(" IndexedFaceSet\n")
file.write(" {\n")
# write vertex paint
if mesh.hasVertexColours():
WriteColors(file, mesh)
# write material indexes
file.write(" materialIndex\n")
file.write(" [\n")
for face in mesh.faces:
file.write(" %i,\n" % face.mat);
file.write(" ]\n")
# write faces with coordinate indexes
file.write(" coordIndex\n")
file.write(" [\n")
for face in mesh.faces:
face_v= face.v
if len(face_v) == 3:
file.write(" %i, %i, %i, -1,\n" % (face_v[0].index,
face_v[1].index, face_v[2].index))
elif len(face_v) == 4:
file.write(" %i, %i, %i, %i, -1,\n" % (face_v[0].index,
face_v[1].index, face_v[2].index, face_v[3].index))
file.write(" ]\n")
file.write(" }\n")
def WriteCamera(file, ob):
camera = ob.getData();
# perspective camera
if camera.type == 0:
file.write(" PerspectiveCamera\n")
file.write(" {\n")
file.write(" nearDistance %s\n" % (camera.clipStart))
file.write(" farDistance %s\n" % (camera.clipEnd))
file.write(" }\n")
# ortho camera
else:
print camera.type
def WriteLamp(file, ob):
lamp = ob.getData();
# spot lamp
if lamp.type == 2:
file.write(" SpotLight\n")
file.write(" {\n")
file.write(" intensity %s\n" % (lamp.energy / 10.0))
file.write(" color %s %s %s\n" % (lamp.col[0], lamp.col[1], lamp.col[2]))
#file.write(" location %s\n" % ())
#file.write(" direction %s\n" % ())
file.write(" dropOffRate %s\n" % (lamp.spotBlend))
file.write(" cutOffAngle %s\n" % (lamp.spotSize * math_pi / 180.0))
file.write(" }\n")
# script main function
def ExportToIv(file_name):
scene = Blender.Scene.GetCurrent()
file = open(file_name, "w")
# make lists of individual ob types
meshes = []
lamps = []
cameras = []
for ob in scene.objects:
obtype= ob.type
if obtype == "Mesh":
meshes.append(ob);
#elif obtype == "Lamp":
# lamps.append(ob);
#elif obtype == "Camera":
# cameras.append(ob);
#else:
# print "Exporting %s objects isn't supported!" % ob.type
# write header, footer and groups of ob types
WriteHeader(file);
#for camera in cameras:
# WriteCamera(file, camera);
#for lamp in lamps:
# WriteLamp(file, lamp)
for mesh in meshes:
WriteMesh(file, mesh)
WriteFooter(file)
file.close()
def FileSelectorCB(file_name):
if not file_name.lower().endswith('.iv'):
file_name += '.iv'
ExportToIv(file_name)
if __name__ == '__main__':
Blender.Window.FileSelector(FileSelectorCB, "Export IV", Blender.sys.makename(ext='.iv'))

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,157 +0,0 @@
#!BPY
""" Registration info for Blender menus: <- these words are ignored
Name: 'Lightwave Motion (.mot)...'
Blender: 241
Group: 'Export'
Tip: 'Export Loc Rot Size chanels to a Lightwave .mot file'
"""
__author__ = "Daniel Salazar (ZanQdo)"
__url__ = ("blender", "blenderartists.org",
"e-mail: zanqdo@gmail.com")
__version__ = "16/04/08"
__bpydoc__ = """\
This script exports the selected object's motion channels to Lightwave
motion files (.mot).
Usage:
Run the script with one or more objects selected (any kind), frames exported
are between Start and End frames in Render buttons.
"""
# $Id$
# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
# Copyright (C) 2003, 2004: A Vanpoucke
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
import Blender as B
import math as M
#------------------------------------
#Declarados:
TotalCanales = 9
#------------------------------------
def FuncionPrincipal (Dir):
B.Window.WaitCursor(1)
ObjSelect = B.Object.GetSelected()
if not ObjSelect:
B.Draw.PupMenu('Select 1 or more objects, aborting.')
return
if not Dir.lower().endswith('.mot'):
Dir += '.mot'
SC = B.Scene.GetCurrent()
SCR = SC.getRenderingContext()
for ob in ObjSelect:
origName= NombreObjeto= ob.name
print '----\nExporting Object "%s" motion file...' % origName
FrameA = B.Get('curframe')
FrameP = B.Get('staframe')
FrameF = B.Get('endframe')
FrameRate = float(SCR.framesPerSec())
#---------------------------------------------
# Replace danger characters by '_'
for ch in ' /\\~!@#$%^&*()+=[];\':",./<>?\t\r\n':
NombreObjeto = NombreObjeto.replace(ch, '_')
# Check for file path extension
if len(ObjSelect) > 1:
DirN= '%s_%s.mot' % (Dir[:-4], NombreObjeto)
else:
DirN= Dir
# Open the file
File = open(DirN,'w')
File.write ('LWMO\n3\n\n') # 3 is the version number.
# number of channels
File.write ('NumChannels %i\n' % TotalCanales)
# ----------------------------
# Main Cycle
def CicloPrimario(NumCanal):
B.Set('curframe', FrameP)
File.write ('Channel %i\n{ Envelope\n %i\n' % (NumCanal, (FrameF - FrameP + 1)))
FrameA = FrameP
while FrameA < (FrameF + 1):
B.Set('curframe', FrameA)
mat= ob.mat # Worldspace matrix
if NumCanal == 0:
Val = mat.translationPart().x
elif NumCanal == 1:
Val = mat.translationPart().z
elif NumCanal == 2:
Val = mat.translationPart().y
elif NumCanal == 3:
Val = M.radians (-mat.toEuler().z)
elif NumCanal == 4:
Val = M.radians (-mat.toEuler().x)
elif NumCanal == 5:
Val = M.radians (-mat.toEuler().y)
elif NumCanal == 6:
Val = mat.scalePart().x
elif NumCanal == 7:
Val = mat.scalePart().z
elif NumCanal == 8:
Val = mat.scalePart().y
File.write (' Key %f %f 3 0 0 0 0 0 0\n' % (Val, (FrameA/FrameRate)))
FrameA += 1
# Ending Stuff
File.write (' Behaviors 1 1\n}\n')
NumObjetoActual = len(ObjSelect)
Iteraciones = 0
ProgBarVal = 0.0
while Iteraciones < TotalCanales:
CicloPrimario(Iteraciones)
# Start Progress Bar
B.Window.DrawProgressBar(ProgBarVal, origName)
ProgBarVal = (float(Iteraciones) / TotalCanales) * 0.98
Iteraciones += 1
B.Window.DrawProgressBar(1.0, '') # Done
print '\nDone, %s motion file location is:\n%s\n' % (origName, DirN)
B.Window.WaitCursor(0)
# Check if there are selected objects
def main():
B.Window.FileSelector(FuncionPrincipal, "Write .mot File", B.sys.makename(ext='.mot'))
if __name__=='__main__':
main()

File diff suppressed because it is too large Load Diff

View File

@@ -1,454 +0,0 @@
#!BPY
"""
Name: 'Quake 3 (.map)'
Blender: 249
Group: 'Export'
Tooltip: 'Export to Quake map format'
"""
__author__ = 'Campbell Barton'
__version__ = '0.1a'
__email__ = "ideasman42@gmail.com"
__bpydoc__ = """\
This script Exports a Quake 3 map format.
Supports meshes, lights and nurbs patch surfaces
"""
# ***** BEGIN GPL LICENSE BLOCK *****
#
# Script copyright (C): Campbell Barton
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
from Blender import *
import BPyMesh
PREF_SCALE= Draw.Create(100)
PREF_FACE_THICK= Draw.Create(0.1)
PREF_GRID_SNAP= Draw.Create(0)
# Quake 1/2?
# PREF_DEF_TEX_OPTS= Draw.Create(' 0 0 0 1 1\n') # not user settable yet
# Quake 3+?
PREF_DEF_TEX_OPTS= Draw.Create(' 0 0 0 1 1 0 0 0\n') # not user settable yet
PREF_NULL_TEX= Draw.Create('NULL') # not user settable yet
PREF_INVIS_TEX= Draw.Create('common/caulk')
def write_cube2brush(file, faces):
'''
Takes 6 faces and writes a brush,
these faces can be from 1 mesh, 1 cube within a mesh of larger cubes
Faces could even come from different meshes or be contrived.
'''
# comment only
# file.write('// brush "%s", "%s"\n' % (ob.name, ob.getData(name_only=1)))
file.write('// brush from cube\n{\n')
if PREF_GRID_SNAP.val: format_vec= '( %d %d %d ) '
else: format_vec= '( %.8f %.8f %.8f ) '
for f in faces:
# from 4 verts this gets them in reversed order and only 3 of them
# 0,1,2,3 -> 2,1,0
for v in f.v[2::-1]:
file.write(format_vec % tuple(v.co) )
try: mode= f.mode
except: mode= 0
if mode & Mesh.FaceModes.INVISIBLE:
file.write(PREF_INVIS_TEX.val)
else:
try: image= f.image
except: image= None
if image: file.write(sys.splitext(sys.basename(image.filename))[0])
else: file.write(PREF_NULL_TEX.val)
# Texture stuff ignored for now
file.write(PREF_DEF_TEX_OPTS.val)
file.write('}\n')
def round_vec(v):
if PREF_GRID_SNAP.val:
return round(v.x), round(v.y), round(v.z)
else:
return tuple(v)
def write_face2brush(file, face):
'''
takes a face and writes it as a brush
each face is a cube/brush
'''
if PREF_GRID_SNAP.val: format_vec= '( %d %d %d ) '
else: format_vec= '( %.8f %.8f %.8f ) '
image_text= PREF_NULL_TEX.val
try: mode= face.mode
except: mode= 0
if mode & Mesh.FaceModes.INVISIBLE:
image_text= PREF_INVIS_TEX.val
else:
try: image= face.image
except: image= None
if image: image_text = sys.splitext(sys.basename(image.filename))[0]
# original verts as tuples for writing
orig_vco= [tuple(v.co) for v in face]
# new verts that give the face a thickness
dist= PREF_SCALE.val * PREF_FACE_THICK.val
new_vco= [round_vec(v.co - (v.no * dist)) for v in face]
#new_vco= [round_vec(v.co - (face.no * dist)) for v in face]
file.write('// brush from face\n{\n')
# front
for co in orig_vco[2::-1]:
file.write(format_vec % co )
file.write(image_text)
# Texture stuff ignored for now
file.write(PREF_DEF_TEX_OPTS.val)
for co in new_vco[:3]:
file.write(format_vec % co )
if mode & Mesh.FaceModes.TWOSIDE:
file.write(image_text)
else:
file.write(PREF_INVIS_TEX.val)
# Texture stuff ignored for now
file.write(PREF_DEF_TEX_OPTS.val)
# sides.
if len(orig_vco)==3: # Tri, it seemms tri brushes are supported.
index_pairs= ((0,1), (1,2), (2,0))
else:
index_pairs= ((0,1), (1,2), (2,3), (3,0))
for i1, i2 in index_pairs:
for co in orig_vco[i1], orig_vco[i2], new_vco[i2]:
file.write( format_vec % co )
file.write(PREF_INVIS_TEX.val)
file.write(PREF_DEF_TEX_OPTS.val)
file.write('}\n')
def is_cube_facegroup(faces):
'''
Returens a bool, true if the faces make up a cube
'''
# cube must have 6 faces
if len(faces) != 6:
print '1'
return False
# Check for quads and that there are 6 unique verts
verts= {}
for f in faces:
if len(f)!= 4:
return False
for v in f:
verts[v.index]= 0
if len(verts) != 8:
return False
# Now check that each vert has 3 face users
for f in faces:
for v in f:
verts[v.index] += 1
for v in verts.itervalues():
if v != 3: # vert has 3 users?
return False
# Could we check for 12 unique edges??, probably not needed.
return True
def is_tricyl_facegroup(faces):
'''
is the face group a tri cylinder
Returens a bool, true if the faces make an extruded tri solid
'''
# cube must have 5 faces
if len(faces) != 5:
print '1'
return False
# Check for quads and that there are 6 unique verts
verts= {}
tottri= 0
for f in faces:
if len(f)== 3:
tottri+=1
for v in f:
verts[v.index]= 0
if len(verts) != 6 or tottri != 2:
return False
# Now check that each vert has 3 face users
for f in faces:
for v in f:
verts[v.index] += 1
for v in verts.itervalues():
if v != 3: # vert has 3 users?
return False
# Could we check for 12 unique edges??, probably not needed.
return True
def write_node_map(file, ob):
'''
Writes the properties of an object (empty in this case)
as a MAP node as long as it has the property name - classname
returns True/False based on weather a node was written
'''
props= [(p.name, p.data) for p in ob.game_properties]
IS_MAP_NODE= False
for name, value in props:
if name=='classname':
IS_MAP_NODE= True
break
if not IS_MAP_NODE:
return False
# Write a node
file.write('{\n')
for name_value in props:
file.write('"%s" "%s"\n' % name_value)
if PREF_GRID_SNAP.val:
file.write('"origin" "%d %d %d"\n' % tuple([round(axis*PREF_SCALE.val) for axis in ob.getLocation('worldspace')]) )
else:
file.write('"origin" "%.6f %.6f %.6f"\n' % tuple([axis*PREF_SCALE.val for axis in ob.getLocation('worldspace')]) )
file.write('}\n')
return True
def export_map(filepath):
pup_block = [\
('Scale:', PREF_SCALE, 1, 1000, 'Scale the blender scene by this value.'),\
('Face Width:', PREF_FACE_THICK, 0.01, 10, 'Thickness of faces exported as brushes.'),\
('Grid Snap', PREF_GRID_SNAP, 'snaps floating point values to whole numbers.'),\
'Null Texture',\
('', PREF_NULL_TEX, 1, 128, 'Export textureless faces with this texture'),\
'Unseen Texture',\
('', PREF_INVIS_TEX, 1, 128, 'Export invisible faces with this texture'),\
]
if not Draw.PupBlock('map export', pup_block):
return
Window.WaitCursor(1)
time= sys.time()
print 'Map Exporter 0.0'
file= open(filepath, 'w')
obs_mesh= []
obs_lamp= []
obs_surf= []
obs_empty= []
SCALE_MAT= Mathutils.Matrix()
SCALE_MAT[0][0]= SCALE_MAT[1][1]= SCALE_MAT[2][2]= PREF_SCALE.val
dummy_mesh= Mesh.New()
TOTBRUSH= TOTLAMP= TOTNODE= 0
for ob in Object.GetSelected():
type= ob.type
if type == 'Mesh': obs_mesh.append(ob)
elif type == 'Surf': obs_surf.append(ob)
elif type == 'Lamp': obs_lamp.append(ob)
elif type == 'Empty': obs_empty.append(ob)
if obs_mesh or obs_surf:
# brushes and surf's must be under worldspan
file.write('\n// entity 0\n')
file.write('{\n')
file.write('"classname" "worldspawn"\n')
print '\twriting cubes from meshes'
for ob in obs_mesh:
dummy_mesh.getFromObject(ob.name)
#print len(mesh_split2connected(dummy_mesh))
# Is the object 1 cube? - object-is-a-brush
dummy_mesh.transform(ob.matrixWorld*SCALE_MAT) # 1 to tx the normals also
if PREF_GRID_SNAP.val:
for v in dummy_mesh.verts:
co= v.co
co.x= round(co.x)
co.y= round(co.y)
co.z= round(co.z)
# High quality normals
BPyMesh.meshCalcNormals(dummy_mesh)
# Split mesh into connected regions
for face_group in BPyMesh.mesh2linkedFaces(dummy_mesh):
if is_cube_facegroup(face_group):
write_cube2brush(file, face_group)
TOTBRUSH+=1
elif is_tricyl_facegroup(face_group):
write_cube2brush(file, face_group)
TOTBRUSH+=1
else:
for f in face_group:
write_face2brush(file, f)
TOTBRUSH+=1
#print 'warning, not exporting "%s" it is not a cube' % ob.name
dummy_mesh.verts= None
valid_dims= 3,5,7,9,11,13,15
for ob in obs_surf:
'''
Surf, patches
'''
surf_name= ob.getData(name_only=1)
data= Curve.Get(surf_name)
mat = ob.matrixWorld*SCALE_MAT
# This is what a valid patch looks like
"""
// brush 0
{
patchDef2
{
NULL
( 3 3 0 0 0 )
(
( ( -64 -64 0 0 0 ) ( -64 0 0 0 -2 ) ( -64 64 0 0 -4 ) )
( ( 0 -64 0 2 0 ) ( 0 0 0 2 -2 ) ( 0 64 0 2 -4 ) )
( ( 64 -64 0 4 0 ) ( 64 0 0 4 -2 ) ( 80 88 0 4 -4 ) )
)
}
}
"""
for i, nurb in enumerate(data):
u= nurb.pointsU
v= nurb.pointsV
if u in valid_dims and v in valid_dims:
file.write('// brush %d surf_name\n' % i)
file.write('{\n')
file.write('patchDef2\n')
file.write('{\n')
file.write('NULL\n')
file.write('( %d %d 0 0 0 )\n' % (u, v) )
file.write('(\n')
u_iter = 0
for p in nurb:
if u_iter == 0:
file.write('(')
u_iter += 1
# add nmapping 0 0 ?
if PREF_GRID_SNAP.val:
file.write(' ( %d %d %d 0 0 )' % round_vec(Mathutils.Vector(p[0:3]) * mat))
else:
file.write(' ( %.6f %.6f %.6f 0 0 )' % tuple(Mathutils.Vector(p[0:3]) * mat))
# Move to next line
if u_iter == u:
file.write(' )\n')
u_iter = 0
file.write(')\n')
file.write('}\n')
file.write('}\n')
# Debugging
# for p in nurb: print 'patch', p
else:
print "NOT EXPORTING PATCH", surf_name, u,v, 'Unsupported'
if obs_mesh or obs_surf:
file.write('}\n') # end worldspan
print '\twriting lamps'
for ob in obs_lamp:
print '\t\t%s' % ob.name
lamp= ob.data
file.write('{\n')
file.write('"classname" "light"\n')
file.write('"light" "%.6f"\n' % (lamp.dist* PREF_SCALE.val))
if PREF_GRID_SNAP.val:
file.write('"origin" "%d %d %d"\n' % tuple([round(axis*PREF_SCALE.val) for axis in ob.getLocation('worldspace')]) )
else:
file.write('"origin" "%.6f %.6f %.6f"\n' % tuple([axis*PREF_SCALE.val for axis in ob.getLocation('worldspace')]) )
file.write('"_color" "%.6f %.6f %.6f"\n' % tuple(lamp.col))
file.write('"style" "0"\n')
file.write('}\n')
TOTLAMP+=1
print '\twriting empty objects as nodes'
for ob in obs_empty:
if write_node_map(file, ob):
print '\t\t%s' % ob.name
TOTNODE+=1
else:
print '\t\tignoring %s' % ob.name
Window.WaitCursor(0)
print 'Exported Map in %.4fsec' % (sys.time()-time)
print 'Brushes: %d Nodes: %d Lamps %d\n' % (TOTBRUSH, TOTNODE, TOTLAMP)
def main():
Window.FileSelector(export_map, 'EXPORT MAP', '*.map')
if __name__ == '__main__': main()
# export_map('/foo.map')

View File

@@ -1,168 +0,0 @@
#!BPY
"""
Name: 'Vertex Keyframe Animation (.mdd)...'
Blender: 242
Group: 'Export'
Tooltip: 'Animated mesh to MDD vertex keyframe file.'
"""
__author__ = "Bill L.Nieuwendorp"
__bpydoc__ = """\
This script Exports Lightwaves MotionDesigner format.
The .mdd format has become quite a popular Pipeline format<br>
for moving animations from package to package.
Be sure not to use modifiers that change the number or order of verts in the mesh
"""
#Please send any fixes,updates,bugs to Slow67_at_Gmail.com or cbarton_at_metavr.com
#Bill Niewuendorp
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
import bpy
import Blender
from Blender import *
import BPyMessages
try:
from struct import pack
except:
pack = None
def zero_file(filepath):
'''
If a file fails, this replaces it with 1 char, better not remove it?
'''
file = open(filepath, 'w')
file.write('\n') # aparently macosx needs some data in a blank file?
file.close()
def check_vertcount(mesh,vertcount):
'''
check and make sure the vertcount is consistent throghout the frame range
'''
if len(mesh.verts) != vertcount:
Blender.Draw.PupMenu('Error%t|Number of verts has changed during animation|cannot export')
f.close()
zero_file(filepath)
return
def mdd_export(filepath, ob, PREF_STARTFRAME, PREF_ENDFRAME, PREF_FPS):
Window.EditMode(0)
Blender.Window.WaitCursor(1)
mesh_orig = Mesh.New()
mesh_orig.getFromObject(ob.name)
#Flip y and z
'''
mat = Mathutils.Matrix()
mat[2][2] = -1
rotmat = Mathutils.RotationMatrix(90, 4, 'x')
mat_flip = mat*rotmat
'''
# Above results in this matrix
mat_flip= Mathutils.Matrix(\
[1.0, 0.0, 0.0, 0.0],\
[0.0, 0.0, 1.0, 0.0],\
[0.0, 1.0, 0.0, 0.0],\
[0.0, 0.0, 0.0, 1.0],\
)
me_tmp = Mesh.New() # container mesh
numverts = len(mesh_orig.verts)
numframes = PREF_ENDFRAME-PREF_STARTFRAME+1
PREF_FPS= float(PREF_FPS)
f = open(filepath, 'wb') #no Errors yet:Safe to create file
# Write the header
f.write(pack(">2i", numframes, numverts))
# Write the frame times (should we use the time IPO??)
f.write( pack(">%df" % (numframes), *[frame/PREF_FPS for frame in xrange(numframes)]) ) # seconds
#rest frame needed to keep frames in sync
Blender.Set('curframe', PREF_STARTFRAME)
me_tmp.getFromObject(ob.name)
check_vertcount(me_tmp,numverts)
me_tmp.transform(ob.matrixWorld * mat_flip)
f.write(pack(">%df" % (numverts*3), *[axis for v in me_tmp.verts for axis in v.co]))
me_tmp.verts= None
for frame in xrange(PREF_STARTFRAME,PREF_ENDFRAME+1):#in order to start at desired frame
Blender.Set('curframe', frame)
me_tmp.getFromObject(ob.name)
check_vertcount(me_tmp,numverts)
me_tmp.transform(ob.matrixWorld * mat_flip)
# Write the vertex data
f.write(pack(">%df" % (numverts*3), *[axis for v in me_tmp.verts for axis in v.co]))
me_tmp.verts= None
f.close()
print'MDD Exported: %s frames:%d\n'% (filepath, numframes-1)
Blender.Window.WaitCursor(0)
def mdd_export_ui(filepath):
# Dont overwrite
if not BPyMessages.Warning_SaveOver(filepath):
return
scn= bpy.data.scenes.active
ob_act= scn.objects.active
if not ob_act or ob_act.type != 'Mesh':
BPyMessages.Error_NoMeshActive()
ctx = scn.getRenderingContext()
orig_frame = Blender.Get('curframe')
PREF_STARTFRAME= Blender.Draw.Create(int(ctx.startFrame()))
PREF_ENDFRAME= Blender.Draw.Create(int(ctx.endFrame()))
PREF_FPS= Blender.Draw.Create(ctx.fps)
block = [\
("Start Frame: ", PREF_STARTFRAME, 1, 30000, "Start Bake from what frame?: Default 1"),\
("End Frame: ", PREF_ENDFRAME, 1, 30000, "End Bake on what Frame?"),\
("FPS: ", PREF_FPS, 1, 100, "Frames per second")\
]
if not Blender.Draw.PupBlock("Export MDD", block):
return
PREF_STARTFRAME, PREF_ENDFRAME=\
min(PREF_STARTFRAME.val, PREF_ENDFRAME.val),\
max(PREF_STARTFRAME.val, PREF_ENDFRAME.val)
print (filepath, ob_act, PREF_STARTFRAME, PREF_ENDFRAME, PREF_FPS.val)
mdd_export(filepath, ob_act, PREF_STARTFRAME, PREF_ENDFRAME, PREF_FPS.val)
Blender.Set('curframe', orig_frame)
if __name__=='__main__':
if not pack:
Draw.PupMenu('Error%t|This script requires a full python install')
Blender.Window.FileSelector(mdd_export_ui, 'EXPORT MDD', sys.makename(ext='.mdd'))

View File

@@ -1,933 +0,0 @@
#!BPY
"""
Name: 'Wavefront (.obj)...'
Blender: 249
Group: 'Export'
Tooltip: 'Save a Wavefront OBJ File'
"""
__author__ = "Campbell Barton, Jiri Hnidek, Paolo Ciccone"
__url__ = ['http://wiki.blender.org/index.php/Scripts/Manual/Export/wavefront_obj', 'www.blender.org', 'blenderartists.org']
__version__ = "1.22"
__bpydoc__ = """\
This script is an exporter to OBJ file format.
Usage:
Select the objects you wish to export and run this script from "File->Export" menu.
Selecting the default options from the popup box will be good in most cases.
All objects that can be represented as a mesh (mesh, curve, metaball, surface, text3d)
will be exported as mesh data.
"""
# ***** BEGIN GPL LICENSE BLOCK *****
#
# Script copyright (C) Campbell J Barton 2007-2009
# - V1.22- bspline import/export added (funded by PolyDimensions GmbH)
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
import Blender
from Blender import Mesh, Scene, Window, sys, Image, Draw
import BPyMesh
import BPyObject
import BPySys
import BPyMessages
# Returns a tuple - path,extension.
# 'hello.obj' > ('hello', '.obj')
def splitExt(path):
dotidx = path.rfind('.')
if dotidx == -1:
return path, ''
else:
return path[:dotidx], path[dotidx:]
def fixName(name):
if name == None:
return 'None'
else:
return name.replace(' ', '_')
# A Dict of Materials
# (material.name, image.name):matname_imagename # matname_imagename has gaps removed.
MTL_DICT = {}
def write_mtl(filename):
world = Blender.World.GetCurrent()
if world:
worldAmb = world.getAmb()
else:
worldAmb = (0,0,0) # Default value
file = open(filename, "w")
file.write('# Blender3D MTL File: %s\n' % Blender.Get('filename').split('\\')[-1].split('/')[-1])
file.write('# Material Count: %i\n' % len(MTL_DICT))
# Write material/image combinations we have used.
for key, (mtl_mat_name, mat, img) in MTL_DICT.iteritems():
# Get the Blender data for the material and the image.
# Having an image named None will make a bug, dont do it :)
file.write('newmtl %s\n' % mtl_mat_name) # Define a new material: matname_imgname
if mat:
file.write('Ns %.6f\n' % ((mat.getHardness()-1) * 1.9607843137254901) ) # Hardness, convert blenders 1-511 to MTL's
file.write('Ka %.6f %.6f %.6f\n' % tuple([c*mat.amb for c in worldAmb]) ) # Ambient, uses mirror colour,
file.write('Kd %.6f %.6f %.6f\n' % tuple([c*mat.ref for c in mat.rgbCol]) ) # Diffuse
file.write('Ks %.6f %.6f %.6f\n' % tuple([c*mat.spec for c in mat.specCol]) ) # Specular
file.write('Ni %.6f\n' % mat.IOR) # Refraction index
file.write('d %.6f\n' % mat.alpha) # Alpha (obj uses 'd' for dissolve)
# 0 to disable lighting, 1 for ambient & diffuse only (specular color set to black), 2 for full lighting.
if mat.getMode() & Blender.Material.Modes['SHADELESS']:
file.write('illum 0\n') # ignore lighting
elif mat.getSpec() == 0:
file.write('illum 1\n') # no specular.
else:
file.write('illum 2\n') # light normaly
else:
#write a dummy material here?
file.write('Ns 0\n')
file.write('Ka %.6f %.6f %.6f\n' % tuple([c for c in worldAmb]) ) # Ambient, uses mirror colour,
file.write('Kd 0.8 0.8 0.8\n')
file.write('Ks 0.8 0.8 0.8\n')
file.write('d 1\n') # No alpha
file.write('illum 2\n') # light normaly
# Write images!
if img: # We have an image on the face!
file.write('map_Kd %s\n' % img.filename.split('\\')[-1].split('/')[-1]) # Diffuse mapping image
elif mat: # No face image. if we havea material search for MTex image.
for mtex in mat.getTextures():
if mtex and mtex.tex.type == Blender.Texture.Types.IMAGE:
try:
filename = mtex.tex.image.filename.split('\\')[-1].split('/')[-1]
file.write('map_Kd %s\n' % filename) # Diffuse mapping image
break
except:
# Texture has no image though its an image type, best ignore.
pass
file.write('\n\n')
file.close()
def copy_file(source, dest):
file = open(source, 'rb')
data = file.read()
file.close()
file = open(dest, 'wb')
file.write(data)
file.close()
def copy_images(dest_dir):
if dest_dir[-1] != sys.sep:
dest_dir += sys.sep
# Get unique image names
uniqueImages = {}
for matname, mat, image in MTL_DICT.itervalues(): # Only use image name
# Get Texface images
if image:
uniqueImages[image] = image # Should use sets here. wait until Python 2.4 is default.
# Get MTex images
if mat:
for mtex in mat.getTextures():
if mtex and mtex.tex.type == Blender.Texture.Types.IMAGE:
image_tex = mtex.tex.image
if image_tex:
try:
uniqueImages[image_tex] = image_tex
except:
pass
# Now copy images
copyCount = 0
for bImage in uniqueImages.itervalues():
image_path = sys.expandpath(bImage.filename)
if sys.exists(image_path):
# Make a name for the target path.
dest_image_path = dest_dir + image_path.split('\\')[-1].split('/')[-1]
if not sys.exists(dest_image_path): # Image isnt alredy there
print '\tCopying "%s" > "%s"' % (image_path, dest_image_path)
copy_file(image_path, dest_image_path)
copyCount+=1
print '\tCopied %d images' % copyCount
def test_nurbs_compat(ob):
if ob.type != 'Curve':
return False
for nu in ob.data:
if (not nu.knotsV) and nu.type != 1: # not a surface and not bezier
return True
return False
def write_nurb(file, ob, ob_mat):
tot_verts = 0
cu = ob.data
# use negative indices
Vector = Blender.Mathutils.Vector
for nu in cu:
if nu.type==0: DEG_ORDER_U = 1
else: DEG_ORDER_U = nu.orderU-1 # Tested to be correct
if nu.type==1:
print "\tWarning, bezier curve:", ob.name, "only poly and nurbs curves supported"
continue
if nu.knotsV:
print "\tWarning, surface:", ob.name, "only poly and nurbs curves supported"
continue
if len(nu) <= DEG_ORDER_U:
print "\tWarning, orderU is lower then vert count, skipping:", ob.name
continue
pt_num = 0
do_closed = (nu.flagU & 1)
do_endpoints = (do_closed==0) and (nu.flagU & 2)
for pt in nu:
pt = Vector(pt[0], pt[1], pt[2]) * ob_mat
file.write('v %.6f %.6f %.6f\n' % (pt[0], pt[1], pt[2]))
pt_num += 1
tot_verts += pt_num
file.write('g %s\n' % (fixName(ob.name))) # fixName(ob.getData(1)) could use the data name too
file.write('cstype bspline\n') # not ideal, hard coded
file.write('deg %d\n' % DEG_ORDER_U) # not used for curves but most files have it still
curve_ls = [-(i+1) for i in xrange(pt_num)]
# 'curv' keyword
if do_closed:
if DEG_ORDER_U == 1:
pt_num += 1
curve_ls.append(-1)
else:
pt_num += DEG_ORDER_U
curve_ls = curve_ls + curve_ls[0:DEG_ORDER_U]
file.write('curv 0.0 1.0 %s\n' % (' '.join( [str(i) for i in curve_ls] ))) # Blender has no U and V values for the curve
# 'parm' keyword
tot_parm = (DEG_ORDER_U + 1) + pt_num
tot_parm_div = float(tot_parm-1)
parm_ls = [(i/tot_parm_div) for i in xrange(tot_parm)]
if do_endpoints: # end points, force param
for i in xrange(DEG_ORDER_U+1):
parm_ls[i] = 0.0
parm_ls[-(1+i)] = 1.0
file.write('parm u %s\n' % ' '.join( [str(i) for i in parm_ls] ))
file.write('end\n')
return tot_verts
def write(filename, objects,\
EXPORT_TRI=False, EXPORT_EDGES=False, EXPORT_NORMALS=False, EXPORT_NORMALS_HQ=False,\
EXPORT_UV=True, EXPORT_MTL=True, EXPORT_COPY_IMAGES=False,\
EXPORT_APPLY_MODIFIERS=True, EXPORT_ROTX90=True, EXPORT_BLEN_OBS=True,\
EXPORT_GROUP_BY_OB=False, EXPORT_GROUP_BY_MAT=False, EXPORT_KEEP_VERT_ORDER=False,\
EXPORT_POLYGROUPS=False, EXPORT_CURVE_AS_NURBS=True):
'''
Basic write function. The context and options must be alredy set
This can be accessed externaly
eg.
write( 'c:\\test\\foobar.obj', Blender.Object.GetSelected() ) # Using default options.
'''
def veckey3d(v):
return round(v.x, 6), round(v.y, 6), round(v.z, 6)
def veckey2d(v):
return round(v.x, 6), round(v.y, 6)
def findVertexGroupName(face, vWeightMap):
"""
Searches the vertexDict to see what groups is assigned to a given face.
We use a frequency system in order to sort out the name because a given vetex can
belong to two or more groups at the same time. To find the right name for the face
we list all the possible vertex group names with their frequency and then sort by
frequency in descend order. The top element is the one shared by the highest number
of vertices is the face's group
"""
weightDict = {}
for vert in face:
vWeights = vWeightMap[vert.index]
for vGroupName, weight in vWeights:
weightDict[vGroupName] = weightDict.get(vGroupName, 0) + weight
if weightDict:
alist = [(weight,vGroupName) for vGroupName, weight in weightDict.iteritems()] # sort least to greatest amount of weight
alist.sort()
return(alist[-1][1]) # highest value last
else:
return '(null)'
print 'OBJ Export path: "%s"' % filename
temp_mesh_name = '~tmp-mesh'
time1 = sys.time()
scn = Scene.GetCurrent()
file = open(filename, "w")
# Write Header
file.write('# Blender3D v%s OBJ File: %s\n' % (Blender.Get('version'), Blender.Get('filename').split('/')[-1].split('\\')[-1] ))
file.write('# www.blender3d.org\n')
# Tell the obj file what material file to use.
if EXPORT_MTL:
mtlfilename = '%s.mtl' % '.'.join(filename.split('.')[:-1])
file.write('mtllib %s\n' % ( mtlfilename.split('\\')[-1].split('/')[-1] ))
# Get the container mesh. - used for applying modifiers and non mesh objects.
containerMesh = meshName = tempMesh = None
for meshName in Blender.NMesh.GetNames():
if meshName.startswith(temp_mesh_name):
tempMesh = Mesh.Get(meshName)
if not tempMesh.users:
containerMesh = tempMesh
if not containerMesh:
containerMesh = Mesh.New(temp_mesh_name)
if EXPORT_ROTX90:
mat_xrot90= Blender.Mathutils.RotationMatrix(-90, 4, 'x')
del meshName
del tempMesh
# Initialize totals, these are updated each object
totverts = totuvco = totno = 1
face_vert_index = 1
globalNormals = {}
# Get all meshes
for ob_main in objects:
for ob, ob_mat in BPyObject.getDerivedObjects(ob_main):
# Nurbs curve support
if EXPORT_CURVE_AS_NURBS and test_nurbs_compat(ob):
if EXPORT_ROTX90:
ob_mat = ob_mat * mat_xrot90
totverts += write_nurb(file, ob, ob_mat)
continue
# end nurbs
# Will work for non meshes now! :)
# getMeshFromObject(ob, container_mesh=None, apply_modifiers=True, vgroups=True, scn=None)
me= BPyMesh.getMeshFromObject(ob, containerMesh, EXPORT_APPLY_MODIFIERS, EXPORT_POLYGROUPS, scn)
if not me:
continue
if EXPORT_UV:
faceuv= me.faceUV
else:
faceuv = False
# We have a valid mesh
if EXPORT_TRI and me.faces:
# Add a dummy object to it.
has_quads = False
for f in me.faces:
if len(f) == 4:
has_quads = True
break
if has_quads:
oldmode = Mesh.Mode()
Mesh.Mode(Mesh.SelectModes['FACE'])
me.sel = True
tempob = scn.objects.new(me)
me.quadToTriangle(0) # more=0 shortest length
oldmode = Mesh.Mode(oldmode)
scn.objects.unlink(tempob)
Mesh.Mode(oldmode)
# Make our own list so it can be sorted to reduce context switching
faces = [ f for f in me.faces ]
if EXPORT_EDGES:
edges = me.edges
else:
edges = []
if not (len(faces)+len(edges)+len(me.verts)): # Make sure there is somthing to write
continue # dont bother with this mesh.
if EXPORT_ROTX90:
me.transform(ob_mat*mat_xrot90)
else:
me.transform(ob_mat)
# High Quality Normals
if EXPORT_NORMALS and faces:
if EXPORT_NORMALS_HQ:
BPyMesh.meshCalcNormals(me)
else:
# transforming normals is incorrect
# when the matrix is scaled,
# better to recalculate them
me.calcNormals()
# # Crash Blender
#materials = me.getMaterials(1) # 1 == will return None in the list.
materials = me.materials
materialNames = []
materialItems = materials[:]
if materials:
for mat in materials:
if mat: # !=None
materialNames.append(mat.name)
else:
materialNames.append(None)
# Cant use LC because some materials are None.
# materialNames = map(lambda mat: mat.name, materials) # Bug Blender, dosent account for null materials, still broken.
# Possible there null materials, will mess up indicies
# but at least it will export, wait until Blender gets fixed.
materialNames.extend((16-len(materialNames)) * [None])
materialItems.extend((16-len(materialItems)) * [None])
# Sort by Material, then images
# so we dont over context switch in the obj file.
if EXPORT_KEEP_VERT_ORDER:
pass
elif faceuv:
try: faces.sort(key = lambda a: (a.mat, a.image, a.smooth))
except: faces.sort(lambda a,b: cmp((a.mat, a.image, a.smooth), (b.mat, b.image, b.smooth)))
elif len(materials) > 1:
try: faces.sort(key = lambda a: (a.mat, a.smooth))
except: faces.sort(lambda a,b: cmp((a.mat, a.smooth), (b.mat, b.smooth)))
else:
# no materials
try: faces.sort(key = lambda a: a.smooth)
except: faces.sort(lambda a,b: cmp(a.smooth, b.smooth))
# Set the default mat to no material and no image.
contextMat = (0, 0) # Can never be this, so we will label a new material teh first chance we get.
contextSmooth = None # Will either be true or false, set bad to force initialization switch.
if EXPORT_BLEN_OBS or EXPORT_GROUP_BY_OB:
name1 = ob.name
name2 = ob.getData(1)
if name1 == name2:
obnamestring = fixName(name1)
else:
obnamestring = '%s_%s' % (fixName(name1), fixName(name2))
if EXPORT_BLEN_OBS:
file.write('o %s\n' % obnamestring) # Write Object name
else: # if EXPORT_GROUP_BY_OB:
file.write('g %s\n' % obnamestring)
# Vert
for v in me.verts:
file.write('v %.6f %.6f %.6f\n' % tuple(v.co))
# UV
if faceuv:
uv_face_mapping = [[0,0,0,0] for f in faces] # a bit of a waste for tri's :/
uv_dict = {} # could use a set() here
for f_index, f in enumerate(faces):
for uv_index, uv in enumerate(f.uv):
uvkey = veckey2d(uv)
try:
uv_face_mapping[f_index][uv_index] = uv_dict[uvkey]
except:
uv_face_mapping[f_index][uv_index] = uv_dict[uvkey] = len(uv_dict)
file.write('vt %.6f %.6f\n' % tuple(uv))
uv_unique_count = len(uv_dict)
del uv, uvkey, uv_dict, f_index, uv_index
# Only need uv_unique_count and uv_face_mapping
# NORMAL, Smooth/Non smoothed.
if EXPORT_NORMALS:
for f in faces:
if f.smooth:
for v in f:
noKey = veckey3d(v.no)
if not globalNormals.has_key( noKey ):
globalNormals[noKey] = totno
totno +=1
file.write('vn %.6f %.6f %.6f\n' % noKey)
else:
# Hard, 1 normal from the face.
noKey = veckey3d(f.no)
if not globalNormals.has_key( noKey ):
globalNormals[noKey] = totno
totno +=1
file.write('vn %.6f %.6f %.6f\n' % noKey)
if not faceuv:
f_image = None
if EXPORT_POLYGROUPS:
# Retrieve the list of vertex groups
vertGroupNames = me.getVertGroupNames()
currentVGroup = ''
# Create a dictionary keyed by face id and listing, for each vertex, the vertex groups it belongs to
vgroupsMap = [[] for _i in xrange(len(me.verts))]
for vertexGroupName in vertGroupNames:
for vIdx, vWeight in me.getVertsFromGroup(vertexGroupName, 1):
vgroupsMap[vIdx].append((vertexGroupName, vWeight))
for f_index, f in enumerate(faces):
f_v= f.v
f_smooth= f.smooth
f_mat = min(f.mat, len(materialNames)-1)
if faceuv:
f_image = f.image
f_uv= f.uv
# MAKE KEY
if faceuv and f_image: # Object is always true.
key = materialNames[f_mat], f_image.name
else:
key = materialNames[f_mat], None # No image, use None instead.
# Write the vertex group
if EXPORT_POLYGROUPS:
if vertGroupNames:
# find what vertext group the face belongs to
theVGroup = findVertexGroupName(f,vgroupsMap)
if theVGroup != currentVGroup:
currentVGroup = theVGroup
file.write('g %s\n' % theVGroup)
# CHECK FOR CONTEXT SWITCH
if key == contextMat:
pass # Context alredy switched, dont do anything
else:
if key[0] == None and key[1] == None:
# Write a null material, since we know the context has changed.
if EXPORT_GROUP_BY_MAT:
file.write('g %s_%s\n' % (fixName(ob.name), fixName(ob.getData(1))) ) # can be mat_image or (null)
file.write('usemtl (null)\n') # mat, image
else:
mat_data= MTL_DICT.get(key)
if not mat_data:
# First add to global dict so we can export to mtl
# Then write mtl
# Make a new names from the mat and image name,
# converting any spaces to underscores with fixName.
# If none image dont bother adding it to the name
if key[1] == None:
mat_data = MTL_DICT[key] = ('%s'%fixName(key[0])), materialItems[f_mat], f_image
else:
mat_data = MTL_DICT[key] = ('%s_%s' % (fixName(key[0]), fixName(key[1]))), materialItems[f_mat], f_image
if EXPORT_GROUP_BY_MAT:
file.write('g %s_%s_%s\n' % (fixName(ob.name), fixName(ob.getData(1)), mat_data[0]) ) # can be mat_image or (null)
file.write('usemtl %s\n' % mat_data[0]) # can be mat_image or (null)
contextMat = key
if f_smooth != contextSmooth:
if f_smooth: # on now off
file.write('s 1\n')
contextSmooth = f_smooth
else: # was off now on
file.write('s off\n')
contextSmooth = f_smooth
file.write('f')
if faceuv:
if EXPORT_NORMALS:
if f_smooth: # Smoothed, use vertex normals
for vi, v in enumerate(f_v):
file.write( ' %d/%d/%d' % (\
v.index+totverts,\
totuvco + uv_face_mapping[f_index][vi],\
globalNormals[ veckey3d(v.no) ])) # vert, uv, normal
else: # No smoothing, face normals
no = globalNormals[ veckey3d(f.no) ]
for vi, v in enumerate(f_v):
file.write( ' %d/%d/%d' % (\
v.index+totverts,\
totuvco + uv_face_mapping[f_index][vi],\
no)) # vert, uv, normal
else: # No Normals
for vi, v in enumerate(f_v):
file.write( ' %d/%d' % (\
v.index+totverts,\
totuvco + uv_face_mapping[f_index][vi])) # vert, uv
face_vert_index += len(f_v)
else: # No UV's
if EXPORT_NORMALS:
if f_smooth: # Smoothed, use vertex normals
for v in f_v:
file.write( ' %d//%d' % (\
v.index+totverts,\
globalNormals[ veckey3d(v.no) ]))
else: # No smoothing, face normals
no = globalNormals[ veckey3d(f.no) ]
for v in f_v:
file.write( ' %d//%d' % (\
v.index+totverts,\
no))
else: # No Normals
for v in f_v:
file.write( ' %d' % (\
v.index+totverts))
file.write('\n')
# Write edges.
if EXPORT_EDGES:
LOOSE= Mesh.EdgeFlags.LOOSE
for ed in edges:
if ed.flag & LOOSE:
file.write('f %d %d\n' % (ed.v1.index+totverts, ed.v2.index+totverts))
# Make the indicies global rather then per mesh
totverts += len(me.verts)
if faceuv:
totuvco += uv_unique_count
me.verts= None
file.close()
# Now we have all our materials, save them
if EXPORT_MTL:
write_mtl(mtlfilename)
if EXPORT_COPY_IMAGES:
dest_dir = filename
# Remove chars until we are just the path.
while dest_dir and dest_dir[-1] not in '\\/':
dest_dir = dest_dir[:-1]
if dest_dir:
copy_images(dest_dir)
else:
print '\tError: "%s" could not be used as a base for an image path.' % filename
print "OBJ Export time: %.2f" % (sys.time() - time1)
def write_ui(filename):
if not filename.lower().endswith('.obj'):
filename += '.obj'
if not BPyMessages.Warning_SaveOver(filename):
return
global EXPORT_APPLY_MODIFIERS, EXPORT_ROTX90, EXPORT_TRI, EXPORT_EDGES,\
EXPORT_NORMALS, EXPORT_NORMALS_HQ, EXPORT_UV,\
EXPORT_MTL, EXPORT_SEL_ONLY, EXPORT_ALL_SCENES,\
EXPORT_ANIMATION, EXPORT_COPY_IMAGES, EXPORT_BLEN_OBS,\
EXPORT_GROUP_BY_OB, EXPORT_GROUP_BY_MAT, EXPORT_KEEP_VERT_ORDER,\
EXPORT_POLYGROUPS, EXPORT_CURVE_AS_NURBS
EXPORT_APPLY_MODIFIERS = Draw.Create(0)
EXPORT_ROTX90 = Draw.Create(1)
EXPORT_TRI = Draw.Create(0)
EXPORT_EDGES = Draw.Create(1)
EXPORT_NORMALS = Draw.Create(0)
EXPORT_NORMALS_HQ = Draw.Create(0)
EXPORT_UV = Draw.Create(1)
EXPORT_MTL = Draw.Create(1)
EXPORT_SEL_ONLY = Draw.Create(1)
EXPORT_ALL_SCENES = Draw.Create(0)
EXPORT_ANIMATION = Draw.Create(0)
EXPORT_COPY_IMAGES = Draw.Create(0)
EXPORT_BLEN_OBS = Draw.Create(0)
EXPORT_GROUP_BY_OB = Draw.Create(0)
EXPORT_GROUP_BY_MAT = Draw.Create(0)
EXPORT_KEEP_VERT_ORDER = Draw.Create(1)
EXPORT_POLYGROUPS = Draw.Create(0)
EXPORT_CURVE_AS_NURBS = Draw.Create(1)
# Old UI
'''
# removed too many options are bad!
# Get USER Options
pup_block = [\
('Context...'),\
('Selection Only', EXPORT_SEL_ONLY, 'Only export objects in visible selection. Else export whole scene.'),\
('All Scenes', EXPORT_ALL_SCENES, 'Each scene as a separate OBJ file.'),\
('Animation', EXPORT_ANIMATION, 'Each frame as a numbered OBJ file.'),\
('Object Prefs...'),\
('Apply Modifiers', EXPORT_APPLY_MODIFIERS, 'Use transformed mesh data from each object. May break vert order for morph targets.'),\
('Rotate X90', EXPORT_ROTX90 , 'Rotate on export so Blenders UP is translated into OBJs UP'),\
('Keep Vert Order', EXPORT_KEEP_VERT_ORDER, 'Keep vert and face order, disables some other options.'),\
('Extra Data...'),\
('Edges', EXPORT_EDGES, 'Edges not connected to faces.'),\
('Normals', EXPORT_NORMALS, 'Export vertex normal data (Ignored on import).'),\
('High Quality Normals', EXPORT_NORMALS_HQ, 'Calculate high quality normals for rendering.'),\
('UVs', EXPORT_UV, 'Export texface UV coords.'),\
('Materials', EXPORT_MTL, 'Write a separate MTL file with the OBJ.'),\
('Copy Images', EXPORT_COPY_IMAGES, 'Copy image files to the export directory, never overwrite.'),\
('Triangulate', EXPORT_TRI, 'Triangulate quads.'),\
('Grouping...'),\
('Objects', EXPORT_BLEN_OBS, 'Export blender objects as "OBJ objects".'),\
('Object Groups', EXPORT_GROUP_BY_OB, 'Export blender objects as "OBJ Groups".'),\
('Material Groups', EXPORT_GROUP_BY_MAT, 'Group by materials.'),\
]
if not Draw.PupBlock('Export...', pup_block):
return
'''
# BEGIN ALTERNATIVE UI *******************
if True:
EVENT_NONE = 0
EVENT_EXIT = 1
EVENT_REDRAW = 2
EVENT_EXPORT = 3
GLOBALS = {}
GLOBALS['EVENT'] = EVENT_REDRAW
#GLOBALS['MOUSE'] = Window.GetMouseCoords()
GLOBALS['MOUSE'] = [i/2 for i in Window.GetScreenSize()]
def obj_ui_set_event(e,v):
GLOBALS['EVENT'] = e
def do_split(e,v):
global EXPORT_BLEN_OBS, EXPORT_GROUP_BY_OB, EXPORT_GROUP_BY_MAT, EXPORT_APPLY_MODIFIERS, KEEP_VERT_ORDER, EXPORT_POLYGROUPS
if EXPORT_BLEN_OBS.val or EXPORT_GROUP_BY_OB.val or EXPORT_GROUP_BY_MAT.val or EXPORT_APPLY_MODIFIERS.val:
EXPORT_KEEP_VERT_ORDER.val = 0
else:
EXPORT_KEEP_VERT_ORDER.val = 1
def do_vertorder(e,v):
global EXPORT_BLEN_OBS, EXPORT_GROUP_BY_OB, EXPORT_GROUP_BY_MAT, EXPORT_APPLY_MODIFIERS, KEEP_VERT_ORDER
if EXPORT_KEEP_VERT_ORDER.val:
EXPORT_BLEN_OBS.val = EXPORT_GROUP_BY_OB.val = EXPORT_GROUP_BY_MAT.val = EXPORT_APPLY_MODIFIERS.val = 0
else:
if not (EXPORT_BLEN_OBS.val or EXPORT_GROUP_BY_OB.val or EXPORT_GROUP_BY_MAT.val or EXPORT_APPLY_MODIFIERS.val):
EXPORT_KEEP_VERT_ORDER.val = 1
def do_help(e,v):
url = __url__[0]
print 'Trying to open web browser with documentation at this address...'
print '\t' + url
try:
import webbrowser
webbrowser.open(url)
except:
print '...could not open a browser window.'
def obj_ui():
ui_x, ui_y = GLOBALS['MOUSE']
# Center based on overall pup size
ui_x -= 165
ui_y -= 140
global EXPORT_APPLY_MODIFIERS, EXPORT_ROTX90, EXPORT_TRI, EXPORT_EDGES,\
EXPORT_NORMALS, EXPORT_NORMALS_HQ, EXPORT_UV,\
EXPORT_MTL, EXPORT_SEL_ONLY, EXPORT_ALL_SCENES,\
EXPORT_ANIMATION, EXPORT_COPY_IMAGES, EXPORT_BLEN_OBS,\
EXPORT_GROUP_BY_OB, EXPORT_GROUP_BY_MAT, EXPORT_KEEP_VERT_ORDER,\
EXPORT_POLYGROUPS, EXPORT_CURVE_AS_NURBS
Draw.Label('Context...', ui_x+9, ui_y+239, 220, 20)
Draw.BeginAlign()
EXPORT_SEL_ONLY = Draw.Toggle('Selection Only', EVENT_NONE, ui_x+9, ui_y+219, 110, 20, EXPORT_SEL_ONLY.val, 'Only export objects in visible selection. Else export whole scene.')
EXPORT_ALL_SCENES = Draw.Toggle('All Scenes', EVENT_NONE, ui_x+119, ui_y+219, 110, 20, EXPORT_ALL_SCENES.val, 'Each scene as a separate OBJ file.')
EXPORT_ANIMATION = Draw.Toggle('Animation', EVENT_NONE, ui_x+229, ui_y+219, 110, 20, EXPORT_ANIMATION.val, 'Each frame as a numbered OBJ file.')
Draw.EndAlign()
Draw.Label('Output Options...', ui_x+9, ui_y+189, 220, 20)
Draw.BeginAlign()
EXPORT_APPLY_MODIFIERS = Draw.Toggle('Apply Modifiers', EVENT_REDRAW, ui_x+9, ui_y+170, 110, 20, EXPORT_APPLY_MODIFIERS.val, 'Use transformed mesh data from each object. May break vert order for morph targets.', do_split)
EXPORT_ROTX90 = Draw.Toggle('Rotate X90', EVENT_NONE, ui_x+119, ui_y+170, 110, 20, EXPORT_ROTX90.val, 'Rotate on export so Blenders UP is translated into OBJs UP')
EXPORT_COPY_IMAGES = Draw.Toggle('Copy Images', EVENT_NONE, ui_x+229, ui_y+170, 110, 20, EXPORT_COPY_IMAGES.val, 'Copy image files to the export directory, never overwrite.')
Draw.EndAlign()
Draw.Label('Export...', ui_x+9, ui_y+139, 220, 20)
Draw.BeginAlign()
EXPORT_EDGES = Draw.Toggle('Edges', EVENT_NONE, ui_x+9, ui_y+120, 50, 20, EXPORT_EDGES.val, 'Edges not connected to faces.')
EXPORT_TRI = Draw.Toggle('Triangulate', EVENT_NONE, ui_x+59, ui_y+120, 70, 20, EXPORT_TRI.val, 'Triangulate quads.')
Draw.EndAlign()
Draw.BeginAlign()
EXPORT_MTL = Draw.Toggle('Materials', EVENT_NONE, ui_x+139, ui_y+120, 70, 20, EXPORT_MTL.val, 'Write a separate MTL file with the OBJ.')
EXPORT_UV = Draw.Toggle('UVs', EVENT_NONE, ui_x+209, ui_y+120, 31, 20, EXPORT_UV.val, 'Export texface UV coords.')
Draw.EndAlign()
Draw.BeginAlign()
EXPORT_NORMALS = Draw.Toggle('Normals', EVENT_NONE, ui_x+250, ui_y+120, 59, 20, EXPORT_NORMALS.val, 'Export vertex normal data (Ignored on import).')
EXPORT_NORMALS_HQ = Draw.Toggle('HQ', EVENT_NONE, ui_x+309, ui_y+120, 31, 20, EXPORT_NORMALS_HQ.val, 'Calculate high quality normals for rendering.')
Draw.EndAlign()
EXPORT_POLYGROUPS = Draw.Toggle('Polygroups', EVENT_REDRAW, ui_x+9, ui_y+95, 120, 20, EXPORT_POLYGROUPS.val, 'Export vertex groups as OBJ groups (one group per face approximation).')
EXPORT_CURVE_AS_NURBS = Draw.Toggle('Nurbs', EVENT_NONE, ui_x+139, ui_y+95, 100, 20, EXPORT_CURVE_AS_NURBS.val, 'Export 3D nurbs curves and polylines as OBJ curves, (bezier not supported).')
Draw.Label('Blender Objects as OBJ:', ui_x+9, ui_y+59, 220, 20)
Draw.BeginAlign()
EXPORT_BLEN_OBS = Draw.Toggle('Objects', EVENT_REDRAW, ui_x+9, ui_y+39, 60, 20, EXPORT_BLEN_OBS.val, 'Export blender objects as "OBJ objects".', do_split)
EXPORT_GROUP_BY_OB = Draw.Toggle('Groups', EVENT_REDRAW, ui_x+69, ui_y+39, 60, 20, EXPORT_GROUP_BY_OB.val, 'Export blender objects as "OBJ Groups".', do_split)
EXPORT_GROUP_BY_MAT = Draw.Toggle('Material Groups', EVENT_REDRAW, ui_x+129, ui_y+39, 100, 20, EXPORT_GROUP_BY_MAT.val, 'Group by materials.', do_split)
Draw.EndAlign()
EXPORT_KEEP_VERT_ORDER = Draw.Toggle('Keep Vert Order', EVENT_REDRAW, ui_x+239, ui_y+39, 100, 20, EXPORT_KEEP_VERT_ORDER.val, 'Keep vert and face order, disables some other options. Use for morph targets.', do_vertorder)
Draw.BeginAlign()
Draw.PushButton('Online Help', EVENT_REDRAW, ui_x+9, ui_y+9, 110, 20, 'Load the wiki page for this script', do_help)
Draw.PushButton('Cancel', EVENT_EXIT, ui_x+119, ui_y+9, 110, 20, '', obj_ui_set_event)
Draw.PushButton('Export', EVENT_EXPORT, ui_x+229, ui_y+9, 110, 20, 'Export with these settings', obj_ui_set_event)
Draw.EndAlign()
# hack so the toggle buttons redraw. this is not nice at all
while GLOBALS['EVENT'] not in (EVENT_EXIT, EVENT_EXPORT):
Draw.UIBlock(obj_ui, 0)
if GLOBALS['EVENT'] != EVENT_EXPORT:
return
# END ALTERNATIVE UI *********************
if EXPORT_KEEP_VERT_ORDER.val:
EXPORT_BLEN_OBS.val = False
EXPORT_GROUP_BY_OB.val = False
EXPORT_GROUP_BY_MAT.val = False
EXPORT_APPLY_MODIFIERS.val = False
Window.EditMode(0)
Window.WaitCursor(1)
EXPORT_APPLY_MODIFIERS = EXPORT_APPLY_MODIFIERS.val
EXPORT_ROTX90 = EXPORT_ROTX90.val
EXPORT_TRI = EXPORT_TRI.val
EXPORT_EDGES = EXPORT_EDGES.val
EXPORT_NORMALS = EXPORT_NORMALS.val
EXPORT_NORMALS_HQ = EXPORT_NORMALS_HQ.val
EXPORT_UV = EXPORT_UV.val
EXPORT_MTL = EXPORT_MTL.val
EXPORT_SEL_ONLY = EXPORT_SEL_ONLY.val
EXPORT_ALL_SCENES = EXPORT_ALL_SCENES.val
EXPORT_ANIMATION = EXPORT_ANIMATION.val
EXPORT_COPY_IMAGES = EXPORT_COPY_IMAGES.val
EXPORT_BLEN_OBS = EXPORT_BLEN_OBS.val
EXPORT_GROUP_BY_OB = EXPORT_GROUP_BY_OB.val
EXPORT_GROUP_BY_MAT = EXPORT_GROUP_BY_MAT.val
EXPORT_KEEP_VERT_ORDER = EXPORT_KEEP_VERT_ORDER.val
EXPORT_POLYGROUPS = EXPORT_POLYGROUPS.val
EXPORT_CURVE_AS_NURBS = EXPORT_CURVE_AS_NURBS.val
base_name, ext = splitExt(filename)
context_name = [base_name, '', '', ext] # basename, scene_name, framenumber, extension
# Use the options to export the data using write()
# def write(filename, objects, EXPORT_EDGES=False, EXPORT_NORMALS=False, EXPORT_MTL=True, EXPORT_COPY_IMAGES=False, EXPORT_APPLY_MODIFIERS=True):
orig_scene = Scene.GetCurrent()
if EXPORT_ALL_SCENES:
export_scenes = Scene.Get()
else:
export_scenes = [orig_scene]
# Export all scenes.
for scn in export_scenes:
scn.makeCurrent() # If alredy current, this is not slow.
context = scn.getRenderingContext()
orig_frame = Blender.Get('curframe')
if EXPORT_ALL_SCENES: # Add scene name into the context_name
context_name[1] = '_%s' % BPySys.cleanName(scn.name) # WARNING, its possible that this could cause a collision. we could fix if were feeling parranoied.
# Export an animation?
if EXPORT_ANIMATION:
scene_frames = xrange(context.startFrame(), context.endFrame()+1) # up to and including the end frame.
else:
scene_frames = [orig_frame] # Dont export an animation.
# Loop through all frames in the scene and export.
for frame in scene_frames:
if EXPORT_ANIMATION: # Add frame to the filename.
context_name[2] = '_%.6d' % frame
Blender.Set('curframe', frame)
if EXPORT_SEL_ONLY:
export_objects = scn.objects.context
else:
export_objects = scn.objects
full_path= ''.join(context_name)
# erm... bit of a problem here, this can overwrite files when exporting frames. not too bad.
# EXPORT THE FILE.
write(full_path, export_objects,\
EXPORT_TRI, EXPORT_EDGES, EXPORT_NORMALS,\
EXPORT_NORMALS_HQ, EXPORT_UV, EXPORT_MTL,\
EXPORT_COPY_IMAGES, EXPORT_APPLY_MODIFIERS,\
EXPORT_ROTX90, EXPORT_BLEN_OBS,\
EXPORT_GROUP_BY_OB, EXPORT_GROUP_BY_MAT, EXPORT_KEEP_VERT_ORDER,\
EXPORT_POLYGROUPS, EXPORT_CURVE_AS_NURBS)
Blender.Set('curframe', orig_frame)
# Restore old active scene.
orig_scene.makeCurrent()
Window.WaitCursor(0)
if __name__ == '__main__':
Window.FileSelector(write_ui, 'Export Wavefront OBJ', sys.makename(ext='.obj'))

View File

@@ -1,111 +0,0 @@
#!BPY
"""
Name: 'Same Weights...'
Blender: 245
Group: 'FaceSelect'
Tooltip: 'Select same faces with teh same weight for the active group.'
"""
__author__ = ["Campbell Barton aka ideasman42"]
__url__ = ["www.blender.org", "blenderartists.org", "www.python.org"]
__version__ = "0.1"
__bpydoc__ = """\
Select Same Weights
Select same weights as the active face on the active group.
"""
# ***** BEGIN GPL LICENSE BLOCK *****
#
# Script copyright (C) Campbell J Barton
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
from Blender import Scene, Draw, Mesh
import BPyMesh
def selSameWeights(me, PREF_TOLERENCE):
# Check for missing data
if not me.faceUV: return
act_group= me.activeGroup
if not act_group: return
act_face = me.faces[me.activeFace]
if act_face == None: return
groupNames, vWeightDict= BPyMesh.meshWeight2Dict(me)
def get_face_weight(f):
'''
Return the faces median weight and weight range.
'''
wmin = 1.0
wmax = 0.0
w = 0.0
for v in f:
try:
new_weight = vWeightDict[v.index][act_group]
if wmin > new_weight: wmin = new_weight
if wmax < new_weight: wmax = new_weight
w += new_weight
except:
pass
return w, wmax-wmin # weight, range
weight_from, weight_range_from = get_face_weight(act_face)
for f in me.faces:
if (not f.sel) and f != act_face:
weight, weight_range = get_face_weight(f)
# Compare the 2 faces weight difference and difference in their contrast.
if\
abs(weight - weight_from) <= PREF_TOLERENCE and\
abs(weight_range - weight_range_from) <= PREF_TOLERENCE:
f.sel = True
def main():
scn= Scene.GetCurrent()
ob= scn.objects.active
if not ob or ob.type != 'Mesh':
Draw.PupMenu('Error, no active mesh object, aborting.')
return
me= ob.getData(mesh=1)
PREF_TOLERENCE= Draw.Create(0.1)
pup_block= [\
('Tolerence:', PREF_TOLERENCE, 0.01, 1.0, 'Tolerence for selecting faces of the same weight.'),\
]
if not Draw.PupBlock('Select Same Weight...', pup_block):
return
PREF_TOLERENCE= PREF_TOLERENCE.val
selSameWeights(me, PREF_TOLERENCE)
if __name__=='__main__':
main()

File diff suppressed because one or more lines are too long

View File

@@ -1,835 +0,0 @@
#!BPY
"""
Name: 'FLT DOF Editor'
Blender: 240
Group: 'Misc'
Tooltip: 'Degree of Freedom editor for FLT nodes'
"""
__author__ = "Geoffrey Bantle"
__version__ = "1.0 11/21/07"
__email__ = ('scripts', 'Author, ')
__url__ = ('blender', 'blenderartists.org')
__bpydoc__ ="""\
This script provides tools for working with OpenFlight databases in Blender. OpenFlight is a
registered trademark of MultiGen-Paradigm, Inc.
Feature overview and more availible at:
http://wiki.blender.org/index.php/Scripts/Manual/FLTools
"""
# --------------------------------------------------------------------------
# flt_palettemanager.py version 0.1 2005/04/08
# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
# Copyright (C) 2007: Blender Foundation
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
import Blender.Draw as Draw
from Blender.BGL import *
import Blender
import flt_properties
reload(flt_properties)
from flt_properties import *
#event codes
evcode = {
"DOF_MAKE" : 100,
"DOF_UPDATE" : 138,
"DOF_DELETE" : 101,
"DOF_TRANSX" : 102,
"DOF_TRANSY" : 103,
"DOF_TRANSZ" : 104,
"DOF_ROTX" : 105,
"DOF_ROTY" : 106,
"DOF_ROTZ" : 107,
"DOF_SCALEX" : 108,
"DOF_SCALEY" : 109,
"DOF_SCALEZ" : 110,
"DOF_MIN_TRANSX" : 111,
"DOF_MIN_TRANSY" : 112,
"DOF_MIN_TRANSZ" : 113,
"DOF_MIN_ROTX" : 114,
"DOF_MIN_ROTY" : 115,
"DOF_MIN_ROTZ" : 116,
"DOF_MIN_SCALEX" : 117,
"DOF_MIN_SCALEY" : 118,
"DOF_MIN_SCALEZ" : 119,
"DOF_MAX_TRANSX" : 120,
"DOF_MAX_TRANSY" : 121,
"DOF_MAX_TRANSZ" : 122,
"DOF_MAX_ROTX" : 123,
"DOF_MAX_ROTY" : 124,
"DOF_MAX_ROTZ" : 125,
"DOF_MAX_SCALEX" : 126,
"DOF_MAX_SCALEY" : 127,
"DOF_MAX_SCALEZ" : 128,
"DOF_STEP_TRANSX" : 129,
"DOF_STEP_TRANSY" : 130,
"DOF_STEP_TRANSZ" : 131,
"DOF_STEP_ROTX" : 132,
"DOF_STEP_ROTY" : 133,
"DOF_STEP_ROTZ" : 134,
"DOF_STEP_SCALEX" : 135,
"DOF_STEP_SCALEY" : 136,
"DOF_STEP_SCALEZ" : 137
}
#system
DOF_MAKE = None
DOF_UPDATE = None
DOF_DELETE = None
#toggle buttons
DOF_TRANSX = None
DOF_TRANSY = None
DOF_TRANSZ = None
DOF_ROTX = None
DOF_ROTY = None
DOF_ROTZ = None
DOF_SCALEX = None
DOF_SCALEY = None
DOF_SCALEZ = None
#Minimums
DOF_MIN_TRANSX = None
DOF_MIN_TRANSY = None
DOF_MIN_TRANSZ = None
DOF_MIN_ROTX = None
DOF_MIN_ROTY = None
DOF_MIN_ROTZ = None
DOF_MIN_SCALEX = None
DOF_MIN_SCALEY = None
DOF_MIN_SCALEZ = None
#maximums
DOF_MAX_TRANSX = None
DOF_MAX_TRANSY = None
DOF_MAX_TRANSZ = None
DOF_MAX_ROTX = None
DOF_MAX_ROTY = None
DOF_MAX_ROTZ = None
DOF_MAX_SCALEX = None
DOF_MAX_SCALEY = None
DOF_MAX_SCALEZ = None
#step
DOF_STEP_TRANSX = None
DOF_STEP_TRANSY = None
DOF_STEP_TRANSZ = None
DOF_STEP_ROTX = None
DOF_STEP_ROTY = None
DOF_STEP_ROTZ = None
DOF_STEP_SCALEX = None
DOF_STEP_SCALEY = None
DOF_STEP_SCALEZ = None
#labels
DOF_ROTSTRING = None
DOF_TRANSTRING = None
DOF_SCALESTRING = None
DOF_EDITLABEL = None
#make ID props easier/morereadable
zmin = '14d!ZMIN'
zmax = '15d!ZMAX'
zcur = '16d!ZCUR'
zstep = '17d!ZSTEP'
ymin = '18d!YMIN'
ymax = '19d!YMAX'
ycur = '20d!YCUR'
ystep = '21d!YSTEP'
xmin = '22d!XMIN'
xmax = '23d!XMAX'
xcur = '24d!XCUR'
xstep = '25d!XSTEP'
pitchmin = '26d!PITCH-MIN'
pitchmax = '27d!PITCH-MAX'
pitchcur = '28d!PITCH-CUR'
pitchstep = '29d!PITCH-STEP'
rollmin = '30d!ROLL-MIN'
rollmax = '31d!ROLL-MAX'
rollcur = '32d!ROLL-CUR'
rollstep = '33d!ROLL-STEP'
yawmin = '34d!YAW-MIN'
yawmax = '35d!YAW-MAX'
yawcur = '36d!YAW-CUR'
yawstep = '37d!YAW-STEP'
zscalemin = '38d!ZSIZE-MIN'
zscalemax = '39d!ZSIZE-MAX'
zscalecur = '40d!ZSIZE-CUR'
zscalestep = '41d!ZSIZE-STEP'
yscalemin = '42d!YSIZE-MIN'
yscalemax = '43d!YSIZE-MAX'
yscalecur = '44d!YSIZE-CUR'
yscalestep = '45d!YSIZE-STEP'
xscalemin = '46d!XSIZE-MIN'
xscalemax = '47d!XSIZE-MAX'
xscalecur = '48d!XSIZE-CUR'
xscalestep = '49d!XSIZE-STEP'
def update_state():
state = dict()
state["activeScene"] = Blender.Scene.GetCurrent()
state["activeObject"] = state["activeScene"].objects.active
if state["activeObject"] and not state["activeObject"].sel:
state["activeObject"] = None
state["activeMesh"] = None
if state["activeObject"] and state["activeObject"].type == 'Mesh':
state["activeMesh"] = state["activeObject"].getData(mesh=True)
state["activeFace"] = None
if state["activeMesh"]:
if state["activeMesh"].faceUV and state["activeMesh"].activeFace != None:
state["activeFace"] = state["activeMesh"].faces[state["activeMesh"].activeFace]
#update editmode
state["editmode"] = Blender.Window.EditMode()
return state
def idprops_append(object, typecode, props):
object.properties["FLT"] = dict()
object.properties["FLT"]['type'] = typecode
for prop in props:
object.properties["FLT"][prop] = props[prop]
object.properties["FLT"]['3t8!id'] = object.name
def idprops_kill():
state = update_state()
if state["activeObject"] and state["activeObject"].properties.has_key('FLT'):
state["activeObject"].properties.pop('FLT')
def idprops_copy(source):
state = update_state()
if source.properties.has_key('FLT'):
for object in state["activeScene"].objects:
if object.sel and object != source and (state["activeScene"].Layers & object.Layers):
idprops_kill(object)
object.properties['FLT'] = dict()
for key in source.properties['FLT']:
object.properties['FLT'][key] = source.properties['FLT'][key]
def select_by_typecode(typecode):
state = update_state()
for object in state["activeScene"].objects:
if object.properties.has_key('FLT') and object.properties['FLT']['type'] == typecode and state["activeScene"].Layers & object.Layers:
object.select(1)
def DOF_get_frame():
state = update_state()
if not state["activeObject"] and not id_props_type(state["activeObject"], 14):
return
#Warning! assumes 1 BU == 10 meters.
#do origin
state["activeObject"].properties['FLT']['5d!ORIGX'] = state["activeObject"].getLocation('worldspace')[0]*10.0
state["activeObject"].properties['FLT']['6d!ORIGY'] = state["activeObject"].getLocation('worldspace')[1]*10.0
state["activeObject"].properties['FLT']['7d!ORIGZ'] = state["activeObject"].getLocation('worldspace')[2]*10.0
#do X axis
x = Blender.Mathutils.Vector(1.0,0.0,0.0)
x = x * state["activeObject"].getMatrix('worldspace')
x = x * 10.0
state["activeObject"].properties['FLT']['8d!XAXIS-X'] = x[0]
state["activeObject"].properties['FLT']['9d!XAXIS-Y'] = x[1]
state["activeObject"].properties['FLT']['10d!XAXIS-Z'] = x[2]
#do X/Y plane
x = Blender.Mathutils.Vector(0.0,1.0,0.0)
x.normalize()
x = x * state["activeObject"].getMatrix('worldspace')
x = x * 10.0
state["activeObject"].properties['FLT']['11d!XYPLANE-X'] = x[0]
state["activeObject"].properties['FLT']['12d!XYPLANE-Y'] = x[1]
state["activeObject"].properties['FLT']['13d!XZPLANE-Z'] = x[2]
def idprops_type(object, typecode):
if object.properties.has_key('FLT') and object.properties['FLT'].has_key('type') and object.properties['FLT']['type'] == typecode:
return True
return False
#ui type code
def get_prop(typecode, prop):
state = update_state()
if state["activeObject"] and idprops_type(state["activeObject"], typecode):
props = state["activeObject"].properties['FLT']
else:
props = flt_properties.FLTDOF
return props[prop]
def set_prop(typecode, prop, value):
state = update_state()
if state["activeObject"] and idprops_type(state["activeObject"],typecode):
state["activeObject"].properties['FLT'][prop] = value
lockxtrans = (1 << 31)
lockytrans = (1 << 30)
lockztrans = (1 << 29)
lockxrot = (1 << 28)
lockyrot = (1 << 27)
lockzrot = (1 << 26)
lockxscale = (1 << 25)
lockyscale = (1 << 24)
lockzscale = (1 << 23)
def get_lockmask(mask):
state = update_state()
if state["activeObject"]:
flag = get_prop(14,'50I!FLAG')
if flag & mask:
return True
return False
def set_lockmask(mask):
state = update_state()
if state["activeObject"] and idprops_type(state["activeObject"], 14):
oldvalue = state["activeObject"].properties['FLT']['50I!FLAG']
oldvalue = struct.unpack('>I', struct.pack('>i', oldvalue))[0]
oldvalue |= mask
state["activeObject"].properties['FLT']['50I!FLAG'] = struct.unpack('>i', struct.pack(">I", oldvalue))[0]
def clear_lockmask(mask):
state = update_state()
if state["activeObject"] and idprops_type(state["activeObject"], 14):
oldvalue = state["activeObject"].properties['FLT']['50I!FLAG']
oldvalue = struct.unpack('>I', struct.pack('>i', oldvalue))[0]
oldvalue &= ~mask
state["activeObject"].properties['FLT']['50I!FLAG'] = struct.unpack('>i',struct.pack('>I',oldvalue))[0]
def create_dof():
state = update_state()
actobj = state["activeObject"]
if actobj and not idprops_type(actobj, 14):
idprops_kill()
idprops_append(actobj,14, flt_properties.FLTDOF)
DOF_get_frame()
def event(evt,val):
if evt == Draw.ESCKEY:
Draw.Exit()
def but_event(evt):
global DOF_MAKE
global DOF_UPDATE
global DOF_DELETE
global DOF_TRANSX
global DOF_TRANSY
global DOF_TRANSZ
global DOF_ROTX
global DOF_ROTY
global DOF_ROTZ
global DOF_SCALEX
global DOF_SCALEY
global DOF_SCALEZ
global DOF_MIN_TRANSX
global DOF_MIN_TRANSY
global DOF_MIN_TRANSZ
global DOF_MIN_ROTX
global DOF_MIN_ROTY
global DOF_MIN_ROTZ
global DOF_MIN_SCALEX
global DOF_MIN_SCALEY
global DOF_MIN_SCALEZ
global DOF_MAX_TRANSX
global DOF_MAX_TRANSY
global DOF_MAX_TRANSZ
global DOF_MAX_ROTX
global DOF_MAX_ROTY
global DOF_MAX_ROTZ
global DOF_MAX_SCALEX
global DOF_MAX_SCALEY
global DOF_MAX_SCALEZ
global DOF_STEP_TRANSX
global DOF_STEP_TRANSY
global DOF_STEP_TRANSZ
global DOF_STEP_ROTX
global DOF_STEP_ROTY
global DOF_STEP_ROTZ
global DOF_STEP_SCALEX
global DOF_STEP_SCALEY
global DOF_STEP_SCALEZ
#labels
global DOF_ROTSTRING
global DOF_TRANSTRING
global DOF_SCALESTRING
#masks
global lockxtrans
global lockytrans
global lockztrans
global lockxrot
global lockyrot
global lockzrot
global lockxscale
global lockyscale
global lockzscale
global zmin
global zmax
global zcur
global zstep
global ymin
global ymax
global ycur
global ystep
global xmin
global xmax
global xcur
global xstep
global pitchmin
global pitchmax
global pitchcur
global pitchstep
global rollmin
global rollmax
global rollcur
global rollstep
global yawmin
global yawmax
global yawcur
global yawstep
global zscalemin
global zscalemax
global zscalecur
global zscalestep
global yscalemin
global yscalemax
global yscalecur
global yscalestep
global xscalemin
global xscalemax
global xscalecur
global xscalestep
#do "system" events
if evt == evcode["DOF_MAKE"]:
create_dof()
if evt == evcode["DOF_UPDATE"]:
DOF_get_frame()
if evt == evcode["DOF_DELETE"]:
idprops_kill()
#do translation lock events
if evt == evcode["DOF_TRANSX"]:
if DOF_TRANSX.val == True:
set_lockmask(lockxtrans)
else:
clear_lockmask(lockxtrans)
if evt == evcode["DOF_TRANSY"]:
if DOF_TRANSY.val == True:
set_lockmask(lockytrans)
else:
clear_lockmask(lockytrans)
if evt == evcode["DOF_TRANSZ"]:
if DOF_TRANSZ.val == True:
set_lockmask(lockztrans)
else:
clear_lockmask(lockztrans)
#do rotation lock events
if evt == evcode["DOF_ROTX"]:
if DOF_ROTX.val == True:
set_lockmask(lockxrot)
else:
clear_lockmask(lockxrot)
if evt == evcode["DOF_ROTY"]:
if DOF_ROTY.val == True:
set_lockmask(lockyrot)
else:
clear_lockmask(lockyrot)
if evt == evcode["DOF_ROTZ"]:
if DOF_ROTZ.val == True:
set_lockmask(lockzrot)
else:
clear_lockmask(lockzrot)
#do scale lock events
if evt == evcode["DOF_SCALEX"]:
if DOF_SCALEX.val == True:
set_lockmask(lockxscale)
else:
clear_lockmask(lockxscale)
if evt == evcode["DOF_SCALEY"]:
if DOF_SCALEY.val == True:
set_lockmask(lockyscale)
else:
clear_lockmask(lockyscale)
if evt == evcode["DOF_SCALEZ"]:
if DOF_SCALEZ.val == True:
set_lockmask(lockzscale)
else:
clear_lockmask(lockzscale)
#do translation buttons
if evt == evcode["DOF_MIN_TRANSX"]:
set_prop(14, xmin, DOF_MIN_TRANSX.val)
if evt == evcode["DOF_MAX_TRANSX"]:
set_prop(14,xmax, DOF_MAX_TRANSX.val)
if evt == evcode["DOF_STEP_TRANSX"]:
set_prop(14,xstep, DOF_STEP_TRANSX.val)
if evt == evcode["DOF_MIN_TRANSY"]:
set_prop(14, ymin, DOF_MIN_TRANSY.val)
if evt == evcode["DOF_MAX_TRANSY"]:
set_prop(14,ymax, DOF_MAX_TRANSY.val)
if evt == evcode["DOF_STEP_TRANSY"]:
set_prop(14,ystep, DOF_STEP_TRANSY.val)
if evt == evcode["DOF_MIN_TRANSZ"]:
set_prop(14, zmin, DOF_MIN_TRANSZ.val)
if evt == evcode["DOF_MAX_TRANSZ"]:
set_prop(14, zmax, DOF_MAX_TRANSZ.val)
if evt == evcode["DOF_STEP_TRANSZ"]:
set_prop(14, zstep, DOF_STEP_TRANSZ.val)
#do rotation buttons
if evt == evcode["DOF_MIN_ROTX"]:
set_prop(14, pitchmin, DOF_MIN_ROTX.val)
if evt == evcode["DOF_MAX_ROTX"]:
set_prop(14, pitchmax, DOF_MAX_ROTX.val)
if evt == evcode["DOF_STEP_ROTX"]:
set_prop(14, pitchstep, DOF_STEP_ROTX.val)
if evt == evcode["DOF_MIN_ROTY"]:
set_prop(14, rollmin, DOF_MIN_ROTY.val)
if evt == evcode["DOF_MAX_ROTY"]:
set_prop(14, rollmax, DOF_MAX_ROTY.val)
if evt == evcode["DOF_STEP_ROTY"]:
set_prop(14, rollstep, DOF_STEP_ROTY.val)
if evt == evcode["DOF_MIN_ROTZ"]:
set_prop(14, yawmin, DOF_MIN_ROTZ.val)
if evt == evcode["DOF_MAX_ROTZ"]:
set_prop(14, yawmax, DOF_MAX_ROTZ.val)
if evt == evcode["DOF_STEP_ROTZ"]:
set_prop(14, yawstep, DOF_STEP_ROTZ.val)
#do scale buttons
if evt == evcode["DOF_MIN_SCALEX"]:
set_prop(14, xscalemin, DOF_MIN_SCALEX.val)
if evt == evcode["DOF_MAX_SCALEX"]:
set_prop(14, xscalemax, DOF_MAX_SCALEX.val)
if evt == evcode["DOF_STEP_SCALEX"]:
set_prop(14, xscalestep, DOF_STEP_SCALEX.val)
if evt == evcode["DOF_MIN_SCALEY"]:
set_prop(14, yscalemin, DOF_MIN_SCALEY.val)
if evt == evcode["DOF_MAX_SCALEY"]:
set_prop(14, yscalemax, DOF_MAX_SCALEY.val)
if evt == evcode["DOF_STEP_SCALEY"]:
set_prop(14, yscalestep, DOF_STEP_SCALEY.val)
if evt == evcode["DOF_MIN_SCALEZ"]:
set_prop(14, zscalemin, DOF_MIN_SCALEZ.val)
if evt == evcode["DOF_MAX_SCALEZ"]:
set_prop(14, zscalemax, DOF_MAX_SCALEZ.val)
if evt == evcode["DOF_STEP_SCALEZ"]:
set_prop(14, zscalestep, DOF_STEP_SCALEZ.val)
Draw.Redraw(1)
Blender.Window.RedrawAll()
def draw_propsheet(x,y):
#UI buttons
global DOF_MAKE
global DOF_UPDATE
global DOF_DELETE
global DOF_TRANSX
global DOF_TRANSY
global DOF_TRANSZ
global DOF_ROTX
global DOF_ROTY
global DOF_ROTZ
global DOF_SCALEX
global DOF_SCALEY
global DOF_SCALEZ
global DOF_MIN_TRANSX
global DOF_MIN_TRANSY
global DOF_MIN_TRANSZ
global DOF_MIN_ROTX
global DOF_MIN_ROTY
global DOF_MIN_ROTZ
global DOF_MIN_SCALEX
global DOF_MIN_SCALEY
global DOF_MIN_SCALEZ
global DOF_MAX_TRANSX
global DOF_MAX_TRANSY
global DOF_MAX_TRANSZ
global DOF_MAX_ROTX
global DOF_MAX_ROTY
global DOF_MAX_ROTZ
global DOF_MAX_SCALEX
global DOF_MAX_SCALEY
global DOF_MAX_SCALEZ
global DOF_STEP_TRANSX
global DOF_STEP_TRANSY
global DOF_STEP_TRANSZ
global DOF_STEP_ROTX
global DOF_STEP_ROTY
global DOF_STEP_ROTZ
global DOF_STEP_SCALEX
global DOF_STEP_SCALEY
global DOF_STEP_SCALEZ
#labels
global DOF_ROTSTRING
global DOF_TRANSTRING
global DOF_SCALESTRING
global DOF_EDITLABEL
#masks
global lockxtrans
global lockytrans
global lockztrans
global lockxrot
global lockyrot
global lockzrot
global lockxscale
global lockyscale
global lockzscale
global zmin
global zmax
global zcur
global zstep
global ymin
global ymax
global ycur
global ystep
global xmin
global xmax
global xcur
global xstep
global pitchmin
global pitchmax
global pitchcur
global pitchstep
global rollmin
global rollmax
global rollcur
global rollstep
global yawmin
global yawmax
global yawcur
global yawstep
global zscalemin
global zscalemax
global zscalecur
global zscalestep
global yscalemin
global yscalemax
global yscalecur
global yscalestep
global xscalemin
global xscalemax
global xscalecur
global xscalestep
global evcode
state = update_state()
row_height = 20
toggle_width = 50
input_width = 100
pad = 10
origx = x
origy = (row_height * 15) + (pad * 15)
#editor label
x = origx
y = origy
#y = y - (row_height + pad)
DOF_EDITLABEL = Blender.Draw.Label("FLT Degree of Freedom Editor", x, y, 200, row_height)
#draw Translation limits
x = origx
y = y- (row_height + pad)
DOF_TRANSTRING = Blender.Draw.Label("Translation Limits", x, y, input_width, row_height)
#X limits
x = origx
y = y- (row_height + pad)
DOF_TRANSX = Blender.Draw.Toggle("LimX", evcode["DOF_TRANSX"], x, y, toggle_width, row_height, get_lockmask(lockxtrans), "")
x = x + (toggle_width + pad)
DOF_MIN_TRANSX = Blender.Draw.Number("MinX", evcode["DOF_MIN_TRANSX"], x, y, input_width, row_height,get_prop(14,xmin), -1000000.0, 1000000.0, "")
x = x + (input_width + pad)
DOF_MAX_TRANSX = Blender.Draw.Number("MaxX", evcode["DOF_MAX_TRANSX"], x, y, input_width, row_height,get_prop(14,xmax), -1000000.0, 1000000.0, "")
x = x + (input_width + pad)
DOF_STEP_TRANSX = Blender.Draw.Number("StepX", evcode["DOF_STEP_TRANSX"], x, y, input_width, row_height,get_prop(14,xstep), -1000000.0, 1000000.0, "")
#Y limits
x = origx
y = y- (row_height + pad)
DOF_TRANSY = Blender.Draw.Toggle("LimY", evcode["DOF_TRANSY"], x, y, toggle_width, row_height, get_lockmask(lockytrans), "")
x = x + (toggle_width + pad)
DOF_MIN_TRANSY = Blender.Draw.Number("MinY", evcode["DOF_MIN_TRANSY"], x, y, input_width, row_height, get_prop(14,ymin), -1000000.0, 1000000.0, "")
x = x + (input_width + pad)
DOF_MAX_TRANSY = Blender.Draw.Number("MaxY", evcode["DOF_MAX_TRANSY"], x, y, input_width, row_height, get_prop(14,ymax), -1000000.0, 1000000.0, "")
x = x + (input_width + pad)
DOF_STEP_TRANSY = Blender.Draw.Number("StepY", evcode["DOF_STEP_TRANSY"], x, y, input_width, row_height, get_prop(14,ystep), -1000000.0, 1000000.0, "")
#Z limits
x = origx
y = y- (row_height + pad)
DOF_TRANSZ = Blender.Draw.Toggle("LimZ", evcode["DOF_TRANSZ"], x, y, toggle_width, row_height, get_lockmask(lockztrans), "")
x = x + (toggle_width + pad)
DOF_MIN_TRANSZ = Blender.Draw.Number("MinZ", evcode["DOF_MIN_TRANSZ"], x, y, input_width, row_height, get_prop(14,zmin), -1000000.0, 1000000.0, "")
x = x + (input_width + pad)
DOF_MAX_TRANSZ = Blender.Draw.Number("MaxZ", evcode["DOF_MAX_TRANSZ"], x, y, input_width, row_height, get_prop(14,zmax), -1000000.0, 1000000.0, "")
x = x + (input_width + pad)
DOF_STEP_TRANSZ = Blender.Draw.Number("StepZ", evcode["DOF_STEP_TRANSZ"], x, y, input_width, row_height, get_prop(14,zstep), -1000000.0, 1000000.0, "")
#draw Rotation limits
x = origx
y = y- (row_height + pad)
DOF_ROTSTRING = Blender.Draw.Label("Rotation Limits", x, y, input_width, row_height)
#draw Rotation limits
#X limits
x = origx
y = y- (row_height + pad)
DOF_ROTX = Blender.Draw.Toggle("LimX", evcode["DOF_ROTX"], x, y, toggle_width, row_height, get_lockmask(lockxrot), "")
x = x + (toggle_width + pad)
DOF_MIN_ROTX = Blender.Draw.Number("MinX", evcode["DOF_MIN_ROTX"], x, y, input_width, row_height, get_prop(14,pitchmin), -1000000.0, 1000000.0, "")
x = x + (input_width + pad)
DOF_MAX_ROTX = Blender.Draw.Number("MaxX", evcode["DOF_MAX_ROTX"], x, y, input_width, row_height, get_prop(14,pitchmax), -1000000.0, 1000000.0, "")
x = x + (input_width + pad)
DOF_STEP_ROTX = Blender.Draw.Number("StepX", evcode["DOF_STEP_ROTX"], x, y, input_width, row_height, get_prop(14,pitchstep), -1000000.0, 1000000.0, "")
#Y limits
x = origx
y = y- (row_height + pad)
DOF_ROTY = Blender.Draw.Toggle("LimY", evcode["DOF_ROTY"], x, y, toggle_width, row_height, get_lockmask(lockyrot), "")
x = x + (toggle_width + pad)
DOF_MIN_ROTY = Blender.Draw.Number("MinY", evcode["DOF_MIN_ROTY"], x, y, input_width, row_height, get_prop(14,rollmin), -1000000.0, 1000000.0, "")
x = x + (input_width + pad)
DOF_MAX_ROTY = Blender.Draw.Number("MaxY", evcode["DOF_MAX_ROTY"], x, y, input_width, row_height, get_prop(14,rollmax), -1000000.0, 1000000.0, "")
x = x + (input_width + pad)
DOF_STEP_ROTY = Blender.Draw.Number("StepY", evcode["DOF_STEP_ROTY"], x, y, input_width, row_height, get_prop(14,rollstep), -1000000.0, 1000000.0, "")
#Z limits
x = origx
y = y- (row_height + pad)
DOF_ROTZ = Blender.Draw.Toggle("LimZ", evcode["DOF_ROTZ"], x, y, toggle_width, row_height, get_lockmask(lockzrot), "")
x = x + (toggle_width + pad)
DOF_MIN_ROTZ = Blender.Draw.Number("MinZ", evcode["DOF_MIN_ROTZ"], x, y, input_width, row_height, get_prop(14, yawmin), -1000000.0, 1000000.0, "")
x = x + (input_width + pad)
DOF_MAX_ROTZ = Blender.Draw.Number("MaxZ", evcode["DOF_MAX_ROTZ"], x, y, input_width, row_height, get_prop(14, yawmax), -1000000.0, 1000000.0, "")
x = x + (input_width + pad)
DOF_STEP_ROTZ = Blender.Draw.Number("StepZ", evcode["DOF_STEP_ROTZ"], x, y, input_width, row_height, get_prop(14, yawstep), -1000000.0, 1000000.0, "")
#draw Scale limits
x = origx
y = y- (row_height + pad)
DOF_SCALESTRING = Blender.Draw.Label("Scale Limits", x, y, input_width, row_height)
#draw Scale limits
#X limits
x = origx
y = y- (row_height + pad)
DOF_SCALEX = Blender.Draw.Toggle("LimX", evcode["DOF_SCALEX"], x, y, toggle_width, row_height, get_lockmask(lockxscale), "")
x = x + (toggle_width + pad)
DOF_MIN_SCALEX = Blender.Draw.Number("MinX", evcode["DOF_MIN_SCALEX"], x, y, input_width, row_height, get_prop(14, xscalemin), -1000000.0, 1000000.0, "")
x = x + (input_width + pad)
DOF_MAX_SCALEX = Blender.Draw.Number("MaxX", evcode["DOF_MAX_SCALEX"], x, y, input_width, row_height, get_prop(14, xscalemax), -1000000.0, 1000000.0, "")
x = x + (input_width + pad)
DOF_STEP_SCALEX = Blender.Draw.Number("StepX", evcode["DOF_STEP_SCALEX"], x, y, input_width, row_height, get_prop(14, xscalestep), -1000000.0, 1000000.0, "")
#Y limits
x = origx
y = y- (row_height + pad)
DOF_SCALEY = Blender.Draw.Toggle("LimY", evcode["DOF_SCALEY"], x, y, toggle_width, row_height, get_lockmask(lockyscale), "")
x = x + (toggle_width + pad)
DOF_MIN_SCALEY = Blender.Draw.Number("MinY", evcode["DOF_MIN_SCALEY"], x, y, input_width, row_height, get_prop(14, yscalemin), -1000000.0, 1000000.0, "")
x = x + (input_width + pad)
DOF_MAX_SCALEY = Blender.Draw.Number("MaxY", evcode["DOF_MAX_SCALEY"], x, y, input_width, row_height, get_prop(14, yscalemax), -1000000.0, 1000000.0, "")
x = x + (input_width + pad)
DOF_STEP_SCALEY = Blender.Draw.Number("StepY", evcode["DOF_STEP_SCALEY"], x, y, input_width, row_height, get_prop(14, yscalestep), -1000000.0, 1000000.0, "")
#Z limits
x = origx
y = y- (row_height + pad)
DOF_SCALEZ = Blender.Draw.Toggle("LimZ", evcode["DOF_SCALEZ"], x, y, toggle_width, row_height, get_lockmask(lockzscale), "")
x = x + (toggle_width + pad)
DOF_MIN_SCALEZ = Blender.Draw.Number("MinZ", evcode["DOF_MIN_SCALEZ"], x, y, input_width, row_height, get_prop(14, zscalemin), -1000000.0, 1000000.0, "")
x = x + (input_width + pad)
DOF_MAX_SCALEZ = Blender.Draw.Number("MaxZ", evcode["DOF_MAX_SCALEZ"], x, y, input_width, row_height, get_prop(14, zscalemax), -1000000.0, 1000000.0, "")
x = x + (input_width + pad)
DOF_STEP_SCALEZ = Blender.Draw.Number("StepZ", evcode["DOF_STEP_SCALEZ"], x, y, input_width, row_height, get_prop(14, zscalestep), -1000000.0, 1000000.0, "")
#System
x = origx
y = y - (row_height + (pad)*3)
DOF_MAKE = Blender.Draw.PushButton("Make DOF", evcode["DOF_MAKE"], x, y, input_width, row_height, "Make a Dof Node out of Active Object")
x = x + (input_width + pad)
DOF_UPDATE = Blender.Draw.PushButton("Grab Loc/Rot", evcode["DOF_UPDATE"], x, y, input_width, row_height, "Update the Dof Node position/orientation")
x = x + (input_width + pad)
DOF_DELETE = Blender.Draw.PushButton("Delete DOF", evcode["DOF_DELETE"], x, y, input_width, row_height, "Delete the Dof Node properties")
def gui():
#draw the propsheet/toolbox.
psheety = 800
#psheetx = psheety + 10
draw_propsheet(20,psheety)
Draw.Register(gui,event,but_event)

File diff suppressed because it is too large Load Diff

View File

@@ -1,286 +0,0 @@
#!BPY
# flt_filewalker.py is an utility module for OpenFlight IO scripts for blender.
# Copyright (C) 2005 Greg MacDonald
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
__bpydoc__ ="""\
File read/write module used by OpenFlight I/O and tool scripts. OpenFlight is a
registered trademark of MultiGen-Paradigm, Inc.
"""
import Blender
from struct import *
import re
class FltIn:
def __init__(self, filename):
self.file = open(filename, 'rb')
self.position = 0
self.next_position = 100000
self.opcode = 0
self.length = 0
self.level = 0
self.repeat = False # Repeat the last record.
def begin_record(self):
if self.repeat == True:
self.repeat = False
else:
self.position += self.length
try:
self.file.seek(self.position)
input = self.file.read(4)
except:
print 'Parse Error!'
return False
if not input:
self.close_file()
return False
self.opcode = unpack('>h', input[:2])[0]
self.length = unpack('>H', input[-2:])[0]
self.next_position = self.position + self.length
return True
def repeat_record(self):
self.repeat = True
def get_opcode(self):
return self.opcode
def get_level(self):
return self.level
def up_level(self):
self.level += 1
def down_level(self):
self.level -= 1
def read_string(self, length):
s = ''
if self.file.tell() + length <= self.next_position:
start = self.file.tell()
for i in xrange(length):
char = self.file.read(1)
if char == '\x00':
break
s = s + char
self.file.seek(start+length)
# else:
# print 'Warning: string truncated'
return s
def read_int(self):
if self.file.tell() + 4 <= self.next_position:
return unpack('>i', self.file.read(4))[0]
else:
#print 'Warning: int truncated'
return 0
def read_uint(self):
if self.file.tell() + 4 <= self.next_position:
return unpack('>I', self.file.read(4))[0]
else:
#print 'Warning: uint truncated'
return 0
def read_double(self):
if self.file.tell() + 8 <= self.next_position:
return unpack('>d', self.file.read(8))[0]
else:
#print 'Warning: double truncated'
return 0.0
def read_float(self):
if self.file.tell() + 4 <= self.next_position:
return unpack('>f', self.file.read(4))[0]
else:
#print 'Warning: float truncated'
return 0.0
def read_ushort(self):
if self.file.tell() + 2 <= self.next_position:
return unpack('>H', self.file.read(2))[0]
else:
#print 'Warning: ushort truncated'
return 0
def read_short(self):
if self.file.tell() + 2 <= self.next_position:
return unpack('>h', self.file.read(2))[0]
else:
#print 'Warning: short trunated'
return 0
def read_uchar(self):
if self.file.tell() + 1 <= self.next_position:
return unpack('>B', self.file.read(1))[0]
else:
#print 'Warning: uchar truncated'
return 0
def read_char(self):
if self.file.tell() + 1 <= self.next_position:
return unpack('>b', self.file.read(1))[0]
else:
#print 'Warning: char truncated'
return 0
def read_ahead(self, i):
if self.file.tell() + i <= self.next_position:
self.file.seek(i, 1)
# else:
# print 'Warning: attempt to seek past record'
def get_length(self):
return self.length
def close_file(self):
self.file.close()
class FltOut:
# Length includes terminating null
def write_string(self, string, length):
if len(string) > length - 1:
str_len = length - 1
else:
str_len = len(string)
pad_len = length - str_len
self.file.write(string[:str_len])
self.pad(pad_len)
def write_int(self, a):
self.file.write( pack('>i', a) )
def write_uint(self, a):
self.file.write( pack('>I', a) )
def write_double(self, a):
self.file.write( pack('>d', a) )
def write_float(self, a):
self.file.write( pack('>f', a) )
def write_ushort(self, a):
self.file.write( pack('>H', a) )
def write_short(self, a):
self.file.write( pack('>h', a) )
def write_uchar(self, a):
self.file.write( pack('>B', a) )
def write_char(self, a):
self.file.write( pack('>b', a) )
def pad(self, reps):
for i in xrange(reps):
self.file.write('\x00')
def close_file(self):
self.file.close()
def __init__(self, filename):
self.file = open(filename, 'wb')
self.filename = filename
class FileFinder:
def add_file_to_search_path(self, filename):
dir = Blender.sys.dirname(filename)
if dir != None and dir != '':
self.search_dirs.append(dir)
def strip_path(self, full_path):
# One of my flt files had a windows path with unix seperation. Basename
# returned the whole path + filename, which isn't expected. So my
# attempt to fix it is to replace all / or \ with the platform specific
# dir seperator.
#
# note: \\\\ is actually just one \ indirected twice, once for python
# then again for re.sub
if Blender.sys.sep == '\\':
full_path = re.sub('/', '\\\\', full_path)
elif Blender.sys.sep == '/':
full_path = re.sub('\\\\', '/', full_path)
filename = Blender.sys.basename(full_path)
return filename
def find(self, full_path):
if full_path == '':
return None
# Seperate out the path.
dirname = Blender.sys.dirname(full_path)
# Try it first.
if Blender.sys.exists(full_path):
if not dirname in self.search_dirs:
self.search_dirs.append(dirname)
return full_path
# Maybe it's relative.
for path in self.search_dirs:
rel_full_path = Blender.sys.join(path, full_path)
if Blender.sys.exists(rel_full_path):
return rel_full_path
# Search previous directories that have worked.
filename = self.strip_path(full_path)
for path in self.search_dirs:
t = Blender.sys.join(path, filename)
if Blender.sys.exists(t):
return t
# Ask user where it is.
self.user_input = Blender.Draw.PupStrInput(filename + "? ", '', 100)
#self.user_input = None
if self.user_input != None:
t = Blender.sys.join(self.user_input, filename)
if Blender.sys.exists(t):
user_dirname = Blender.sys.dirname(t)
if not user_dirname in self.search_dirs:
self.search_dirs.append(user_dirname)
return t
# Couldn't find it.
return None
def __init__(self):
self.user_input = ''
self.current_file = ''
self.search_dirs = []
dir = Blender.Get('texturesdir')
if dir != None and dir != '':
self.search_dirs.append(dir)
dir = Blender.sys.dirname(Blender.Get('filename'))
if dir != None and dir != '':
print dir
self.search_dirs.append(dir)

File diff suppressed because it is too large Load Diff

View File

@@ -1,502 +0,0 @@
#!BPY
"""
Name: 'FLT LOD Editor'
Blender: 240
Group: 'Misc'
Tooltip: 'Level of Detail Edtior for FLT nodes'
"""
__author__ = "Geoffrey Bantle"
__version__ = "1.0 11/21/07"
__email__ = ('scripts', 'Author, ')
__url__ = ('blender', 'blenderartists.org')
__bpydoc__ ="""\
This script provides tools for working with OpenFlight databases in Blender. OpenFlight is a
registered trademark of MultiGen-Paradigm, Inc.
Feature overview and more availible at:
http://wiki.blender.org/index.php/Scripts/Manual/FLTools
"""
# --------------------------------------------------------------------------
# flt_palettemanager.py version 0.1 2005/04/08
# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
# Copyright (C) 2007: Blender Foundation
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
import Blender.Draw as Draw
from Blender.BGL import *
import Blender
import flt_properties
reload(flt_properties)
from flt_properties import *
#event codes
evcode = {
"LOD_MAKE" : 100,
"LOD_DELETE" : 101,
"LOD_CALC_CENTER" : 102,
"LOD_GRAB_CENTER" : 103,
"LOD_X" : 104,
"LOD_Y" : 105,
"LOD_Z" : 106,
"LOD_FREEZE" : 107,
"LOD_SIG" : 108,
"LOD_IN" : 109,
"LOD_OUT" : 110,
"LOD_TRANS" : 111,
"LOD_PREVIOUS" : 112
}
#system
LOD_MAKE = None #PushButton
LOD_DELETE = None #PushButton
LOD_CALC_CENTER = None #PushButton
LOD_GRAB_CENTER = None #Pushbutton
LOD_FREEZE = None #Toggle
LOD_PREVIOUS = None #Toggle
LOD_X = None #Input
LOD_Y = None #Input
LOD_Z = None #Input
LOD_SIG = None #Input
LOD_IN = None #Input
LOD_OUT = None #Input
LOD_TRANS = None #Input
#labels
LOD_EDITLABEL = None
LOD_SWITCHLABEL = None
LOD_CENTERLABEL = None
LOD_XLABEL = None
LOD_YLABEL = None
LOD_ZLABEL = None
LOD_SIGLABEL = None
LOD_INLABEL = None
LOD_OUTLABEL = None
LOD_TRANSLABEL = None
#ID Props
switch_in = '5d!switch in'
switch_out = '6d!switch out'
xco = '10d!X co'
yco = '11d!Y co'
zco = '12d!Z co'
trans = '13d!Transition'
sig_size = '14d!Sig Size'
#Flags
lodflag = '9I!flags'
previous_mask = (1 << 31)
freeze_mask = (1 << 29)
def update_state():
state = dict()
state["activeScene"] = Blender.Scene.GetCurrent()
state["activeObject"] = state["activeScene"].objects.active
if state["activeObject"] and not state["activeObject"].sel:
state["activeObject"] = None
state["activeMesh"] = None
if state["activeObject"] and state["activeObject"].type == 'Mesh':
state["activeMesh"] = state["activeObject"].getData(mesh=True)
state["activeFace"] = None
if state["activeMesh"]:
if state["activeMesh"].faceUV and state["activeMesh"].activeFace != None:
state["activeFace"] = state["activeMesh"].faces[state["activeMesh"].activeFace]
#update editmode
state["editmode"] = Blender.Window.EditMode()
return state
def idprops_append(object, typecode, props):
object.properties["FLT"] = dict()
object.properties["FLT"]['type'] = typecode
for prop in props:
object.properties["FLT"][prop] = props[prop]
object.properties["FLT"]['3t8!id'] = object.name
def idprops_kill():
state = update_state()
if state["activeObject"] and state["activeObject"].properties.has_key('FLT'):
state["activeObject"].properties.pop('FLT')
def idprops_copy(source):
state = update_state()
if source.properties.has_key('FLT'):
for object in state["activeScene"].objects:
if object.sel and object != source and (state["activeScene"].Layers & object.Layers):
idprops_kill(object)
object.properties['FLT'] = dict()
for key in source.properties['FLT']:
object.properties['FLT'][key] = source.properties['FLT'][key]
def select_by_typecode(typecode):
state = update_state()
for object in state["activeScene"].objects:
if object.properties.has_key('FLT') and object.properties['FLT']['type'] == typecode and state["activeScene"].Layers & object.Layers:
object.select(1)
def idprops_type(object, typecode):
if object.properties.has_key('FLT') and object.properties['FLT'].has_key('type') and object.properties['FLT']['type'] == typecode:
return True
return False
#ui type code
def get_prop(typecode, prop):
state = update_state()
if state["activeObject"] and idprops_type(state["activeObject"], typecode):
props = state["activeObject"].properties['FLT']
else:
props = flt_properties.FLTLOD
return props[prop]
def set_prop(typecode, prop, value):
state = update_state()
if state["activeObject"] and idprops_type(state["activeObject"],typecode):
state["activeObject"].properties['FLT'][prop] = value
def get_lockmask(mask):
global lodflag
state = update_state()
if state["activeObject"]:
flag = get_prop(73,lodflag)
if flag & mask:
return True
return False
def set_lockmask(mask):
state = update_state()
if state["activeObject"] and idprops_type(state["activeObject"], 73):
oldvalue = state["activeObject"].properties['FLT'][lodflag]
oldvalue = struct.unpack('>I', struct.pack('>i', oldvalue))[0]
oldvalue |= mask
state["activeObject"].properties['FLT'][lodflag] = struct.unpack('>i', struct.pack(">I", oldvalue))[0]
def clear_lockmask(mask):
state = update_state()
if state["activeObject"] and idprops_type(state["activeObject"], 73):
oldvalue = state["activeObject"].properties['FLT'][lodflag]
oldvalue = struct.unpack('>I', struct.pack('>i', oldvalue))[0]
oldvalue &= ~mask
state["activeObject"].properties['FLT'][lodflag] = struct.unpack('>i',struct.pack('>I',oldvalue))[0]
def findchildren(object):
state = update_state()
children = list()
for candidate in state["activeScene"].objects:
if candidate.parent == object:
children.append(candidate)
retlist = list(children)
for child in children:
retlist = retlist + findchildren(child)
return retlist
def get_object_center(object):
bbox = object.getBoundBox(1)
average = Blender.Mathutils.Vector(0.0, 0.0, 0.0)
for point in bbox:
average[0] += point[0]
average[1] += point[1]
average[2] += point[2]
average[0] = average[0] / 8.0
average[1] = average[1] / 8.0
average[2] = average[2] / 8.0
return average
def calc_center():
global xco
global yco
global zco
state = update_state()
if state["activeObject"] and idprops_type(state["activeObject"], 73):
average = Blender.Mathutils.Vector(0.0, 0.0, 0.0)
children = findchildren(state["activeObject"]) #get children objects
if children:
for child in children:
center = get_object_center(child)
average[0] += center[0]
average[1] += center[1]
average[2] += center[2]
average[0] = average[0] / len(children)
average[1] = average[1] / len(children)
average[2] = average[2] / len(children)
set_prop(73, xco, average[0])
set_prop(73, yco, average[1])
set_prop(73, zco, average[2])
def grab_center():
global xco
global yco
global zco
state = update_state()
if state["activeObject"] and idprops_type(state["activeObject"], 73):
center = Blender.Window.GetCursorPos()
set_prop(73, xco, center[0])
set_prop(73, yco, center[1])
set_prop(73, zco, center[2])
def create_lod():
state = update_state()
actobj = state["activeObject"]
if actobj and not idprops_type(actobj, 73):
idprops_kill()
idprops_append(actobj,73, flt_properties.FLTLOD)
calc_center()
def event(evt,val):
if evt == Draw.ESCKEY:
Draw.Exit()
def but_event(evt):
global LOD_MAKE
global LOD_DELETE
global LOD_CALC_CENTER
global LOD_GRAB_CENTER
global LOD_FREEZE
global LOD_PREVIOUS
global LOD_X
global LOD_Y
global LOD_Z
global LOD_SIG
global LOD_IN
global LOD_OUT
global LOD_TRANS
global switch_in
global switch_out
global xco
global yco
global zco
global trans
global sig_size
global lodflag
global previous_mask
global freeze_mask
global evcode
#do "system" events
if evt == evcode["LOD_MAKE"]:
create_lod()
if evt == evcode["LOD_CALC_CENTER"]:
calc_center()
if evt == evcode["LOD_DELETE"]:
idprops_kill()
if evt == evcode["LOD_GRAB_CENTER"]:
grab_center()
#do mask events
if evt == evcode["LOD_FREEZE"]:
if LOD_FREEZE.val == True:
set_lockmask(freeze_mask)
else:
clear_lockmask(freeze_mask)
if evt == evcode["LOD_PREVIOUS"]:
if LOD_PREVIOUS.val == True:
set_lockmask(previous_mask)
else:
clear_lockmask(previous_mask)
#do input events
if evt == evcode["LOD_X"]:
set_prop(73, xco, LOD_X.val)
if evt == evcode["LOD_Y"]:
set_prop(73, yco, LOD_Y.val)
if evt == evcode["LOD_Z"]:
set_prop(73, zco, LOD_Z.val)
if evt == evcode["LOD_SIG"]:
set_prop(73, sig_size, LOD_SIG.val)
if evt == evcode["LOD_IN"]:
set_prop(73, switch_in, LOD_IN.val)
if evt == evcode["LOD_OUT"]:
set_prop(73, switch_out, LOD_OUT.val)
if evt == evcode["LOD_TRANS"]:
set_prop(73, trans, LOD_TRANS.val)
Draw.Redraw(1)
Blender.Window.RedrawAll()
def draw_propsheet(x,y):
global LOD_MAKE
global LOD_DELETE
global LOD_CALC_CENTER
global LOD_GRAB_CENTER
global LOD_FREEZE
global LOD_PREVIOUS
global LOD_X
global LOD_Y
global LOD_Z
global LOD_SIG
global LOD_IN
global LOD_OUT
global LOD_TRANS
#labels
global LOD_EDITLABEL
global LOD_SWITCHLABEL
global LOD_CENTERLABEL
global LOD_XLABEL
global LOD_YLABEL
global LOD_ZLABEL
global LOD_SIGLABEL
global LOD_INLABEL
global LOD_OUTLABEL
global LOD_TRANSLABEL
global switch_in
global switch_out
global xco
global yco
global zco
global trans
global sig_size
global lodflag
global previous_mask
global freeze_mask
global evcode
global evcode
state = update_state()
label_width = 100
row_height = 20
toggle_width = 50
input_width = 100
pad = 10
origx = x
origy = (row_height * 16) + (pad * 16)
#editor label
x = origx
y = origy
LOD_EDITLABEL = Blender.Draw.Label("FLT Level of Detail Editor", x, y, 250, row_height)
#Center inputs
x = origx
y = y- (row_height + pad)
LOD_CENTERLABEL = Blender.Draw.Label("LOD center", x, y, label_width, row_height)
y = y- (row_height + pad)
LOD_XLABEL = Blender.Draw.Label("X Coordinate", x, y, label_width, row_height)
x = origx + (label_width + pad)
LOD_X = Blender.Draw.Number("", evcode["LOD_X"], x, y, input_width, row_height,get_prop(73,xco), -1000000.0, 1000000.0, "")
x = origx
y = y- (row_height + pad)
LOD_YLABEL = Blender.Draw.Label("Y Coordinate", x, y, label_width, row_height)
x = origx + (label_width + pad)
LOD_Y = Blender.Draw.Number("", evcode["LOD_Y"], x, y, input_width, row_height,get_prop(73,yco), -1000000.0, 1000000.0, "")
x = origx
y = y- (row_height + pad)
LOD_ZLABEL = Blender.Draw.Label("Z Coordinate", x, y, label_width, row_height)
x = origx + (label_width + pad)
LOD_Z = Blender.Draw.Number("", evcode["LOD_Z"], x, y, input_width, row_height,get_prop(73,zco), -1000000.0, 1000000.0, "")
#Switch inputs
x = origx
y = y- (row_height + pad)
LOD_SWITCHLABEL = Blender.Draw.Label("Switch Settings", x, y, input_width, row_height)
y = y- (row_height + pad)
LOD_SIGLABEL = Blender.Draw.Label("Significant Size", x, y, label_width, row_height)
x = origx + (label_width + pad)
LOD_SIG = Blender.Draw.Number("", evcode["LOD_SIG"], x, y, input_width, row_height, get_prop(73,sig_size), -1000000.0, 1000000.0, "")
x = origx
y = y- (row_height + pad)
LOD_INLABEL = Blender.Draw.Label("Switch In", x, y, label_width, row_height)
x = origx + (label_width + pad)
LOD_IN = Blender.Draw.Number("", evcode["LOD_IN"], x, y, input_width, row_height, get_prop(73,switch_in), -1000000.0, 1000000.0, "")
x = origx
y = y- (row_height + pad)
LOD_OUTLABEL = Blender.Draw.Label("Switch Out", x, y, label_width, row_height)
x = origx + (label_width + pad)
LOD_OUT = Blender.Draw.Number("", evcode["LOD_OUT"], x, y, input_width, row_height, get_prop(73,switch_out), -1000000.0, 1000000.0, "")
x = origx
y = y- (row_height + pad)
LOD_TRANSLABEL = Blender.Draw.Label("Transition", x, y, label_width, row_height)
x = origx + (label_width + pad)
LOD_TRANS = Blender.Draw.Number("", evcode["LOD_TRANS"], x, y, input_width, row_height, get_prop(73,trans), -1000000.0, 1000000.0, "")
x = origx
y = y - (row_height + pad)
LOD_MAKE = Blender.Draw.PushButton("Make LOD", evcode["LOD_MAKE"], x, y, input_width + label_width + pad, row_height, "Make a LOD Node out of Active Object")
y = y - (row_height + pad)
LOD_DELETE = Blender.Draw.PushButton("Delete LOD", evcode["LOD_DELETE"], x, y, input_width + label_width + pad, row_height, "Delete the LOD Node properties")
y = y - (row_height + pad)
LOD_CALC_CENTER = Blender.Draw.PushButton("Calculate Center", evcode["LOD_CALC_CENTER"], x, y, input_width + label_width + pad, row_height, "Calculate the center of this LOD")
y = y - (row_height + pad)
LOD_GRAB_CENTER = Blender.Draw.PushButton("Grab Center", evcode["LOD_GRAB_CENTER"], x, y, input_width + label_width + pad, row_height, "Grab center from 3d cursor")
y = y - (row_height + pad)
LOD_FREEZE = Blender.Draw.Toggle("Freeze Center", evcode["LOD_FREEZE"], x, y, input_width + label_width + pad, row_height, get_lockmask(freeze_mask), "")
y = y - (row_height + pad)
LOD_PREVIOUS = Blender.Draw.Toggle("Previous Range", evcode["LOD_PREVIOUS"], x, y, input_width + label_width + pad, row_height, get_lockmask(previous_mask), "")
def gui():
#draw the propsheet/toolbox.
psheety = 800
#psheetx = psheety + 10
draw_propsheet(20,psheety)
Draw.Register(gui,event,but_event)

View File

@@ -1,505 +0,0 @@
#!BPY
"""
Name: 'FLT Palette Manager'
Blender: 240
Group: 'Misc'
Tooltip: 'Manage FLT colors'
"""
__author__ = "Geoffrey Bantle"
__version__ = "1.0 11/21/2007"
__email__ = ('scripts', 'Author, ')
__url__ = ('blender', 'blenderartists.org')
__bpydoc__ ="""\
This script manages colors in OpenFlight databases. OpenFlight is a
registered trademark of MultiGen-Paradigm, Inc.
Todo:
-Figure out whats causing the PC speaker to beep when initializing...
Feature overview and more availible at:
http://wiki.blender.org/index.php/Scripts/Manual/FLTools
"""
# --------------------------------------------------------------------------
# flt_palettemanager.py version 1.0 2005/04/08
# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
# Copyright (C) 2007: Blender Foundation
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
import Blender.Draw as Draw
from Blender.BGL import *
import Blender
import flt_properties
import flt_defaultp as defaultp
from flt_properties import *
def RGBtoHSV( r, g, b):
minc = min( r, g, b )
maxc = max( r, g, b )
v = maxc
delta = maxc - minc
if( max != 0 ):
s = delta / maxc
else:
s = 0
h = -1
return (h,s,v)
if( r == maxc ):
h = ( g - b ) / delta
elif( g == maxc ):
h = 2 + ( b - r ) / delta
else:
h = 4 + ( r - g ) / delta
h *= 60
if( h < 0 ):
h += 360
return(h,s,v)
def HSVtoRGB(h,s,v):
if( s == 0 ):
return (v,v,v)
h /= 60
i = math.floor( h)
f = h - i
p = v * ( 1 - s )
q = v * ( 1 - s * f )
t = v * ( 1 - s * ( 1 - f ) )
if i == 0:
r = v
g = t
b = p
elif i == 1:
r = q
g = v
b = p
elif i== 2:
r = p
g = v
b = t
elif i==3:
r = p
g = q
b = v
elif i==4:
r = t
g = p
b = v
else:
r = v
g = p
b = q
return(r,g,b)
palette_size = 12
palette_x = 0
palette_y = 0
colors = list()
curint = 1.0
curswatch = 0
#make a default palette, not very useful.
cinc = 1.0 / 1024.0
cstep = 0.0
picker = None
ptt = ""
ts1=None
ts2=None
ts3=None
ts4=None
ts5=None
for i in xrange(1024):
colors.append([cstep,cstep,cstep])
cstep = cstep + cinc
def update_state():
state = dict()
state["activeScene"] = Blender.Scene.getCurrent()
state["activeObject"] = state["activeScene"].getActiveObject()
state["activeMesh"] = None
if state["activeObject"] and state["activeObject"].type == 'Mesh':
state["activeMesh"] = state["activeObject"].getData(mesh=True)
state["activeFace"] = None
if state["activeMesh"]:
if state["activeMesh"].faceUV and state["activeMesh"].activeFace != None:
state["activeFace"] = state["activeMesh"].faces[state["activeMesh"].activeFace]
return state
def pack_face_index(index, intensity):
return ((127*intensity)+(128*index))
def unpack_face_index(face_index):
index = face_index / 128
intensity = float(face_index - 128.0 * index) / 127.0
return(index,intensity)
def event(evt,val):
global palette_size
global palette_x
global palette_y
global colors
global curint
global curswatch
areas = Blender.Window.GetScreenInfo()
curarea = Blender.Window.GetAreaID()
curRect = None
editmode = 0
for area in areas:
if area['id'] == curarea:
curRect = area['vertices']
break
if evt == Draw.LEFTMOUSE:
mval = Blender.Window.GetMouseCoords()
rastx = mval[0] - curRect[0]
rasty = mval[1] - curRect[1]
swatchx = (rastx -palette_x) / palette_size #+state["palette_x"]
swatchy = (rasty -palette_y) / palette_size #+state["palette_y"]
if rastx > palette_x and rastx < (palette_x + palette_size * 32) and rasty > palette_y and rasty < (palette_y+ palette_size* 32):
if swatchx < 32 and swatchy < 32:
curswatch = (swatchx * 32) + swatchy
Draw.Redraw(1)
elif swatchy < 34 and swatchx < 32:
curint = 1.0 - (float(rastx-palette_x)/(palette_size*32.0))
Draw.Redraw(1)
#copy current color and intensity to selected faces.
elif evt == Draw.VKEY:
if Blender.Window.EditMode():
Blender.Window.EditMode(0)
editmode = 1
state = update_state()
#retrieve color from palette
color = struct.unpack('>BBBB',struct.pack('>i',colors[curswatch]))
actmesh = state["activeMesh"]
if actmesh:
if(Blender.Window.GetKeyQualifiers() != Blender.Window.Qual["CTRL"]):
selfaces = list()
for face in actmesh.faces:
if face.sel:
selfaces.append(face)
if not "FLT_COL" in actmesh.faces.properties:
actmesh.faces.addPropertyLayer("FLT_COL",Blender.Mesh.PropertyTypes["INT"])
for face in actmesh.faces:
face.setProperty("FLT_COL",127) #default
try:
actmesh.activeColorLayer = "FLT_Fcol"
except:
actmesh.addColorLayer("FLT_Fcol")
actmesh.activeColorLayer = "FLT_Fcol"
for face in selfaces:
#First append packed index + color and store in face property
face.setProperty("FLT_COL",int(pack_face_index(curswatch,curint)))
#Save baked color to face vertex colors
for col in face.col:
col.r = int(color[0] * curint)
col.g = int(color[1] * curint)
col.b = int(color[2] * curint)
col.a = int(color[3] * curint)
else:
if Blender.Mesh.Mode() == Blender.Mesh.SelectModes['VERTEX']:
if not 'FLT_VCOL' in actmesh.verts.properties:
actmesh.verts.addPropertyLayer("FLT_VCOL",Blender.Mesh.PropertyTypes["INT"])
for vert in actmesh.verts:
vert.setProperty("FLT_VCOL",127)
else:
for vert in actmesh.verts:
if vert.sel:
vert.setProperty("FLT_VCOL",int(pack_face_index(curswatch,curint)))
if editmode:
Blender.Window.EditMode(1)
Blender.Window.RedrawAll()
#grab color and intensity from active face
elif evt == Draw.CKEY:
if Blender.Window.EditMode():
Blender.Window.EditMode(0)
editmode = 1
state = update_state()
actmesh = state["activeMesh"]
activeFace = state["activeFace"]
if activeFace:
if not "FLT_COL" in actmesh.faces.properties:
actmesh.faces.addPropertyLayer("FLT_COL",Blender.Mesh.PropertyTypes["INT"])
for face in actmesh.faces:
face.setProperty("FLT_COL",127) #default
try:
actmesh.activeColorLayer = "FLT_Fcol"
except:
actmesh.addColorLayer("FLT_Fcol")
actmesh.activeColorLayer = "FLT_Fcol"
tcol = activeFace.getProperty("FLT_COL")
(index,intensity) = unpack_face_index(tcol)
curswatch = index
curint = intensity
if editmode:
Blender.Window.EditMode(1)
Blender.Window.RedrawAll()
elif evt == Draw.GKEY:
if Blender.Window.EditMode():
Blender.Window.EditMode(0)
editmode =1
state = update_state()
actmesh = state["activeMesh"]
activeFace = state["activeFace"]
if activeFace and "FLT_COL" in actmesh.faces.properties:
(index,intensity) = unpack_face_index(activeFace.getProperty("FLT_COL"))
for face in actmesh.faces:
(index2, intensity2) = unpack_face_index(face.getProperty("FLT_COL"))
if index == index2:
face.sel = 1
elif evt == Draw.ESCKEY:
Draw.Exit()
if editmode:
Blender.Window.EditMode(1)
def update_all():
global colors
state = update_state()
#update the baked FLT colors for all meshes.
for object in state["activeScene"].objects:
if object.type == "Mesh":
mesh = object.getData(mesh=True)
if 'FLT_COL' in mesh.faces.properties and "FLT_Fcol" in mesh.getColorLayerNames():
mesh.activeColorLayer = "FLT_Fcol"
for face in mesh.faces:
(index,intensity) = unpack_face_index(face.getProperty('FLT_COL'))
color = struct.unpack('>BBBB',struct.pack('>i',colors[index]))
#update the vertex colors for this face
for col in face.col:
col.r = int(color[0] * intensity)
col.g = int(color[1] * intensity)
col.b = int(color[2] * intensity)
col.a = 255
def but_event(evt):
global palette_size
global palette_x
global palette_y
global colors
global curint
global curswatch
global picker
state = update_state()
if evt == 1:
if picker.val:
rval = (int(picker.val[0]*255),int(picker.val[1]*255),int(picker.val[2]*255),255)
rval = struct.pack('>BBBB',rval[0],rval[1],rval[2],rval[3])
rval = struct.unpack('>i',rval)
colors[curswatch] = rval[0]
#go cd through all meshes and update their FLT colors
update_all()
Draw.Redraw(1)
def init_pal():
global palette_size
global palette_x
global palette_y
global colors
global curint
global curswatch
state = update_state()
if not state["activeScene"].properties.has_key('FLT'):
state["activeScene"].properties['FLT'] = dict()
try:
colors = state["activeScene"].properties['FLT']['Color Palette']
except:
state["activeScene"].properties['FLT']['Color Palette'] = defaultp.pal
colors = state["activeScene"].properties['FLT']['Color Palette']
def draw_palette():
global palette_size
global palette_x
global palette_y
global colors
global curint
global curswatch
global picker
global ts1
global ts2
global ts3
global ts4
global ts5
state = update_state()
init_pal()
ssize = palette_size
xpos = palette_x
cid = 0
highlight = [(palette_x,palette_y),(palette_x+palette_size,palette_y),(palette_x+palette_size,palette_y+palette_size),(palette_x,palette_y+palette_size)]
for x in xrange(32):
ypos = palette_y
for y in xrange(32):
color = struct.unpack('>BBBB',struct.pack('>i',colors[cid]))
glColor3f(color[0]/255.0,color[1]/255.0,color[2]/255.0)
glBegin(GL_POLYGON)
glVertex2i(xpos,ypos)
glVertex2i(xpos+ssize,ypos)
glVertex2i(xpos+ssize,ypos+ssize)
glVertex2i(xpos,ypos+ssize)
glEnd()
if curswatch == cid:
highlight[0] = (xpos,ypos)
highlight[1] = (xpos+ssize,ypos)
highlight[2] = (xpos+ssize,ypos+ssize)
highlight[3] = (xpos,ypos+ssize)
glColor3f(0.0,0.0,0.0)
glBegin(GL_LINE_LOOP)
glVertex2i(xpos,ypos)
glVertex2i(xpos+ssize,ypos)
glVertex2i(xpos+ssize,ypos+ssize)
glVertex2i(xpos,ypos+ssize)
glVertex2i(xpos,ypos)
glEnd()
cid = cid + 1
ypos = ypos + ssize
xpos = xpos + ssize
#draw intensity gradient
color = struct.unpack('>BBBB',struct.pack('>i',colors[curswatch]))
color = [color[0]/255.0,color[1]/255.0,color[2]/255.0]
colsteps = [color[0]/255.0,color[1]/255.0,color[2]/255.0]
stripwidth = (palette_size * 32.0) / 256
strippad = palette_size / 2.0
xpos = palette_x
grady = (palette_y + (palette_size * 32.0)) + strippad
for x in xrange(256):
color[0] = color[0] - colsteps[0]
color[1] = color[1] - colsteps[1]
color[2] = color[2] - colsteps[2]
glColor3f(color[0], color[1] ,color[2])
glBegin(GL_POLYGON)
glVertex2f(xpos,grady)
glVertex2f(xpos+stripwidth,grady)
glVertex2f(xpos+stripwidth,grady+palette_size)
glVertex2f(xpos,grady+palette_size)
glEnd()
xpos = xpos + stripwidth
#draw intensity slider bar
#xposition == 512 - ((curint) * 512)
xpos = ((palette_size*32) * (1.0 - curint)) + palette_x
glColor3f(1.0,1.0,1.0)
glBegin(GL_LINE_LOOP)
glVertex2i(int(xpos-6),int(grady-1))
glVertex2i(int(xpos+6),int(grady-1))
glVertex2i(int(xpos+6),int(grady+palette_size+1))
glVertex2i(int(xpos-6),int(grady+palette_size+1))
#glVertex2i(xpos-6,grady+7)
glEnd()
#draw color picker
color = struct.unpack('>BBBB',struct.pack('>i',colors[curswatch]))
pickcol = (color[0]/255.0,color[1]/255.0,color[2]/255.0)
picker = Blender.Draw.ColorPicker(1,highlight[0][0]+1,highlight[0][1]+1,ssize-2,ssize-2,pickcol,ptt)
#draw highlight swatch
glColor3f(1.0,1.0,1.0)
glBegin(GL_LINE_LOOP)
glVertex2i(highlight[0][0],highlight[0][1])
glVertex2i(highlight[1][0],highlight[1][1])
glVertex2i(highlight[2][0],highlight[2][1])
glVertex2i(highlight[3][0],highlight[3][1])
glVertex2i(highlight[0][0],highlight[0][1])
glEnd()
#draw text string explanations
xpos = palette_size*32+20
ypos = palette_size*32+10
glRasterPos2d(xpos,ypos)
ts1 = Blender.Draw.Text("FLT Palette Manager V 1.0")
ypos = ypos - 20
glRasterPos2d(xpos,ypos)
ts3 = Blender.Draw.Text("CKEY - Copy Active Face Color*")
ypos = ypos - 20
glRasterPos2d(xpos,ypos)
ts2 = Blender.Draw.Text("VKEY - Paste Color to Selected Faces")
ypos = ypos - 20
glRasterPos2d(xpos,ypos)
ts4 = Blender.Draw.Text("GKEY - Select Faces With Same Color")
ypos = ypos - 15
glRasterPos2d(xpos,ypos)
ts5 = Blender.Draw.Text("(*Requires mesh with UV coordinates)", 'small')
def gui():
glClearColor(0.5,0.5,0.5,1.0)
glClear(GL_COLOR_BUFFER_BIT)
draw_palette()
init_pal()
Draw.Register(gui,event,but_event)

View File

@@ -1,630 +0,0 @@
# flt_properties.py. For setting default OpenFLight ID property types
# Copyright (C) 2007 Blender Foundation
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
__bpydoc__ ="""\
Utility functions and data defintions used by OpenFlight I/O and tool scripts. OpenFlight is a
registered trademark of MultiGen-Paradigm, Inc.
"""
import struct
bitsLSB = [2147483648]
for i in xrange(31):
bitsLSB.append(bitsLSB[-1]/2)
bitsRSB = bitsLSB[:]
bitsRSB.reverse()
def pack_color(col):
return struct.pack('>B',col[3]) + struct.pack('>B',col[2]) + struct.pack('>B',col[1]) + struct.pack('>B',col[0])
def unpack_color(col):
string = struct.pack('>I', col)
r = struct.unpack('>B',string[3:4])
g = struct.unpack('>B',string[2:3])
b = struct.unpack('>B',string[1:2])
a = struct.unpack('>B',string[0:1])
return [r,g,b,a]
def reverse_bits(len,num):
bitbucket = list()
rval = 0
for i in xrange(len):
if num & bitsRSB[i]:
bitbucket.append(1)
else:
bitbucket.append(0)
bitbucket.reverse()
for i, bit in enumerate(bitbucket):
if bit:
rval |= bitsLSB[i]
return rval
opcode_name = { 0: 'db',
1: 'head',
2: 'grp',
4: 'obj',
5: 'face',
10: 'push',
11: 'pop',
14: 'dof',
19: 'push sub',
20: 'pop sub',
21: 'push ext',
22: 'pop ext',
23: 'cont',
31: 'comment',
32: 'color pal',
33: 'long id',
49: 'matrix',
50: 'vector',
52: 'multi-tex',
53: 'uv lst',
55: 'bsp',
60: 'rep',
61: 'inst ref',
62: 'inst def',
63: 'ext ref',
64: 'tex pal',
67: 'vert pal',
68: 'vert w col',
69: 'vert w col & norm',
70: 'vert w col, norm & uv',
71: 'vert w col & uv',
72: 'vert lst',
73: 'lod',
74: 'bndin box',
76: 'rot edge',
78: 'trans',
79: 'scl',
80: 'rot pnt',
81: 'rot and/or scale pnt',
82: 'put',
83: 'eyepoint & trackplane pal',
84: 'mesh',
85: 'local vert pool',
86: 'mesh prim',
87: 'road seg',
88: 'road zone',
89: 'morph vert lst',
90: 'link pal',
91: 'snd',
92: 'rd path',
93: 'snd pal',
94: 'gen matrix',
95: 'txt',
96: 'sw',
97: 'line styl pal',
98: 'clip reg',
100: 'ext',
101: 'light src',
102: 'light src pal',
103: 'reserved',
104: 'reserved',
105: 'bndin sph',
106: 'bndin cyl',
107: 'bndin hull',
108: 'bndin vol cntr',
109: 'bndin vol orient',
110: 'rsrvd',
111: 'light pnt',
112: 'tex map pal',
113: 'mat pal',
114: 'name tab',
115: 'cat',
116: 'cat dat',
117: 'rsrvd',
118: 'rsrvd',
119: 'bounding hist',
120: 'rsrvd',
121: 'rsrvd',
122: 'push attrib',
123: 'pop attrib',
124: 'rsrvd',
125: 'rsrvd',
126: 'curv',
127: 'road const',
128: 'light pnt appear pal',
129: 'light pnt anim pal',
130: 'indexed lp',
131: 'lp sys',
132: 'indx str',
133: 'shdr pal'}
typecodes = ['c','C','s','S','i','I','f','d','t']
FLT_GRP = 2
FLT_OBJ = 4
FLT_LOD = 73
FLT_XRF = 63
FLT_DOF = 14
FLT_ILP = 111
FLT_DB = 1
FLT_FCE = 5
#not actual opcodes
FLT_NUL = 0
FLT_EXP = -1
#valid childtypes for each FLT node type
FLT_CHILDTYPES = {
FLT_GRP : [111,2,73,4,14,63],
FLT_OBJ : [111],
FLT_LOD : [111,2,73,4,14,63],
FLT_XRF : [],
FLT_DOF : [111,2,73,4,14,63],
FLT_ILP : []
}
#List of nodes that can have faces as children
FLT_FACETYPES = [
FLT_GRP,
FLT_OBJ,
FLT_LOD,
FLT_DOF
]
def write_prop(fw,type,value,length):
if type == 'c':
fw.write_char(value)
elif type == 'C':
fw.write_uchar(value)
elif type == 's':
fw.write_short(value)
elif type == 'S':
fw.write_ushort(value)
elif type == 'i':
fw.write_int(value)
elif type == 'I':
#NOTE!:
#there is no unsigned int type in python, but we can only store signed ints in ID props
newvalue = struct.unpack('>I', struct.pack('>i', value))[0]
fw.write_uint(newvalue)
elif type == 'd':
fw.write_double(value)
elif type == 'f':
fw.write_float(value)
elif type == 't':
fw.write_string(value,length)
def read_prop(fw,type,length):
rval = None
if type == 'c':
rval = fw.read_char()
elif type == 'C':
rval = fw.read_uchar()
elif type == 's':
rval = fw.read_short()
elif type == 'S':
rval = fw.read_ushort()
elif type == 'i':
rval = fw.read_int()
elif type == 'I':
rval = fw.read_uint()
elif type == 'd':
rval = fw.read_double()
elif type == 'f':
rval = fw.read_float()
elif type == 't':
rval = fw.read_string(length)
return rval
FLTExt = {
'3t8!id' : 'Ext',
'4t8!sid' : '',
'5c!reserved': 0,
'6c!revision' : 0,
'7S!recordcode' : 0
}
FLTGroup = {
'3t8!id' : 'G',
'4s!priority' : 0,
'5s!reserved1' : 0,
'6i!flags' : 0,
'7s!special1' : 0,
'8s!special2' : 0,
'9s!significance' : 0,
'10c!layer code' : 0,
'11c!reserved2' : 0,
'12i!reserved3' : 0,
'13i!loop count' : 0,
'14f!loop duration' : 0,
'15f!last frame duration' : 0
}
FLTGroupDisplay = [5,11,12]
FLTObject = {
'3t8!id' : 'O',
'4I!flags' : 0,
'5s!priority' : 0,
'6S!transp' : 0,
'7s!SFX1' : 0,
'8s!SFX2' : 0,
'9s!significance' : 0,
'10s!reserved' : 0
}
FLTObjectDisplay = [10]
FLTLOD = {
'3t8!id' : 'L',
'4i!reserved' : 0,
'5d!switch in' : 0.0,
'6d!switch out' : 0.0,
'7s!sfx ID1' : 0,
'8s!sfx ID2' : 0,
'9I!flags' : 0,
'10d!X co' : 0.0,
'11d!Y co' : 0.0,
'12d!Z co' : 0.0,
'13d!Transition' : 0.0,
'14d!Sig Size' : 0.0
}
FLTLODDisplay = [4]
FLTInlineLP = {
'3t8!id' : 'Lp',
'4s!smc' : 0,
'5s!fid' : 0,
'6C!back color: a' : 255,
'7C!back color: b' : 255,
'8C!back color: g' : 255,
'9C!back color: r' : 255,
'10i!display mode' : 0,
'11f!intensity' : 1.0,
'12f!back intensity' : 0.0,
'13f!minimum defocus' : 0.0,
'14f!maximum defocus' : 1.0,
'15i!fading mode' : 0,
'16i!fog punch mode' : 0,
'17i!directional mode' : 1,
'18i!range mode' : 0,
'19f!min pixel size' : 1.0,
'20f!max pixel size' : 1024,
'21f!actual size' : 0.25,
'22f!trans falloff pixel size' : 0.25,
'23f!trans falloff exponent' : 1.0,
'24f!trans falloff scalar' : 1.0,
'25f!trans falloff clamp' : 1.0,
'26f!fog scalar' : 0.25,
'27f!fog intensity' : 1.0,
'28f!size threshold' : 0.1,
'29i!directionality' : 0,
'30f!horizontal lobe angle' : 180.0,
'31f!vertical lobe angle' : 180.0,
'32f!lobe roll angle' : 0.0,
'33f!dir falloff exponent' : 1.0,
'34f!dir ambient intensity' : 0.1,
'35f!anim period' : 2,
'36f!anim phase' : 0,
'37f!anim enabled' : 1.0,
'38f!significance' : 0.0,
'39i!draw order' : 0,
'40I!flags' : 277004288,
'41f!roti' : 0,
'42f!rotj' : 0,
'43f!rotk' : 1.0
}
FLTInlineLPDisplay = [35,36,37,41,42,43]
FLTXRef = {
'3t200!filename' : '', #we dont actually use this value on export
'4i!reserved' : 0,
'5I!flag' : -478150656,
'6s!bbox' : 0,
'7s!reserved' : 0
}
FLTXRefDisplay = [4,7,3]
FLTDOF = {
'3t8!id' : 'D',
'4i!reserved' : 0,
'5d!ORIGX' : 0.0,
'6d!ORIGY' : 0.0,
'7d!ORIGZ' : 0.0,
'8d!XAXIS-X' : 10.0,
'9d!XAXIS-Y' : 0.0,
'10d!XAXIS-Z' : 0.0,
'11d!XYPLANE-X' : 0.0,
'12d!XYPLANE-Y' : 10.0,
'13d!XZPLANE-Z' : 0.0,
'14d!ZMIN' : 0.0,
'15d!ZMAX' : 0.0,
'16d!ZCUR' : 0.0,
'17d!ZSTEP' : 0.0,
'18d!YMIN' : 0.0,
'19d!YMAX' : 0.0,
'20d!YCUR' : 0.0,
'21d!YSTEP' : 0.0,
'22d!XMIN' : 0.0,
'23d!XMAX' : 0.0,
'24d!XCUR' : 0.0,
'25d!XSTEP' : 0.0,
'26d!PITCH-MIN' : 0.0,
'27d!PITCH-MAX' : 0.0,
'28d!PITCH-CUR' : 0.0,
'29d!PITCH-STEP' : 0.0,
'30d!ROLL-MIN' : 0.0,
'31d!ROLL-MAX' : 0.0,
'32d!ROLL-CUR' : 0.0,
'33d!ROLL-STEP' : 0.0,
'34d!YAW-MIN' : 0.0,
'35d!YAW-MAX' : 0.0,
'36d!YAW-CUR' : 0.0,
'37d!YAW-STEP' : 0.0,
'38d!ZSIZE-MIN' : 0.0,
'39d!ZSIZE-MAX' : 0.0,
'40d!ZSIZE-CUR' : 1.0,
'41d!ZSIZE-STEP' : 0.0,
'42d!YSIZE-MIN' : 0.0,
'43d!YSIZE-MAX' : 0.0,
'44d!YSIZE-CUR' : 1.0,
'45d!YSIZE-STEP' : 0.0,
'46d!XSIZE-MIN' : 0.0,
'47d!XSIZE-MAX' : 0.0,
'48d!XSIZE-CUR' : 1.0,
'49d!XSIZE-STEP' : 0.0,
'50I!FLAG' : 1897582,
'51i!reserved2' : 0
}
FLTDOFDisplay = [4]
FLTImage = {
'3i!RealU Direction' : 0,
'4i!RealV Direction' : 0,
'5i!UpX' : 0,
'6i!UpY' : 0,
'7i!File Format' : 0,
'8i!Min Filter' : 6,
'9i!Mag Filter' : 1,
'10i!Wrap' : 0,
'11i!WrapU' : 0,
'12i!WrapV' : 0,
'13i!Modified' : 0,
'14i!PivotX' : 0,
'15i!PivotY' : 0,
'16i!Enviorment' : 0,
'17i!WhiteAlpha' : 0,
'18i!reserved1' : 0,
'19i!reserved2' : 0,
'20i!reserved3' : 0,
'21i!reserved4' : 0,
'22i!reserved5' : 0,
'23i!reserved6' : 0,
'24i!reserved7' : 0,
'25i!reserved8' : 0,
'26i!reserved9' : 0,
'27d!RealU Direction' : 0,
'28d!RealV Direction' : 0,
'29i!Origin' : 0,
'30i!Kernel no.' : 0,
'31i!Internal Format' : 0,
'32i!External Format' : 0,
'33i!MipMap Filter?' : 0,
'34f!MMF1' : 0.0,
'35f!MMF2' : 0.0,
'36f!MMF3' : 0.0,
'37f!MMF4' : 0.0,
'38f!MMF5' : 0.0,
'39f!MMF6' : 0.0,
'40f!MMF7' : 0.0,
'41f!MMF8' : 0.0,
'42i!Tex CPs?' : 0,
'43f!LOD0 CP' : 0.0,
'44f!Scale0 CP' : 0.0,
'45f!LOD1 CP' : 0.0,
'46f!Scale1 CP' : 0.0,
'47f!LOD2 CP' : 0.0,
'48f!Scale2 CP' : 0.0,
'49f!LOD3 CP' : 0.0,
'50f!Scale3 CP' : 0.0,
'51f!LOD4 CP' : 0.0,
'52f!Scale4 CP' : 0.0,
'53f!LOD5 CP' : 0.0,
'54f!Scale5 CP' : 0.0,
'55f!LOD6 CP' : 0.0,
'56f!Scale6 CP' : 0.0,
'57f!LOD7 CP' : 0.0,
'58f!Scale7 CP' : 0.0,
'59f!Control Clamp' : 0.0,
'60i!Mag Alpha Filter' : 0,
'61i!Mag Color Filter' : 0,
'62f!reserved10' : 0,
'63f!reserved11' : 0,
'64f!reserved12' : 0,
'65f!reserved13' : 0,
'66f!reserved14' : 0,
'67f!reserved15' : 0,
'68f!reserved16' : 0,
'69f!reserved17' : 0,
'70f!reserved18' : 0,
'71d!Lambert Central' : 0.0,
'72d!Lambert Upper' : 0.0,
'73d!Lambert Lower' : 0.0,
'74d!reserved19' : 0,
'75f!reserved20' : 0,
'76f!reserved21' : 0,
'77f!reserved22' : 0,
'78f!reserved23' : 0,
'79f!reserved24' : 0,
'80i!Tex Detail?' : 0,
'81i!Tex J' : 0,
'82i!Tex K' : 0,
'83i!Tex M' : 0,
'84i!Tex N' : 0,
'85i!Tex Scramble' : 0,
'86i!Tex Tile?' : 0,
'87f!Tex Tile LLU' : 0.0,
'88f!Tex Tile LLV' : 0.0,
'89f!Tex Tile URU' : 0.0,
'90f!Tex Tile URV' : 0.0,
'91i!Projection' : 0,
'92i!Earth Model' : 0,
'93i!reserved25' : 0,
'94i!UTM Zone' : 0,
'95i!Image Origin' : 0,
'96i!GPU' : 0,
'97i!reserved26' : 0,
'98i!reserved27' : 0,
'99i!GPU Hemi' : 0,
'100i!reserved41' : 0,
'101i!reserved42' : 0,
'102i!reserved43' : 0,
'103i!Cubemap' : 0,
'104t588!reserved44' : '',
'105t512!Comments' : '',
'106i!reserved28' : 0,
'107i!reserved29' : 0,
'108i!reserved30' : 0,
'109i!reserved31' : 0,
'110i!reserved32' : 0,
'111i!reserved33' : 0,
'112i!reserved34' : 0,
'113i!reserved35' : 0,
'114i!reserved36' : 0,
'115i!reserved37' : 0,
'116i!reserved38' : 0,
'117i!reserved39' : 0,
'118i!reserved40' : 0,
'119i!reserved45' : 0,
'120i!Format Version' : 0,
'121i!GPU num' : 0,
}
FLTImageDisplay = [18,19,29,21,22,23,24,25,26,62,63,64,65,66,67,68,69,70,74,75,76,77,78,79,93,97,98,102,114]
FLTHeader = {
'3t8!id' : 'db',
'4i!version' : 1620,
'5i!editversion' : 0,
'6t32!date' : 0,
'7s!NGID' : 0,
'8s!NLID' : 0,
'9s!NOID' : 0,
'10s!NFID' : 0,
'11s!UMULT' : 1,
'12c!units' : 0,
'13c!set white' : 0,
'14I!flags' : 0x80000000,
'15i!reserved1' : 0,
'16i!reserved2' : 0,
'17i!reserved3' : 0,
'18i!reserved4' : 0,
'19i!reserved5' : 0,
'20i!reserved6' : 0,
'21i!projection type' : 0,
'22i!reserved7' : 0,
'23i!reserved8' : 0,
'24i!reserved9' : 0,
'25i!reserved10' : 0,
'26i!reserved11' : 0,
'27i!reserved12' : 0,
'28i!reserved13' : 0,
'29s!NDID' : 0,
'30s!vstore' : 1,
'31i!origin' : 0,
'32d!sw x' : 0,
'33d!sw y' : 0,
'34d!dx' : 0,
'35d!dy' : 0,
'36s!NSID' : 0,
'37s!NPID' : 0,
'38i!reserved14' : 0,
'39i!reserved15' : 0,
'40s!NCID' : 0,
'41s!NTID' : 0,
'42s!NBID' : 0,
'43s!NWID' : 0,
'44i!reserved14' : 0,
'45d!sw lat' : 0,
'46d!sw lon' : 0,
'47d!ne lat' : 0,
'48d!ne lon' : 0,
'49d!origin lat' : 0,
'50d!origin lon' : 0,
'51d!lambert lat1' : 0,
'52d!lambert lat2' : 0,
'53s!NLSID' : 0,
'54s!NLPID' : 0,
'55s!NRID' : 0,
'56s!NCATID' : 0,
'57s!reserved15' : 0,
'58s!reserved16' : 0,
'59s!reserved17' : 0,
'60s!reserved18' : 0,
'61i!ellipsoid model' : 1,
'62s!NAID' : 0,
'63s!NCVID' : 0,
'64s!utm zone' : 0,
'65t6!reserved19' : 0,
'66d!dz' : 0,
'67d!radius' : 0,
'68S!NMID' : 0,
'69S!NLPSID' : 0,
'70i!reserved20' : 0,
'71d!major axis' : 0,
'72d!minor axis' : 0,
}
FLT_Records = {
2 : FLTGroup,
4 : FLTObject,
73 : FLTLOD,
63 : FLTXRef,
14 : FLTDOF,
1 : FLTHeader,
111 : FLTInlineLP,
100 : FLTExt,
'Image' : FLTImage
}
def process_recordDefs():
records = dict()
for record in FLT_Records:
props = dict()
for prop in FLT_Records[record]:
position = ''
slice = 0
(format,name) = prop.split('!')
for i in format:
if i not in typecodes:
position = position + i
slice = slice + 1
else:
break
type = format[slice:]
length = type[1:]
if len(length) == 0:
length = 1
else:
type = type[0]
length = int(length)
props[int(position)] = (type,length,prop)
records[record] = props
return records

View File

@@ -1,809 +0,0 @@
#!BPY
"""
Name: 'FLT Toolbar'
Blender: 240
Group: 'Misc'
Tooltip: 'Tools for working with FLT databases'
"""
__author__ = "Geoffrey Bantle"
__version__ = "1.0 11/21/07"
__email__ = ('scripts', 'Author, ')
__url__ = ('blender', 'blenderartists.org')
__bpydoc__ ="""\
This script provides tools for working with OpenFlight databases in Blender. OpenFlight is a
registered trademark of MultiGen-Paradigm, Inc.
Feature overview and more availible at:
http://wiki.blender.org/index.php/Scripts/Manual/FLTools
"""
# --------------------------------------------------------------------------
# flt_palettemanager.py version 0.1 2005/04/08
# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
# Copyright (C) 2007: Blender Foundation
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
import Blender.Draw as Draw
from Blender.BGL import *
import Blender
import flt_properties
reload(flt_properties)
from flt_properties import *
xrefprefix = ""
xrefstack = list()
vofsstack = list()
vquatstack = list()
prop_w = 256
prop_h = 256
#event codes
evcode = {
"XREF_MAKE" : 100,
"XREF_EDIT" : 101,
"XREF_FILE" : 102,
"XREF_PICK" : 103,
"XREF_SELECT" : 104,
"XREF_POP" : 105,
"XREF_PREFIX" : 106,
"FACE_NAME" : 200,
"FACE_MAKESUB" : 201,
"FACE_KILLSUB" : 202,
"FACE_SELSUB" : 203,
"SCENE_UPDATE" : 303,
"IDPROP_COPY" : 501,
"IDPROP_KILL" : 502,
"CLIGHT_MAKE" : 700,
"DFROMACT" : 701,
"FIXCOL" : 702
}
XREF_PREFIX = None
XREF_MAKE = None
XREF_EDIT = None
XREF_SELECT = None
XREF_POP = None
FACE_MAKESUB = None
FACE_SELSUB = None
FACE_KILLSUB = None
IDPROP_KILL = None
IDPROP_COPY = None
SCENE_UPDATE = None
CLIGHT_MAKE = None
DFROMACT = None
FIXCOL = None
def RGBtoHSV( r, g, b):
cmin = min( r, g, b )
cmax = max( r, g, b )
v = cmax
if(cmax!=0.0):
s = (cmax-cmin)/cmax
else:
s = 0.0
h = 0.0
if(s == 0.0):
h = -1.0
else:
cdelta = cmax-cmin
rc = (cmax-r)/cdelta
gc = (cmax-g)/cdelta
bc = (cmax-b)/cdelta
if(r==cmax):
h = bc-gc
else:
if(g==cmax):
h = 2.0+rc-bc
else:
h = 4.0+gc-rc
h = h*60.0
if(h<0.0):
h += 360.0
h = h/360.0
if(h < 0.0):
h = 0.0
return (h,s,v)
def update_state():
state = dict()
state["activeScene"] = Blender.Scene.GetCurrent()
state["activeObject"] = state["activeScene"].objects.active
if state["activeObject"] and not state["activeObject"].sel:
state["activeObject"] = None
state["activeMesh"] = None
if state["activeObject"] and state["activeObject"].type == 'Mesh':
state["activeMesh"] = state["activeObject"].getData(mesh=True)
state["activeFace"] = None
if state["activeMesh"]:
if state["activeMesh"].faceUV and state["activeMesh"].activeFace != None:
state["activeFace"] = state["activeMesh"].faces[state["activeMesh"].activeFace]
#update editmode
state["editmode"] = Blender.Window.EditMode()
return state
def pack_face_index(index, intensity):
return ((127*intensity)+(128*index))
def unpack_face_index(face_index):
index = face_index / 128
intensity = float(face_index - 128.0 * index) / 127.0
return(index,intensity)
def idprops_append(object, typecode, props):
object.properties["FLT"] = dict()
object.properties["FLT"]['type'] = typecode
for prop in props:
object.properties["FLT"][prop] = props[prop]
object.properties["FLT"]['3t8!id'] = object.name
def idprops_kill(object):
state = update_state()
if object and object.properties.has_key('FLT'):
object.properties.pop('FLT')
def idprops_copy(source):
state = update_state()
if source.properties.has_key('FLT'):
for object in state["activeScene"].objects:
if object.sel and object != source and (state["activeScene"].Layers & object.Layers):
idprops_kill(object)
object.properties['FLT'] = dict()
for key in source.properties['FLT']:
object.properties['FLT'][key] = source.properties['FLT'][key]
def unpack_color(color):
return struct.unpack('>BBBB',struct.pack('>I',color))
def findColorKey(colordict, hsv):
hdelta = 0.001
for key in colordict:
if not (((hsv[0] < (key[0] + hdelta)) and (hsv[0] > (key[0] - hdelta))) and ((hsv[1] < (key[1] + hdelta)) and (hsv[1] > (key[1] - hdelta)))):
return key
return None
def hsvsort(a, b):
(index1, mag1) = a
(index2, mag2) = b
if mag1 > mag2:
return 1
elif mag1 < mag2:
return -1
return 0
def fix_colors():
editmode = 0
if Blender.Window.EditMode():
Blender.Window.EditMode(0)
editmode = 1
state = update_state()
scene = state["activeScene"]
colors = None
if state["activeScene"].properties.has_key('FLT'):
try:
colors = state["activeScene"].properties['FLT']['Color Palette']
except:
pass
if not colors:
return
#first build a HSV version of our palette
hsvpalette = list()
for swatch in colors:
color = unpack_color(swatch)
hsv = RGBtoHSV(color[0] / 255.0, color[1] / 255.0, color[2] / 255.0)
hsvpalette.append(hsv)
#collect all of our meshes
meshes = list()
for object in scene.objects.context:
if object.sel and object.type == 'Mesh':
mesh = object.getData(mesh=True)
if "FLT_COL" in mesh.faces.properties:
meshes.append(mesh)
#Now go through our meshes, and build a dictionary of face lists keyed according to (hue,saturation) of the baked color
colordict = dict()
for mesh in meshes:
for face in mesh.faces:
hsv = RGBtoHSV(face.col[0].r/255.0, face.col[0].g/255.0, face.col[0].b/255.0) #retrieve baked color
if colordict.has_key((hsv[0],hsv[1])):
colordict[(hsv[0],hsv[1])].append(face)
else:
colordict[(hsv[0],hsv[1])] = [face]
#for each color key in the color dict, build a list of distances from it to the values in hsvpalette and then quicksort them for closest match
for key in colordict:
maglist = list()
for i, hsv in enumerate(hsvpalette):
norm = Blender.Mathutils.Vector(hsv[0], hsv[1]) - Blender.Mathutils.Vector(key[0],key[1])
maglist.append((i,norm.length))
maglist.sort(hsvsort)
print maglist[0]
for face in colordict[key]:
(index, intensity) = unpack_face_index(face.getProperty("FLT_COL"))
newfindex = pack_face_index(maglist[0][0],intensity)
face.setProperty("FLT_COL", int(newfindex))
for mesh in meshes:
update_mesh_colors(colors,mesh)
if editmode:
Blender.Window.EditMode(1)
def update_mesh_colors(colors, mesh):
if 'FLT_COL' in mesh.faces.properties:
mesh.activeColorLayer = "FLT_Fcol"
for face in mesh.faces:
(index,intensity) = unpack_face_index(face.getProperty('FLT_COL'))
color = struct.unpack('>BBBB',struct.pack('>I',colors[index]))
if index == 0 and intensity == 0:
color = (255,255,255)
intensity = 1.0
#update the vertex colors for this face
for col in face.col:
col.r = int(color[0] * intensity)
col.g = int(color[1] * intensity)
col.b = int(color[2] * intensity)
col.a = 255
def update_all():
editmode = 0
if Blender.Window.EditMode():
Blender.Window.EditMode(0)
editmode = 1
state = update_state()
colors = None
if state["activeScene"].properties.has_key('FLT'):
try:
colors = state["activeScene"].properties['FLT']['Color Palette']
except:
pass
if colors:
#update the baked FLT colors for all meshes.
for object in state["activeScene"].objects:
if object.type == "Mesh":
mesh = object.getData(mesh=True)
update_mesh_colors(colors,mesh)
if editmode:
Blender.Window.EditMode(1)
#Change this to find the deep parent
def xref_create():
global xrefprefix
global xrefstack
global vofsstack
global vquatstack
global prop_w
global prop_h
state = update_state()
def findchildren(object):
children = list()
for candidate in state["activeScene"].objects:
if candidate.parent == object:
children.append(candidate)
retlist = list(children)
for child in children:
retlist = retlist + findchildren(child)
return retlist
actObject = state["activeObject"]
if actObject and xrefprefix:
scenenames = list()
for scene in Blender.Scene.Get():
scenenames.append(scene.name)
if xrefprefix in scenenames:
#build a unique name for the xref...
suffix = 1
found = False
while not found:
candidate = xrefprefix + str(suffix)
if not candidate in scenenames:
xrefname = candidate
found = True
suffix+=1
else:
xrefname = xrefprefix
#create our XRef node
xnode = state["activeScene"].objects.new('Empty')
xnode.name = 'X:' + xrefname
xnode.properties['FLT'] = dict()
for prop in FLTXRef:
xnode.properties['FLT'][prop] = FLTXRef[prop]
xnode.properties['FLT']['3t200!filename'] = xrefname + '.flt'
xnode.properties['FLT']['type'] = 63
xnode.enableDupGroup = True
xnode.DupGroup = Blender.Group.New(xrefname) #this is dangerous... be careful!
#copy rot and loc of actObject
xnode.setLocation(actObject.getLocation())
xnode.setEuler(actObject.getEuler())
#build the new scene
xrefscene = Blender.Scene.New(xrefname)
xrefscene.properties['FLT'] = dict()
xrefscene.properties['FLT']['Filename'] = xrefname
xrefscene.properties['FLT']['Main'] = 0
#find the children of actObject so that we can add them to the group
linkobjects = findchildren(actObject)
linkobjects.append(actObject)
for object in linkobjects:
xrefscene.objects.link(object)
state["activeScene"].objects.unlink(object)
xnode.DupGroup.objects.link(object)
#clear rotation of actObject and location
actObject.setLocation(0.0,0.0,0.0)
actObject.setEuler(0.0,0.0,0.0)
xrefscene.update(1)
state["activeScene"].update(1)
def xref_select():
state = update_state()
candidates = list()
scenelist = [scene.name for scene in Blender.Scene.Get()]
for object in state["activeScene"].objects:
if object.type == 'Empty' and object.enableDupGroup == True and object.DupGroup:
candidates.append(object)
for object in candidates:
if object.DupGroup.name in scenelist:
object.sel = 1
def xref_edit():
global xrefprefix
global xrefstack
global vofsstack
global vquatstack
global prop_w
global prop_h
state = update_state()
actObject = state["activeObject"]
if actObject and actObject.type == 'Empty' and actObject.DupGroup:
# if actObject.properties.has_key('FLT') and actObject.properties['FLT']['type'] == 63:
for FLTscene in Blender.Scene.Get():
if FLTscene.properties.has_key('FLT') and FLTscene.name == actObject.DupGroup.name:
actObject.sel = 0
xrefstack.append(state["activeScene"])
vofsstack.append(Blender.Window.GetViewOffset())
vquatstack.append(Blender.Window.GetViewQuat())
FLTscene.makeCurrent()
Blender.Window.SetViewOffset(0.0,0.0,0.0)
def xref_finish():
global xrefprefix
global xrefstack
global vofsstack
global vquatstack
global prop_w
global prop_h
state = update_state()
if xrefstack:
scene = xrefstack.pop()
Blender.Window.SetViewQuat(vquatstack.pop())
Blender.Window.SetViewOffset(vofsstack.pop())
scene.makeCurrent()
def sortSub(a,b):
aindex = a.getProperty("FLT_ORIGINDEX")
bindex = b.getProperty("FLT_ORIGINDEX")
if aindex > bindex:
return 1
elif aindex < bindex:
return -1
return 0
def subface_make():
global xrefprefix
global xrefstack
global vofsstack
global vquatstack
global prop_w
global prop_h
editmode = 0
if Blender.Window.EditMode():
Blender.Window.EditMode(0)
editmode = 1
state = update_state()
actmesh = state["activeMesh"]
activeFace = state["activeFace"]
if actmesh:
if not "FLT_ORIGINDEX" in actmesh.faces.properties:
actmesh.faces.addPropertyLayer("FLT_ORIGINDEX",Blender.Mesh.PropertyTypes["INT"])
for i, face in enumerate(actmesh.faces):
face.setProperty("FLT_ORIGINDEX",i)
if not "FLT_SFLEVEL" in actmesh.faces.properties:
actmesh.faces.addPropertyLayer("FLT_SFLEVEL",Blender.Mesh.PropertyTypes["INT"])
#attach the subfaces to the active face. Note, this doesnt really work 100 percent properly yet, just enough for one level!
if activeFace:
#steps:
#remove actface and selected faces from the facelist
#quicksort facelist
#append actface and subfaces to end of facelist.
#generate new indices
facelist = list()
sublist = list()
for face in actmesh.faces:
facelist.append(face)
for face in facelist:
if face == activeFace:
face.setProperty("FLT_SFLEVEL",0)
sublist.insert(0,face)
elif face.sel:
face.setProperty("FLT_SFLEVEL",1)
sublist.append(face)
for face in sublist:
facelist.remove(face)
facelist.sort(sortSub)
for face in sublist:
facelist.append(face)
for i, face in enumerate(facelist):
face.setProperty("FLT_ORIGINDEX",i)
else:
pass
if editmode:
Blender.Window.EditMode(1)
def subface_kill():
global xrefprefix
global xrefstack
global vofsstack
global vquatstack
global prop_w
global prop_h
editmode = 0
if Blender.Window.EditMode():
Blender.Window.EditMode(0)
editmode = 1
state = update_state()
actmesh = state["activeMesh"]
if actmesh:
if "FLT_ORIGINDEX" in actmesh.faces.properties and "FLT_SFLEVEL" in actmesh.faces.properties:
for i,face in enumerate(actmesh.faces):
face.setProperty("FLT_ORIGINDEX",i)
face.setProperty("FLT_SFLEVEL",0)
if editmode:
Blender.Window.EditMode(1)
def subface_select():
global xrefprefix
global xrefstack
global vofsstack
global vquatstack
global prop_w
global prop_h
editmode = 0
if Blender.Window.EditMode():
Blender.Window.EditMode(0)
editmode = 1
state = update_state()
actmesh = state["activeMesh"]
activeFace = state["activeFace"]
if actmesh and activeFace:
if "FLT_ORIGINDEX" in actmesh.faces.properties and "FLT_SFLEVEL" in actmesh.faces.properties:
facelist = list()
actIndex = None
sublevel = None
for face in actmesh.faces:
facelist.append(face)
facelist.sort(sortSub)
for i, face in enumerate(facelist):
if face == activeFace:
actIndex = i
sublevel = face.getProperty("FLT_SFLEVEL")+1
break
leftover = facelist[actIndex+1:]
for face in leftover:
if face.getProperty("FLT_SFLEVEL") == sublevel:
face.sel = 1
else:
break
if editmode:
Blender.Window.EditMode(1)
def select_by_typecode(typecode):
global xrefprefix
global xrefstack
global vofsstack
global vquatstack
global prop_w
global prop_h
state = update_state()
for object in state["activeScene"].objects:
if object.properties.has_key('FLT') and object.properties['FLT']['type'] == typecode and state["activeScene"].Layers & object.Layers:
object.select(1)
def clight_make():
state = update_state()
actmesh = state["activeMesh"]
actobj = state["activeObject"]
if actobj and actmesh:
actobj.properties['FLT'] = dict()
actobj.properties['FLT']['type'] = 111
for prop in FLTInlineLP:
actobj.properties['FLT'][prop] = FLTInlineLP[prop]
actmesh.verts.addPropertyLayer("FLT_VCOL", Blender.Mesh.PropertyTypes["INT"])
for v in actmesh.verts:
v.setProperty("FLT_VCOL", 83815)
def dfromact():
state = update_state()
actobj = state["activeObject"]
actscene = state["activeScene"]
dof = None
for object in actscene.objects.context:
if object.sel and (object != actobj):
if not dof:
dof = object
else:
break
if not dof:
return
if 'FLT' not in dof.properties:
dof.properties['FLT'] = dict()
#Warning! assumes 1 BU == 10 meters.
#do origin
dof.properties['FLT']['5d!ORIGX'] = actobj.getLocation('worldspace')[0]*10.0
dof.properties['FLT']['6d!ORIGY'] = actobj.getLocation('worldspace')[1]*10.0
dof.properties['FLT']['7d!ORIGZ'] = actobj.getLocation('worldspace')[2]*10.0
#do X axis
x = Blender.Mathutils.Vector(1.0,0.0,0.0)
x = x * actobj.getMatrix('worldspace')
x = x * 10.0
dof.properties['FLT']['8d!XAXIS-X'] = x[0]
dof.properties['FLT']['9d!XAXIS-Y'] = x[1]
dof.properties['FLT']['10d!XAXIS-Z'] = x[2]
#do X/Y plane
x = Blender.Mathutils.Vector(1.0,1.0,0.0)
x.normalize()
x = x * actobj.getMatrix('worldspace')
x = x * 10.0
dof.properties['FLT']['11d!XYPLANE-X'] = x[0]
dof.properties['FLT']['12d!XYPLANE-Y'] = x[1]
dof.properties['FLT']['13d!XZPLANE-Z'] = x[2]
def event(evt,val):
if evt == Draw.ESCKEY:
Draw.Exit()
def but_event(evt):
global xrefprefix
global xrefstack
global vofsstack
global vquatstack
global prop_w
global prop_h
global evcode
state = update_state()
#do Xref buttons
if evt == evcode["XREF_PREFIX"]:
xrefprefix = XREF_PREFIX.val
if evt == evcode["XREF_EDIT"]:
xref_edit()
if evt == evcode["XREF_SELECT"]:
xref_select()
if evt == evcode["XREF_MAKE"]:
xref_create()
#do scene buttons
if evt == evcode["SCENE_UPDATE"]:
update_all()
#do face buttons
if evt == evcode["FACE_MAKESUB"]:
subface_make()
if evt== evcode["FACE_KILLSUB"]:
subface_kill()
if evt== evcode["FACE_SELSUB"]:
subface_select()
#common buttons
if evt == evcode["IDPROP_KILL"]:
if state["activeObject"]:
idprops_kill(state["activeObject"])
if evt == evcode["IDPROP_COPY"]:
if state["activeObject"]:
idprops_copy(state["activeObject"])
if evt == evcode["XREF_POP"]:
xref_finish()
if evt == evcode["CLIGHT_MAKE"]:
clight_make()
if evt == evcode["DFROMACT"]:
dfromact()
if evt == evcode["FIXCOL"]:
fix_colors()
Draw.Redraw(1)
Blender.Window.RedrawAll()
def box(x,y,w,h,c,mode):
glColor3f(c[0],c[1],c[2])
if mode == "outline":
glBegin(GL_LINE_LOOP)
else:
glBegin(GL_POLYGON)
glVertex2i(x,y)
glVertex2i(x+w,y)
glVertex2i(x+w,y+h)
glVertex2i(x,y+h)
glEnd()
def draw_postcommon(x,y,finaly):
global sheetlabel
global xrefprefix
global xrefstack
global vofsstack
global vquatstack
global prop_w
global prop_h
global evcode
state = update_state()
width = prop_w
height = prop_h
#draw the header
glColor3f(0.15,0.15,0.15)
glBegin(GL_POLYGON)
glVertex2i(x-1,y)
glVertex2i(x+width+1,y)
glVertex2i(x+width+1,y-25)
glVertex2i(x-1,y-25)
glEnd()
glColor3f(1,1,1)
glRasterPos2i(x,y-20)
sheetlabel = Blender.Draw.Text("FLT Tools Panel")
#draw the box outline
glColor3f(0,0,0)
glBegin(GL_LINE_LOOP)
glVertex2i(x-1,y)
glVertex2i(x+1+width,y)
glVertex2i(x+1+width,finaly-1)
glVertex2i(x-1,finaly-1)
glEnd()
return finaly
def draw_propsheet(x,y):
global XREF_PREFIX
global XREF_MAKE
global XREF_EDIT
global XREF_SELECT
global XREF_POP
global FACE_MAKESUB
global FACE_SELSUB
global FACE_KILLSUB
global IDPROP_KILL
global IDPROP_COPY
global SCENE_UPDATE
global DFROMACT
global FIXCOL
global CLIGHT_MAKE
global xrefprefix
global xrefstack
global vofsstack
global vquatstack
global prop_w
global prop_h
global evcode
state = update_state()
width = prop_w
height = prop_h
origx = x
origy = y
#draw Xref tools
y = y-20
XREF_PREFIX = Blender.Draw.String("XRef Name:",evcode["XREF_PREFIX"],x,y,width,20,xrefprefix,18,"Xref prefix name, Actual name is generated from this")
y = y-20
XREF_MAKE = Blender.Draw.PushButton("Make XRef",evcode["XREF_MAKE"],x,y,width,20,"Make External Reference")
y = y-20
XREF_EDIT = Blender.Draw.PushButton("Edit XRef",evcode["XREF_EDIT"],x,y,width,20,"Edit External Reference")
y = y-20
XREF_SELECT = Blender.Draw.PushButton("Select XRefs",evcode["XREF_SELECT"],x,y,width,20,"Select External References")
y = y - 20
XREF_POP = Blender.Draw.PushButton("Return to previous scene",evcode["XREF_POP"],x,y,width,20,"Go up one level in xref hierarchy")
#Draw facetools
y = y-20
FACE_MAKESUB = Blender.Draw.PushButton("Make Subfaces",evcode["FACE_MAKESUB"],x,y,width,20,"Make subfaces")
y = y-20
FACE_SELSUB = Blender.Draw.PushButton("Select Subfaces",evcode["FACE_SELSUB"],x,y,width,20,"Select subfaces")
y = y-20
FACE_KILLSUB = Blender.Draw.PushButton("Kill Subfaces",evcode["FACE_KILLSUB"],x,y,width,20,"Kill subfaces")
#Draw ID Property tools
y = y - 20
IDPROP_KILL = Blender.Draw.PushButton("Delete ID props",evcode["IDPROP_KILL"],x,y,width,20,"Delete ID props")
y = y - 20
IDPROP_COPY = Blender.Draw.PushButton("Copy to selected",evcode["IDPROP_COPY"],x,y,width,20, "Copy from active to all selected")
y= y - 20
CLIGHT_MAKE = Blender.Draw.PushButton("Make Light Point", evcode["CLIGHT_MAKE"],x,y,width,20,"Create inline light points from current mesh")
#General tools
y = y-20
SCENE_UPDATE = Blender.Draw.PushButton("Update All",evcode["SCENE_UPDATE"],x,y,width,20,"Update all vertex colors")
y=y-20
DFROMACT = Blender.Draw.PushButton("Dof from Active", evcode["DFROMACT"],x,y,width,20,"Get Dof origin from active object")
y=y-20
FIXCOL = Blender.Draw.PushButton("Fix Colors", evcode["FIXCOL"],x,y,width,20,"Fix baked FLT colors of selected meshes")
draw_postcommon(origx, origy,y)
def gui():
#draw the propsheet/toolbox.
psheety = 300
#psheetx = psheety + 10
draw_propsheet(0,psheety)
Draw.Register(gui,event,but_event)

View File

@@ -1,47 +0,0 @@
#!BPY
"""
Name: 'Blender/Python Scripting API'
Blender: 248
Group: 'Help'
Tooltip: 'The Blender Python API reference manual'
"""
__author__ = "Matt Ebb"
__url__ = ("blender", "blenderartist")
__version__ = "1.0.1"
__bpydoc__ = """\
This script opens the user's default web browser at http://www.blender.org's
"Blender Python API Reference" page.
"""
# --------------------------------------------------------------------------
# Blender/Python Scripting Reference Help Menu Item
# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
import Blender
try: import webbrowser
except: webbrowser = None
if webbrowser:
version = str(int(Blender.Get('version')))
webbrowser.open('http://www.blender.org/documentation/'+ version +'PythonDoc/')
else:
Blender.Draw.PupMenu("Error%t|This script requires a full python installation")

View File

@@ -1,814 +0,0 @@
#!BPY
"""
Name: 'Scripts Help Browser'
Blender: 234
Group: 'Help'
Tooltip: 'Show help information about a chosen installed script.'
"""
__author__ = "Willian P. Germano"
__version__ = "0.3 01/21/09"
__email__ = ('scripts', 'Author, wgermano:ig*com*br')
__url__ = ('blender', 'blenderartists.org')
__bpydoc__ ="""\
This script shows help information for scripts registered in the menus.
Usage:
- Start Screen:
To read any script's "user manual" select a script from one of the
available category menus. If the script has help information in the format
expected by this Help Browser, it will be displayed in the Script Help
Screen. Otherwise you'll be offered the possibility of loading the chosen
script's source file in Blender's Text Editor. The programmer(s) may have
written useful comments there for users.
Hotkeys:<br>
ESC or Q: [Q]uit
- Script Help Screen:
This screen shows the user manual page for the chosen script. If the text
doesn't fit completely on the screen, you can scroll it up or down with
arrow keys or a mouse wheel. There may be link and email buttons that if
clicked should open your default web browser and email client programs for
further information or support.
Hotkeys:<br>
ESC: back to Start Screen<br>
Q: [Q]uit<br>
S: view script's [S]ource code in Text Editor<br>
UP, DOWN Arrows and mouse wheel: scroll text up / down
"""
# $Id$
#
# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
# Copyright (C) 2004: Willian P. Germano, wgermano _at_ ig.com.br
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
# Thanks: Brendon Murphy (suggestion) and Kevin Morgan (implementation)
# for the "run" button; Jean-Michel Soler for pointing a parsing error
# with multilines using triple single quotes.
import Blender
from Blender import sys as bsys, Draw, Window, Registry
WEBBROWSER = True
try:
import webbrowser
except:
WEBBROWSER = False
DEFAULT_EMAILS = {
'scripts': ['Bf-scripts-dev', 'bf-scripts-dev@blender.org']
}
DEFAULT_LINKS = {
'blender': ["blender.org\'s Python forum", "http://www.blender.org/modules.php?op=modload&name=phpBB2&file=viewforum&f=9"]
}
PADDING = 15
COLUMNS = 1
TEXT_WRAP = 100
WIN_W = WIN_H = 200
SCROLL_DOWN = 0
def screen_was_resized():
global WIN_W, WIN_H
w, h = Window.GetAreaSize()
if WIN_W != w or WIN_H != h:
WIN_W = w
WIN_H = h
return True
return False
def fit_on_screen():
global TEXT_WRAP, PADDING, WIN_W, WIN_H, COLUMNS
COLUMNS = 1
WIN_W, WIN_H = Window.GetAreaSize()
TEXT_WRAP = int((WIN_W - PADDING) / 6)
if TEXT_WRAP < 40:
TEXT_WRAP = 40
elif TEXT_WRAP > 100:
if TEXT_WRAP > 110:
COLUMNS = 2
TEXT_WRAP /= 2
else: TEXT_WRAP = 100
def cut_point(text, length):
"Returns position of the last space found before 'length' chars"
l = length
c = text[l]
while c != ' ':
l -= 1
if l == 0: return length # no space found
c = text[l]
return l
def text_wrap(text, length = None):
global TEXT_WRAP
wrapped = []
lines = text.split('<br>')
llen = len(lines)
if llen > 1:
if lines[-1] == '': llen -= 1
for i in range(llen - 1):
lines[i] = lines[i].rstrip() + '<br>'
lines[llen-1] = lines[llen-1].rstrip()
if not length: length = TEXT_WRAP
for l in lines:
while len(l) > length:
cpt = cut_point(l, length)
line, l = l[:cpt], l[cpt + 1:]
wrapped.append(line)
wrapped.append(l)
return wrapped
def load_script_text(script):
global PATHS, SCRIPT_INFO
if script.userdir:
path = PATHS['uscripts']
else:
path = PATHS['scripts']
fname = bsys.join(path, script.fname)
source = Blender.Text.Load(fname)
if source:
Draw.PupMenu("File loaded%%t|Please check the file \"%s\" in the Text Editor window" % source.name)
# for theme colors:
def float_colors(cols):
return map(lambda x: x / 255.0, cols)
# globals
SCRIPT_INFO = None
PATHS = {
'home': Blender.Get('homedir'),
'scripts': Blender.Get('scriptsdir'),
'uscripts': Blender.Get('uscriptsdir')
}
if not PATHS['home']:
errmsg = """
Can't find Blender's home dir and so can't find the
Bpymenus file automatically stored inside it, which
is needed by this script. Please run the
Help -> System -> System Information script to get
information about how to fix this.
"""
raise SystemError, errmsg
BPYMENUS_FILE = bsys.join(PATHS['home'], 'Bpymenus')
f = file(BPYMENUS_FILE, 'r')
lines = f.readlines()
f.close()
AllGroups = []
class Script:
def __init__(self, data):
self.name = data[0]
self.version = data[1]
self.fname = data[2]
self.userdir = data[3]
self.tip = data[4]
# End of class Script
class Group:
def __init__(self, name):
self.name = name
self.scripts = []
def add_script(self, script):
self.scripts.append(script)
def get_name(self):
return self.name
def get_scripts(self):
return self.scripts
# End of class Group
class BPy_Info:
def __init__(self, script, dict):
self.script = script
self.d = dict
self.header = []
self.len_header = 0
self.content = []
self.len_content = 0
self.spaces = 0
self.fix_urls()
self.make_header()
self.wrap_lines()
def make_header(self):
sc = self.script
d = self.d
header = self.header
title = "Script: %s" % sc.name
version = "Version: %s for Blender %1.2f or newer" % (d['__version__'],
sc.version / 100.0)
if len(d['__author__']) == 1:
asuffix = ':'
else: asuffix = 's:'
authors = "%s%s %s" % ("Author", asuffix, ", ".join(d['__author__']))
header.append(title)
header.append(version)
header.append(authors)
self.len_header = len(header)
def fix_urls(self):
emails = self.d['__email__']
fixed = []
for a in emails:
if a in DEFAULT_EMAILS.keys():
fixed.append(DEFAULT_EMAILS[a])
else:
a = a.replace('*','.').replace(':','@')
ltmp = a.split(',')
if len(ltmp) != 2:
ltmp = [ltmp[0], ltmp[0]]
fixed.append(ltmp)
self.d['__email__'] = fixed
links = self.d['__url__']
fixed = []
for a in links:
if a in DEFAULT_LINKS.keys():
fixed.append(DEFAULT_LINKS[a])
else:
ltmp = a.split(',')
if len(ltmp) != 2:
ltmp = [ltmp[0], ltmp[0]]
fixed.append([ltmp[0].strip(), ltmp[1].strip()])
self.d['__url__'] = fixed
def wrap_lines(self, reset = 0):
lines = self.d['__bpydoc__'].split('\n')
self.content = []
newlines = []
newline = []
if reset:
self.len_content = 0
self.spaces = 0
for l in lines:
if l == '' and newline:
newlines.append(newline)
newline = []
newlines.append('')
else: newline.append(l)
if newline: newlines.append(newline)
for lst in newlines:
wrapped = text_wrap(" ".join(lst))
for l in wrapped:
self.content.append(l)
if l: self.len_content += 1
else: self.spaces += 1
if not self.content[-1]:
self.len_content -= 1
# End of class BPy_Info
def parse_pyobj_close(closetag, lines, i):
i += 1
l = lines[i]
while l.find(closetag) < 0:
i += 1
l = "%s%s" % (l, lines[i])
return [l, i]
def parse_pyobj(var, lines, i):
"Bad code, was in a hurry for release"
l = lines[i].replace(var, '').replace('=','',1).strip()
i0 = i - 1
if l[0] == '"':
if l[1:3] == '""': # """
if l.find('"""', 3) < 0: # multiline
l2, i = parse_pyobj_close('"""', lines, i)
if l[-1] == '\\': l = l[:-1]
l = "%s%s" % (l, l2)
elif l[-1] == '"' and l[-2] != '\\': # single line: "..."
pass
else:
l = "ERROR"
elif l[0] == "'":
if l[1:3] == "''": # '''
if l.find("'''", 3) < 0: # multiline
l2, i = parse_pyobj_close("'''", lines, i)
if l[-1] == '\\': l = l[:-1]
l = "%s%s" % (l, l2)
elif l[-1] == '\\':
l2, i = parse_pyobj_close("'", lines, i)
l = "%s%s" % (l, l2)
elif l[-1] == "'" and l[-2] != '\\': # single line: '...'
pass
else:
l = "ERROR"
elif l[0] == '(':
if l[-1] != ')':
l2, i = parse_pyobj_close(')', lines, i)
l = "%s%s" % (l, l2)
elif l[0] == '[':
if l[-1] != ']':
l2, i = parse_pyobj_close(']', lines, i)
l = "%s%s" % (l, l2)
return [l, i - i0]
# helper functions:
def parse_help_info(script):
global PATHS, SCRIPT_INFO
if script.userdir:
path = PATHS['uscripts']
else:
path = PATHS['scripts']
fname = bsys.join(path, script.fname)
if not bsys.exists(fname):
Draw.PupMenu('IO Error: couldn\'t find script %s' % fname)
return None
f = file(fname, 'r')
lines = f.readlines()
f.close()
# fix line endings:
if lines[0].find('\r'):
unixlines = []
for l in lines:
unixlines.append(l.replace('\r',''))
lines = unixlines
llen = len(lines)
has_doc = 0
doc_data = {
'__author__': '',
'__version__': '',
'__url__': '',
'__email__': '',
'__bpydoc__': '',
'__doc__': ''
}
i = 0
while i < llen:
l = lines[i]
incr = 1
for k in doc_data.keys():
if l.find(k, 0, 20) == 0:
value, incr = parse_pyobj(k, lines, i)
exec("doc_data['%s'] = %s" % (k, value))
has_doc = 1
break
i += incr
# fix these to seqs, simplifies coding elsewhere
for w in ['__author__', '__url__', '__email__']:
val = doc_data[w]
if val and type(val) == str:
doc_data[w] = [doc_data[w]]
if not doc_data['__bpydoc__']:
if doc_data['__doc__']:
doc_data['__bpydoc__'] = doc_data['__doc__']
if has_doc: # any data, maybe should confirm at least doc/bpydoc
info = BPy_Info(script, doc_data)
SCRIPT_INFO = info
return True
else:
return False
def parse_script_line(l):
tip = 'No tooltip'
try:
pieces = l.split("'")
name = pieces[1].replace('...','')
data = pieces[2].strip().split()
version = data[0]
userdir = data[-1]
fname = data[1]
i = 1
while not fname.endswith('.py'):
i += 1
fname = '%s %s' % (fname, data[i])
if len(pieces) > 3: tip = pieces[3]
except:
return None
return [name, int(version), fname, int(userdir), tip]
def parse_bpymenus(lines):
global AllGroups
llen = len(lines)
for i in range(llen):
l = lines[i].strip()
if not l: continue
if l[-1] == '{':
group = Group(l[:-2])
AllGroups.append(group)
i += 1
l = lines[i].strip()
while l != '}':
if l[0] != '|':
data = parse_script_line(l)
if data:
script = Script(data)
group.add_script(script)
i += 1
l = lines[i].strip()
# AllGroups.reverse()
def create_group_menus():
global AllGroups
menus = []
for group in AllGroups:
name = group.get_name()
menu = []
scripts = group.get_scripts()
for s in scripts: menu.append(s.name)
menu = "|".join(menu)
menu = "%s%%t|%s" % (name, menu)
menus.append([name, menu])
return menus
# Collecting data:
fit_on_screen()
parse_bpymenus(lines)
GROUP_MENUS = create_group_menus()
# GUI:
from Blender import BGL
from Blender.Window import Theme
# globals:
START_SCREEN = 0
SCRIPT_SCREEN = 1
SCREEN = START_SCREEN
# gui buttons:
len_gmenus = len(GROUP_MENUS)
BUT_GMENU = range(len_gmenus)
for i in range(len_gmenus):
BUT_GMENU[i] = Draw.Create(0)
# events:
BEVT_LINK = None # range(len(SCRIPT_INFO.links))
BEVT_EMAIL = None # range(len(SCRIPT_INFO.emails))
BEVT_GMENU = range(100, len_gmenus + 100)
BEVT_VIEWSOURCE = 1
BEVT_EXIT = 2
BEVT_BACK = 3
BEVT_EXEC = 4 # Executes Script
# gui callbacks:
def gui(): # drawing the screen
global SCREEN, START_SCREEN, SCRIPT_SCREEN
global SCRIPT_INFO, AllGroups, GROUP_MENUS
global BEVT_EMAIL, BEVT_LINK
global BEVT_VIEWSOURCE, BEVT_EXIT, BEVT_BACK, BEVT_GMENU, BUT_GMENU, BEVT_EXEC
global PADDING, WIN_W, WIN_H, SCROLL_DOWN, COLUMNS, FMODE
theme = Theme.Get()[0]
tui = theme.get('ui')
ttxt = theme.get('text')
COL_BG = float_colors(ttxt.back)
COL_TXT = ttxt.text
COL_TXTHI = ttxt.text_hi
BGL.glClearColor(COL_BG[0],COL_BG[1],COL_BG[2],COL_BG[3])
BGL.glClear(BGL.GL_COLOR_BUFFER_BIT)
BGL.glColor3ub(COL_TXT[0],COL_TXT[1], COL_TXT[2])
resize = screen_was_resized()
if resize: fit_on_screen()
if SCREEN == START_SCREEN:
x = PADDING
bw = 85
bh = 25
hincr = 50
butcolumns = (WIN_W - 2*x)/ bw
if butcolumns < 2: butcolumns = 2
elif butcolumns > 7: butcolumns = 7
len_gm = len(GROUP_MENUS)
butlines = len_gm / butcolumns
if len_gm % butcolumns: butlines += 1
h = hincr * butlines + 20
y = h + bh
BGL.glColor3ub(COL_TXTHI[0],COL_TXTHI[1], COL_TXTHI[2])
BGL.glRasterPos2i(x, y)
Draw.Text('Scripts Help Browser')
y -= bh
BGL.glColor3ub(COL_TXT[0],COL_TXT[1], COL_TXT[2])
i = 0
j = 0
for group_menu in GROUP_MENUS:
BGL.glRasterPos2i(x, y)
Draw.Text(group_menu[0]+':')
BUT_GMENU[j] = Draw.Menu(group_menu[1], BEVT_GMENU[j],
x, y-bh-5, bw, bh, 0,
'Choose a script to read its help information')
if i == butcolumns - 1:
x = PADDING
i = 0
y -= hincr
else:
i += 1
x += bw + 3
j += 1
x = PADDING
y = 10
BGL.glRasterPos2i(x, y)
Draw.Text('Select script for its help. Press Q or ESC to leave.')
elif SCREEN == SCRIPT_SCREEN:
if SCRIPT_INFO:
if resize:
SCRIPT_INFO.wrap_lines(1)
SCROLL_DOWN = 0
h = 18 * SCRIPT_INFO.len_content + 12 * SCRIPT_INFO.spaces
x = PADDING
y = WIN_H
bw = 38
bh = 16
BGL.glColor3ub(COL_TXTHI[0],COL_TXTHI[1], COL_TXTHI[2])
for line in SCRIPT_INFO.header:
y -= 18
BGL.glRasterPos2i(x, y)
size = Draw.Text(line)
for line in text_wrap('Tooltip: %s' % SCRIPT_INFO.script.tip):
y -= 18
BGL.glRasterPos2i(x, y)
size = Draw.Text(line)
i = 0
y -= 28
for data in SCRIPT_INFO.d['__url__']:
Draw.PushButton('link %d' % (i + 1), BEVT_LINK[i],
x + i*bw, y, bw, bh, data[0])
i += 1
y -= bh + 1
i = 0
for data in SCRIPT_INFO.d['__email__']:
Draw.PushButton('email', BEVT_EMAIL[i], x + i*bw, y, bw, bh, data[0])
i += 1
y -= 18
y0 = y
BGL.glColor3ub(COL_TXT[0],COL_TXT[1], COL_TXT[2])
for line in SCRIPT_INFO.content[SCROLL_DOWN:]:
if line:
line = line.replace('<br>', '')
BGL.glRasterPos2i(x, y)
Draw.Text(line)
y -= 18
else: y -= 12
if y < PADDING + 20: # reached end, either stop or go to 2nd column
if COLUMNS == 1: break
elif x == PADDING: # make sure we're still in column 1
x = 6*TEXT_WRAP + PADDING / 2
y = y0
x = PADDING
Draw.PushButton('source', BEVT_VIEWSOURCE, x, 17, 45, bh,
'View this script\'s source code in the Text Editor (hotkey: S)')
Draw.PushButton('exit', BEVT_EXIT, x + 45, 17, 45, bh,
'Exit from Scripts Help Browser (hotkey: Q)')
if not FMODE:
Draw.PushButton('back', BEVT_BACK, x + 2*45, 17, 45, bh,
'Back to scripts selection screen (hotkey: ESC)')
Draw.PushButton('run script', BEVT_EXEC, x + 3*45, 17, 60, bh, 'Run this script')
BGL.glColor3ub(COL_TXTHI[0],COL_TXTHI[1], COL_TXTHI[2])
BGL.glRasterPos2i(x, 5)
Draw.Text('use the arrow keys or the mouse wheel to scroll text', 'small')
def fit_scroll():
global SCROLL_DOWN
if not SCRIPT_INFO:
SCROLL_DOWN = 0
return
max = SCRIPT_INFO.len_content + SCRIPT_INFO.spaces - 1
if SCROLL_DOWN > max: SCROLL_DOWN = max
if SCROLL_DOWN < 0: SCROLL_DOWN = 0
def event(evt, val): # input events
global SCREEN, START_SCREEN, SCRIPT_SCREEN
global SCROLL_DOWN, FMODE
if not val: return
if evt == Draw.ESCKEY:
if SCREEN == START_SCREEN or FMODE: Draw.Exit()
else:
SCREEN = START_SCREEN
SCROLL_DOWN = 0
Draw.Redraw()
return
elif evt == Draw.QKEY:
Draw.Exit()
return
elif evt in [Draw.DOWNARROWKEY, Draw.WHEELDOWNMOUSE] and SCREEN == SCRIPT_SCREEN:
SCROLL_DOWN += 1
fit_scroll()
Draw.Redraw()
return
elif evt in [Draw.UPARROWKEY, Draw.WHEELUPMOUSE] and SCREEN == SCRIPT_SCREEN:
SCROLL_DOWN -= 1
fit_scroll()
Draw.Redraw()
return
elif evt == Draw.SKEY:
if SCREEN == SCRIPT_SCREEN and SCRIPT_INFO:
load_script_text(SCRIPT_INFO.script)
return
def button_event(evt): # gui button events
global SCREEN, START_SCREEN, SCRIPT_SCREEN
global BEVT_LINK, BEVT_EMAIL, BEVT_GMENU, BUT_GMENU, SCRIPT_INFO
global SCROLL_DOWN, FMODE
if evt >= 100: # group menus
for i in range(len(BUT_GMENU)):
if evt == BEVT_GMENU[i]:
group = AllGroups[i]
index = BUT_GMENU[i].val - 1
if index < 0: return # user didn't pick a menu entry
script = group.get_scripts()[BUT_GMENU[i].val - 1]
if parse_help_info(script):
SCREEN = SCRIPT_SCREEN
BEVT_LINK = range(20, len(SCRIPT_INFO.d['__url__']) + 20)
BEVT_EMAIL = range(50, len(SCRIPT_INFO.d['__email__']) + 50)
Draw.Redraw()
else:
res = Draw.PupMenu("No help available%t|View Source|Cancel")
if res == 1:
load_script_text(script)
elif evt >= 20:
if not WEBBROWSER:
Draw.PupMenu('Missing standard Python module%t|You need module "webbrowser" to access the web')
return
if evt >= 50: # script screen email buttons
email = SCRIPT_INFO.d['__email__'][evt - 50][1]
webbrowser.open("mailto:%s" % email)
else: # >= 20: script screen link buttons
link = SCRIPT_INFO.d['__url__'][evt - 20][1]
webbrowser.open(link)
elif evt == BEVT_VIEWSOURCE:
if SCREEN == SCRIPT_SCREEN: load_script_text(SCRIPT_INFO.script)
elif evt == BEVT_EXIT:
Draw.Exit()
return
elif evt == BEVT_BACK:
if SCREEN == SCRIPT_SCREEN and not FMODE:
SCREEN = START_SCREEN
SCRIPT_INFO = None
SCROLL_DOWN = 0
Draw.Redraw()
elif evt == BEVT_EXEC: # Execute script
exec_line = ''
if SCRIPT_INFO.script.userdir:
exec_line = bsys.join(Blender.Get('uscriptsdir'), SCRIPT_INFO.script.fname)
else:
exec_line = bsys.join(Blender.Get('scriptsdir'), SCRIPT_INFO.script.fname)
Blender.Run(exec_line)
keepon = True
FMODE = False # called by Blender.ShowHelp(name) API function ?
KEYNAME = '__help_browser'
rd = Registry.GetKey(KEYNAME)
if rd:
rdscript = rd['script']
keepon = False
Registry.RemoveKey(KEYNAME)
for group in AllGroups:
for script in group.get_scripts():
if rdscript == script.fname:
parseit = parse_help_info(script)
if parseit == True:
keepon = True
SCREEN = SCRIPT_SCREEN
BEVT_LINK = range(20, len(SCRIPT_INFO.d['__url__']) + 20)
BEVT_EMAIL = range(50, len(SCRIPT_INFO.d['__email__']) + 50)
FMODE = True
elif parseit == False:
Draw.PupMenu("ERROR: script doesn't have proper help data")
break
if not keepon:
Draw.PupMenu("ERROR: couldn't find script")
else:
Draw.Register(gui, event, button_event)

View File

@@ -1,944 +0,0 @@
#!BPY
# coding: utf-8
""" Registration info for Blender menus:
Name: 'HotKey and MouseAction Reference'
Blender: 242
Group: 'Help'
Tip: 'All the hotkeys/short keys'
"""
__author__ = "Jean-Michel Soler (jms)"
__url__ = ("blender", "blenderartist",
"Script's homepage, http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_hotkeyscript.htm",
"Communicate problems and errors, http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender")
__version__ = "21/01/2007"
__bpydoc__ = """\
This script is a reference about all hotkeys and mouse actions in Blender.
Usage:
Open the script from the Help menu and select group of keys to browse.
Notes:<br>
Additional entries in the database (c) 2004 by Bart.
Additional entries in the database for blender 2.37 --> 2.43 (c) 2003-2007/01 by jms.
"""
#------------------------
# Hotkeys script
# (c) jm soler (2003-->01/2007)
# -----------------------
# Page officielle :
# http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_hotkeyscript.htm
# Communiquer les problemes et les erreurs sur:
# http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender
#---------------------------------------------
# ce script est propos<6F> sous licence GPL pour etre associe
# a la distribution de Blender 2.33 et suivant
# --------------------------------------------------------------------------
# this script is released under GPL licence
# for the Blender 2.33 scripts package
# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
# Script copyright (C) 2003, 2004: Jean-Michel Soler
# Additionnal entries in the original data base (c) 2004 by Bart (bart@neeneenee.de)
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
import Blender
from Blender.Draw import *
from Blender.BGL import *
# INTERNATIONAL={0:'English','1':'French'}
# LANGUAGE=0
hotkeys={
'Search ':[['', '']],
'Specials 1 ':[
[',', 'Set Bounding Box rotation scaling pivot'],
['Ctrl-,', 'Set Median Point rotation scaling pivot'],
['.', 'Set 3D cursor as rotation scaling pivot'],
['.', 'Outliner : to get the current active data in center of view'],
['Ctrl-.', 'Set Individual Object Centers as rotation scaling pivot'],
['~', 'Display all layers (German keys: <20>,french keyboard: <20>)'],
['Shift-~', 'Display all/previous layers (German keys: Shift-<2D>, french keyboard: shift-<2D>)'],
['ENTER', 'Outliner : to open a subtree, works on entire item line. '],
['HOME', 'Outliner : to show the entire Object hierarchy. '],
['SHIFT+BACKSPACE',' Text edit mode: Clear text '],
['SPACE', 'Popup menu'],
['SPACE', '3D View: camera selected'],
['Ctrl-SPACE', 'Manipulator (transform widget) Menu'],
['TAB', 'Enter/exit Edit Mode'],
['TAB', 'Edit Mode and Numerical Edit (see N key) : move to next input value'],
['TAB', 'Sequencer: Edit meta strip'],
['TAB', 'IPO: Edit selected'],
['TAB', 'Text Editor : indent'],
['TAB', 'NODE window : Edit group'], #243
['Shift-TAB', 'Text Editor : unindent'],
['Shift-TAB', 'Edit Mode: Toggle snaping'],
['Ctrl-TAB', 'ARMATURE : Enter/exit Pose Mode'],
['Ctrl-TAB','MESH : all views, enter exit weight paint mode.'],
['Shift-TAB', 'Edit Mode : Enter Object Mode'],
['Ctrl-Open menu /', ''],
['Ctrl-Load Image', 'Opens a thumbnail browser instead of file browser for images'],
['.', '...']
],
'Mouse ':[
['Actions:', ''],
['LMB', '3D View: Set 3D Cursor'],
['LMB', '3D View: camera selected'],
['LMB drag', 'Border select circle: add to selection'],
['LMB hold down', 'Popup menu'],
['LMB hold down drag', 'Gesture'],
['Ctrl-LMB', 'IPO: Add key'],
['Ctrl-LMB', '3D View: OBJECT or EDIT mode, select with the Lasso tool'],
['Ctrl-LMB', '3D View: ARMATURE EDIT mode, add a new bone to the selected end '],
['Shift-LMB','MANIPULATOR (transform widget): select the axe to remove in the current'],
['Shift-LMB','MANIPULATOR transformation ( if there is a problem with small step adjustment'],
['Shift-LMB','MANIPULATOR first select the axe or axes with LBM alone)'],
['Shift-LMB', 'Outliner : Hold Shift while clicking on a triangle arrow to open/close the subtree below'],
['MMB', 'Rotate'],
['Ctrl-MMB', 'Zoom view'],
['Ctrl-LMB', 'Outliner : Hold CTRL while clicking on a name allows you to edit a name.'],
['Ctrl-LMB', 'Outliner : This works for all visualized data, including bones or vertex groups,'],
['Ctrl-LMB', 'Outliner : but not for \'nameless\' items that draw the links to Hooks, Deform '],
['Ctrl-LMB', 'Outliner : Groups or Constraints.'],
['Shift-MMB', 'Move view'],
['RMB', 'Select'],
['RMB drag', 'Border select circle: subtract from selection'],
['RMB hold down', 'Popup menu'],
['Alt-RMB', 'Object Mode :Select but in a displayed list of objects located under the mouse cursor'],
['Alt-RMB', 'Edit Mode: Select EDGES LOOP '],
['Alt-Ctrl-RMB', 'Edit Mode: Select FACES LOOP'],
['Alt-Ctrl-RMB', 'UV Image Editor: Select face'],
['Shift-RMB', 'Add/subtract to/from selection'],
['Wheel', 'Zoom view'],
['Transformations:', ''],
['Drag+Ctrl', 'Step adjustment'],
['Drag+Ctrl-Shift', 'Small step adjustment (Transform Widget : first select the axe or axes with LBM alone)'],
['Drag+Shift', 'Fine adjustment (Transform Widget : first select the axe or axes with LBM alone)'],
['LMB', 'Confirm transformation'],
['MMB', 'Toggle optional transform feature'],
['RMB', 'Abort transformation'],
['LMB', 'Grease Pencil: when "Draw Mode On", draw new stroke'],
['RMB', 'Grease Pencil: when "Draw Mode On", eraser tool for stroke segments'],
['Shift-LMB', 'Grease Pencil: draw new stroke'],
['Alt-RMB', 'Grease Pencil: eraser tool for stroke segments'],
['.', '...']
],
'F-Keys ':[
['F1', 'Open File'],
['Shift-F1', 'Library Data Select'],
['F2', 'Save File'],
['Shift-F2', 'Export DXF'],
['Ctrl-F2', 'Save/export in vrml 1.0 format' ],
['F3', 'Save image'],
['Ctrl-F3', 'Save image : dump 3d view'],
['Ctrl-Shift-F3', 'Save image : dump screen'],
['F4', 'Logic Window (may change)'],
['Shift-F4', 'Object manager Data Select '],
['F5', 'Material Window'],
['Shift-F5', '3D Window'],
['F6', 'Texture Window'],
['Shift-F6', 'IPO Window'],
['F7', 'Object Window'],
['Shift-F7', 'Buttons Window'],
['F8', 'World Window'],
['Shift-F8', 'Video Sequencer Window'],
['F9', 'Edit Mode Window'],
['Shift-F9', 'OOP Window'],
['Alt-Shift-F9', 'OutLiner Window'],
['F10', 'Render Window'],
['Shift-F10', 'UV Image Editor'],
['F11', 'Recall the last rendered image'],
['Shift-F11', 'Text Editor'],
['ctrl-F11', 'replay the last rendered animation'],
['F12', 'Render current Scene'],
['Ctrl-F12', 'Render animation'],
['Ctrl-Shift-F12', 'NLA Editor'],
['Shift-F12', 'Action Editor'],
['Shift-F12', 'Action Editor'],
['.', '...']
],
'Numbers ':[
['1..2..0-=', 'Show layer 1..2..12'],
['1..2..0-=', 'Edit Mode with Size, Grab, rotate tools : enter value'],
['Alt-1..2..0', 'Show layer 11..12..20'],
['Shift-1..2..0', 'Toggle layer 1..2..12'],
['Ctrl-1..4', 'Object/Edit Mode : change subsurf level to the selected value'],
['Shift-ALT-...', 'Toggle layer 11..12..20'],
['Crtl-Shift-ALT-3', 'Edit Mode & Face Mode : Triangle faces'],
['Crtl-Shift-ALT-4', 'Edit Mode & Face Mode : Quad faces'],
['Crtl-Shift-ALT-5', 'Edit Mode & Face Mode : Non quad or triangle faces'],
['.', '...']
],
'Numpad ':[
['Numpad DEL', 'Zoom on object'],
['Numpad /', 'Local view on object (hide others)'],
['Numpad *', 'Rotate view to objects local axes'],
['Numpad +', 'Zoom in (works everywhere)'],
['Numpad -', 'OutLiner window, Collapse one level of the hierarchy'],
['Alt-Numpad +', 'Proportional vertex Edit Mode: Increase range of influence'],
['Ctrl-Numpad +', 'Edit Mode: Select More vertices'],
['Numpad -', 'Zoom out (works everywhere)'],
['Numpad +', 'OutLiner window, Expand one level of the hierarchy'],
['Alt-Numpad -', 'Proportional vertex Edit Mode: Decrease range of influence'],
['Ctrl-Numpad +', 'Edit Mode: Select Less vertices'],
['Numpad 0', 'Set Camera view'],
['Ctrl-Numpad 0', 'Set active object as camera'],
['Alt-Numbad 0', 'Restore old camera'],
['Ctrl-Alt-Numpad 0', 'Align active camera to view'],
['Numpad 1', 'Front view'],
['Ctrl-Numpad 1', 'Back view'],
['Numpad 3', 'Right view'],
['Ctrl-Numpad 3', 'Left view'],
['Numpad 7', 'Top view'],
['Ctrl-Numpad 7', 'Bottom view '],
['Numpad 5', 'Toggle orthogonal/perspective view'],
['Numpad 9', 'Redraw view'],
['Numpad 4', 'Rotate view left'],
['ctrl-Shift-Numpad 4', 'Previous Screen'],
['Numpad 6', 'Rotate view right'],
['ctrl-Shift-Numpad 6', 'Next Screen'],
['Numpad 8', 'Rotate view up'],
['Numpad 2', 'Rotate view down'],
['.', '...']
],
'Arrows ':[
['Home/Pos1', 'View all',''],
['Home', 'OutLiner Windows, Show hierarchy'],
['PgUp', 'Edit Mode and Proportionnal Editing Tools, increase influence'],
['PgUp', 'Strip Editor, Move Down'],
['PgUp', 'TimeLine: Jump to next marker'],
['PgUp', 'IPO: Select next keyframe'],
['Ctrl-PgUp', 'IPO: Select and jump to next keyframe'],
['Ctrl-PgUn', 'TimeLine: Jump to next key'],
['PgDn', 'Edit Mode and Proportionnal Editing Tools, decrease influence'],
['PgDn', 'Strip Editor, Move Up'],
['PgDn', 'TimeLine: Jump to prev marker'],
['PgDn', 'IPO: Select previous keyframe'],
['Ctrl-PgDn', 'IPO: Select and jump to previous keyframe'],
['Ctrl-PgDn', 'TimeLine: Jump to prev key'],
['Left', 'One frame backwards'],
['Right', 'One frame forwards'],
['Down', '10 frames backwards'],
['Up', '10 frames forwards'],
['Alt-Down', 'Blender in Window mode'],
['Alt-Up', 'Blender in Fullscreen mode'],
['Ctrl-Left', 'Previous screen'],
['Ctrl-Right', 'Next screen'],
['Ctrl-Down', 'Maximize window toggle'],
['Ctrl-Up', 'Maximize window toggle'],
['Shift-Arrow', 'Toggle first frame/ last frame'],
['.', '...']
],
'Letters ':[
{
"A":[
['A', 'Select all/Deselect all'],
['A', 'Outliner : Select all/Deselect all'],
['A', 'Ipo Editor : Object mode, Select all/Deselect all displayed Curves'], #243
['A', 'Ipo Editor : Edit mode, Select all/Deselect all vertices'], #243
['A', 'Render window (F12) : Display alpha plane'],
['Alt-A', 'Play animation in current window'],
['Ctrl-A', 'Apply objects size/rotation to object data'],
['Ctrl-A', 'Text Editor: Select all'],
['Ctrl-ALT-A', '3D-View: Armature Edit mode, align selected bones to active bone'],
['Shift-A', 'Sequencer: Add menu'],
['Shift-A', '3D-View: Add menu'],
['Shift-A', 'Sculpt Mode: Keep the brush center anchored to the initial location'],
['Shift-ALT-A', 'Play animation in all windows'],
['Shift-CTRL-A', 'Apply lattice / Make dupliverts real'],
['Shift-CTRL-A', 'Apply Deform '],
['.', '...']
],
"B":[
['B', 'Border select'],
['BB', 'Circle select'],
['Alt-B', 'Object Mode: Select visible view section in 3D space'],
['Shift-B', 'Set render border (in active camera view)'],
['Ctrl-Alt-B', 'Object Mode: in 3D view, Bake (on an image in the uv editor window) the selected Meshes'], #243
['Ctrl-Alt-B', 'Object Mode: in 3D view, Bake Full render of selected Meshes'], #243
['Ctrl-Alt-B', 'Object Mode: in 3D view, Bake Ambient Occlusion of selected Meshes'], #243
['Ctrl-Alt-B', 'Object Mode: in 3D view, Bake Normals of the selected Meshes'], #243
['Ctrl-Alt-B', 'Object Mode: in 3D view, Bake Texture Only of selected Meshes'], #243
['.', '...']
],
"C":[
['C', 'Center view on cursor'],
['C', 'UV Image Editor: Active Face Select toggle'],
['C', 'Sequencer: Change content of the strip '], #243
['C', 'IPO: Snap current frame to selected key'],
['C', 'TimeLine: Center View'],
['C', 'File Selector : Copy file'],
['C', 'NODE window : Show cyclic referencies'], #243
['Alt-C', 'Object Mode: Convert menu'],
['Alt-C', 'Text Editor: Copy '],
['Ctrl-Alt-C', 'Object Mode : Add Constraint'],
['Ctrl-Shift-C', 'Text Editor: Copy selection to clipboard'],
['Ctrl-C', 'Copy menu (Copy properties of active to selected objects)'],
['Ctrl-C', 'UV Image Editor: Stick UVs to mesh vertex'],
['Ctrl-C','ARMATURE : posemode, Copy pose attributes'],
['Ctrl-Alt-C',' ARMATURE : posemode, add constraint to new empty object.'],
['Shift-C', 'Center and zoom view on selected objects'],
['Shift-C', 'UV Image Editor: Stick local UVs to mesh vertex'],
['.', '...']
],
"D":[
['D', 'Set 3d draw mode'],
['Alt-D', 'Object Mode: Create new instance of object'],
['Ctrl-D', 'Display alpha of image texture as wire'],
['Ctrl-D', 'Text Editor : uncomment'],
['Shift-D', 'Create full copy of object'],
['Shift-D', 'NODE window : duplicate'], #243
['CTRL-SHIFT-D', 'NLA editor : Duplicate markers'],
['CTRL-SHIFT-D', 'Action editor : Duplicate markers'],
['CTRL-SHIFT-D', 'IPO editor : Duplicate markers'],
['.', '...']
],
"E":[
['E', 'Edit Mode: Extrude'],
['E', 'UV Image Editor: LSCM Unwrap'],
['E', 'TimeLine: Set current frame as End '],
['E', 'NODE window : Execute composite'], #243
['ER', 'Edit Mode: Extrude Rotate'],
['ES', 'Edit Mode: Extrude Scale'],
['ESX', 'Edit Mode: Extrude Scale X axis'],
['ESY', 'Edit Mode: Extrude Scale Y axis'],
['ESZ', 'Edit Mode: Extrude Scale Z axis'],
['EX', 'Edit Mode: Extrude along X axis'],
['EY', 'Edit Mode: Extrude along Y axis'],
['EZ', 'Edit Mode: Extrude along Z axis'],
['Alt-E', 'Edit Mode: exit Edit Mode'],
['Ctrl-E', 'Edit Mode: Edge Specials menu'],
['Ctrl-E', 'Edit Mode: Edge Specials menu, Mark seams'],
['Ctrl-E', 'Edit Mode: Edge Specials menu, Clear seams'],
['Ctrl-E', 'Edit Mode: Edge Specials menu, Rotate Edge CW'],
['Ctrl-E', 'Edit Mode: Edge Specials menu, Rotate Edge CCW'],
['Ctrl-E', 'Edit Mode: Edge Specials menu, Loop Cut'],
['Ctrl-E', 'Edit Mode: Edge Specials menu, Edge Slide'],
['Shift-E', 'Edit Mode: SubSurf Edge Sharpness'],
['.', '...']
],
"F":[
['F', 'Edit mode: Make edge/face'],
['F', 'Sequencer: Set Filter Y'],
['F', 'Object Mode: UV/Face Select mode'],
['Alt-F', 'Edit Mode: Beautify fill'],
['Alt-F,','Text editor : find again '],
['Alt-Ctrl-F,','Text editor : find '],
['Ctrl-F', 'Object Mode: Sort faces in Z direction'],
['Ctrl-F', 'Edit Mode: Flip triangle edges'],
['Shift-F', 'Edit Mode: Fill with triangles'],
['Shift-F', 'Object Mode: fly mode (see header for fly mode keys)'],
['.', '...']
],
"G":[
['G', 'Grab (move)'],
['G', 'Timeline : Grab (move) Marker'],
['Alt-G', 'Clear location (this does only make sense in Object mode)'],
['Alt-G', 'NODE window : ungroup'], #243
['Shift-ALT-G', 'Object mode: Remove selected objects from group'],
['Ctrl-G', 'NODE window : group'], #243
['Ctrl-G', 'Add selected objects to group'],
['Ctrl-G', 'IPO editor, Grab/move marker'],
['Ctrl-Alt-G', 'MANIPULATOR (transform widget): set in Grab Mode'],
['Shift-G', 'Object mode: Selected Group menu'],
['Shift-G', 'Object mode: Selected Group menu 1, Children'],
['Shift-G', 'Object mode: Selected Group menu 2, Immediate Children'],
['Shift-G', 'Object mode: Selected Group menu 3, Parent'],
['Shift-G', 'Object mode: Selected Group menu 4, Sibling'],
['Shift-G', 'Object mode: Selected Group menu 5, Object of same type'],
['Shift-G', 'Object mode: Selected Group menu 6, Object in same shared layers'],
['Shift-G', 'Object mode: Selected Group menu 7, Objects in same group'],
['.', '...']
],
"H":[
['H', 'Hide selected vertices/faces'],
['H', 'Curves: Set handle type'],
['H', 'Action editor: Handle type aligned'],
['H', 'Action editor: Handle type free'],
['H', 'NODE window : hide/unhide'], #243
['Alt-H', 'Edit Mode : Show Hidden vertices/faces'],
['Shift-H', 'Curves: Automatic handle calculation'],
['Shift-H', 'Action editor: Handle type auto'],
['Shift-H', 'Edit Mode : Hide deselected vertices/faces'],
['Ctrl-H', 'Edit Mode : Add a hook on selected points or show the hook menu .'],
['.', '...']
],
"I":[
['I', 'Insert Keyframe menu'],
['Alt-I','Delete Keyframe menu'],
['Ctrl-I','Select Inverse'],
['Shift-I','ARMATURE : add IK constraint'],
['Ctrl-Alt-I','ARMATURE : posemode, remove IK constraints.'],
['.', '...']
],
"J":[
['J', 'IPO: Join menu'],
['J', 'Mesh: Join all adjacent triangles to quads'],
['J', 'Render Window: Swap render buffer'],
['Alt-J,','Text editor : Jump '],
['Ctrl-J', 'Join selected objects'],
['Ctrl-J', 'Nurbs: Add segment'],
['Ctrl-J', 'IPO: Join keyframes menu'],
['.', '...']
],
"K":[
['K', '3d Window: Show keyframe positions'],
['K', 'Edit Mode: Loop/Cut menu'],
['K', 'IPO: Show keyframe positions'],
['K', 'Nurbs: Print knots'],
['K', 'VIDEO editor : cut at current frame'], #243
['Ctrl-K', 'Make skeleton from armature'],
['Shift-K', 'Show and select all keyframes for object'],
['Shift-K', 'Edit Mode: Knife Mode select'],
['Shift-K', 'UV Face Select: Clear vertex colours'],
['Shift-K', 'Vertex Paint: All vertex colours are erased; they are changed to the current drawing colour.'],
['.', '...']
],
"L":[
['L', 'Make local menu'],
['L', 'Edit Mode: Select linked vertices (near mouse pointer)'],
['L', 'NODE window: Select linked from '], #243
['L', 'OOPS window: Select linked objects'],
['L', 'UV Face Select: Select linked faces'],
['Ctrl-L', 'Make links menu (for instance : to scene...)'],
['Shift-L', 'Select links menu'],
['Shift-L', 'NODE window: Select linked to '], #243
['Ctrl-L', 'POSELIB: browse poses'],
['Shift-L', 'POSELIB: add/replace pose'],
['Ctrl-Shift-L', 'POSELIB: rename pose'],
['Alt-L', 'POSELIB: remove pose'],
['.', '...']
],
"M":[
['M', 'Object mode : Move object to different layer'],
['M', 'Sequencer: Make meta strip (group) from selected strips'],
['M', 'Edit Mode: Mirros Axis menu'],
['M', 'File Selector: rename file'],
['M', 'Video Sequence Editor : Make Meta strip...'],
['M', 'NLA editor: Add marker'],
['M', 'Action editor: Add marker'],
['M', 'IPO editor: Add marker'],
['M', 'TimeLine: Add marker'],
['Alt-M', 'Edit Mode: Merge vertices menu'],
['Alt-M', 'Video Sequence Editor : Separate Meta strip...'],
['Ctrl-M', 'Object Mode: Mirros Axis menu'],
['Shift-M', 'TimeLine: Name marker'],
['Shift-M', 'IPO editor : Name marker'],
['Shift-M', 'NLA editor : Name marker'],
['Shift-M', 'Actions editor : Name marker'],
['.', '...']
],
"N":[
['N', 'Transform Properties panel'] ,
['N', 'OOPS window: Rename object'],
['N', 'VIDEO SEQUENCE editor : display strip properties '], #243
['Alt-N', 'Text Editor : New text '],
['Ctrl-N', 'Armature: Recalculate bone roll angles'] ,
['Ctrl-N', 'Edit Mode: Recalculate normals to outside'] ,
['Ctrl-Shift-N', 'Edit Mode: Recalculate normals to inside'],
['.', '...']
],
"O":[
['O', 'Edit Mode/UV Image Editor: Toggle proportional vertex editing'],
['O', 'IPO editor: Clean ipo curves (beware to the thresold needed value)'], #243
['Alt-O', 'Clear object origin'],
['Alt-O', 'Edit mode, 3dview with prop-edit-mode, enables/disables connected'],
['Alt-O', 'Text Editor : Open file '],
['Ctrl-O', 'Open a panel with the ten most recent projets files'], #243
['Shift-O', 'Proportional vertex Edit Mode: Toggle smooth/steep falloff'],
['Shift-O', 'Object Mode: Add a subsurf modifier to the selected mesh'],
['Shift-O', 'IPO editor: Smooth ipo curves'], #243
['.', '...']
],
"P":[
['P', 'Object Mode: Start realtime engine'],
['P', 'Edit mode: Seperate vertices to new object'],
['Shift-P', 'Edit mode: Push-Pull'],
['Shift-P', 'Object mode: Add a preview window in the D window'],
['P', 'UV Image Editor: Pin selected vertices. Pinned vertices will stay in place on the UV editor when executing an LSCM unwrap.'],
['Alt-P', 'Clear parent relationship'],
['Alt-P', 'UV Image Editor: Unpin UVs'],
['Alt-P', 'Text Editor : Run current script '],
['Ctrl-P', 'Make active object parent of selected object'],
['Ctrl-Shift-P', 'Make active object parent of selected object without inverse'],
['Ctrl-P', 'Edit mode: Make active vertex parent of selected object'],
['Ctrl-P', 'ARMATURE : editmode, make bone parent.'],
['Ctrl-Alt-P', 'ARMATURE: edimode, separate bones to new object'],
['.', '...']
],
"Q":[['Ctrl-Q', 'Quit'],
['.', '...']
],
"R":[
['R', 'FileSelector : remove file'],
['R', 'Rotate'],
['R', 'IPO: Record mouse movement as IPO curve'],
['R', 'UV Face Select: Rotate menu uv coords or vertex colour'],
['R', 'NODE window : read saved render result'], #243
['R', 'SEQUENCER window : re-assign entries to another strip '], #243
['RX', 'Rotate around X axis'],
['RXX', "Rotate around object's local X axis"],
['RY', 'Rotate around Y axis'],
['RYY', "Rotate around object's local Y axis"],
['RZ', 'Rotate around Z axis'],
['RZZ', "Rotate around object's local Z axis"],
['Alt-R', 'Clear object rotation'],
['Alt-R', 'Text editor : reopen text.'],
['Ctrl-R', 'Edit Mode: Knife, cut selected edges, accept left mouse/ cancel right mouse'],
['Ctrl-Alt-R', 'MANIPULATOR (transform widget): set in Rotate Mode'],
['Shift-R', 'Edit Mode: select Face Loop'],
['Shift-R', 'Nurbs: Select row'],
['.', '...']
],
"S":[
['S', 'Scale'] ,
['S', 'TimeLine: Set Start'],
['SX', 'Flip around X axis'] ,
['SY', 'Flip around Y axis'] ,
['SZ', 'Flip around Z axis'] ,
['SXX', 'Flip around X axis and show axis'] ,
['SYY', 'Flip around Y axis and show axis'] ,
['SZZ', 'Flip around Z axis and show axis'] ,
['Alt-S', 'Edit mode: Shrink/fatten (Scale along vertex normals)'] ,
['Alt-S', 'Text Editor : Save the current text to file '],
['Alt-S',' ARMATURE : posemode editmode: Scale envalope.'],
['Ctrl-Shift-S', 'Edit mode: To Sphere'] ,
['Ctrl-Alt-Shift-S', 'Edit mode: Shear'] ,
['Alt-S', 'Clear object size'] ,
['Ctrl-S', 'Edit mode: Shear'] ,
['Alt-Shift-S,','Text editor : Select the line '],
['Ctrl-Alt-G', 'MANIPULATOR (transform widget): set in Size Mode'],
['Shift-S', 'Cursor/Grid snap menu'],
['Shift-S', 'Sculpt Mode: Smooth Stroke.'],
['Shift-S+1', 'VIDEO SEQUENCE editor : jump to the current frame '],
['.', '...']
],
"T":[
['T', 'Adjust texture space'],
['T', 'Edit mode: Flip 3d curve'],
['T', 'IPO: Menu Change IPO type, 1 Constant'],
['T', 'IPO: Menu Change IPO type, 2 Linear'],
['T', 'IPO: Menu Change IPO type, 3 Bezier'],
['T', 'TimeLine: Show second'],
['T', 'VIDEO SEQUENCE editor : toggle between show second andd show frame'], #243
['Alt-T', 'Clear tracking of object'],
['Ctrl-T', 'Make selected object track active object'],
['Ctrl-T', 'Edit Mode: Convert to triangles'],
['Ctrl-Alt-T', 'Benchmark'],
['.', '...']
],
"U":[
['U', 'Make single user menu (for import completly linked object to another scene for instance) '] ,
['U', '3D View: Make Single user Menu'] ,
['U', 'UV Face Select: Automatic UV calculation menu'] ,
['U', 'Vertex-/Weightpaint mode: Undo'] ,
['Ctrl-U', 'Save current state as user default'],
['Shift-U', 'Edit Mode: Redo Menu'],
['Alt-U', 'Edit Mode & Object Mode: Undo Menu'],
['.', '...']
],
"V":[
['V', 'Curves/Nurbs: Vector handle'],
['V', 'Edit Mode : Rip selected vertices'],
['V', 'Vertexpaint mode'],
['V', 'UV Image Editor: Stitch UVs'],
['Ctrl-V',' UV Image Editor: maximize stretch.'],
['V', 'Action editor: Vector'],
['Alt-V', "Scale object to match image texture's aspect ratio"],
['Alt-V', 'Text Editor : Paste '],
['Alt-Shift-V', 'Text Editor : View menu'],
['Alt-Shift-V', 'Text Editor : View menu 1, Top of the file '],
['Alt-Shift-V', 'Text Editor : View menu 2, Bottom of the file '],
['Alt-Shift-V', 'Text Editor : View menu 3, PageUp'],
['Alt-Shift-V', 'Text Editor : View menu 4, PageDown'],
['Ctrl-Shift-V', 'Text Editor: Paste from clipboard'],
['Shift-V', 'Edit mode: Align view to selected vertices'],
['Shift-V', 'UV Image Editor: Limited Stitch UVs popup'],
['.', '...']
],
"W":[
['W', 'Edit Mode: Specials menu'],
['W', 'Edit Mode: Specials menu, ARMATURE 1 Subdivide'],
['W', 'Edit Mode: Specials menu, ARMATURE 2 Subdivide Multi'],
['W', 'Edit Mode: Specials menu, ARMATURE 3 Switch Direction'],
['W', 'Edit Mode: Specials menu, ARMATURE 4 Flip Left-Right Name'],
['W', 'Edit Mode: Specials menu, ARMATURE 5 AutoName Left-Right'],
['W', 'Edit Mode: Specials menu, ARMATURE 6 AutoName Front-Back'],
['W', 'Edit Mode: Specials menu, ARMATURE 7 AutoName Top-Bottom'],
['W', 'Edit Mode: Specials menu, CURVE 1 Subdivide'],
['W', 'Edit Mode: Specials menu, CURVE 2 Swich Direction'],
['W', 'Edit Mode: Specials menu, CURVE 3 Set Goal Weight'],
['W', 'Edit Mode: Specials menu, CURVE 4 Set Radius'],
['W', 'Edit Mode: Specials menu, CURVE 5 Smooth'],
['W', 'Edit Mode: Specials menu, CURVE 6 Smooth Radius'],
['W', 'Edit Mode: Specials menu, MESH 1 Subdivide'],
['W', 'Edit Mode: Specials menu, MESH 2 Subdivide Multi'],
['W', 'Edit Mode: Specials menu, MESH 3 Subdivide Multi Fractal'],
['W', 'Edit Mode: Specials menu, MESH 4 Subdivide Smooth'],
['W', 'Edit Mode: Specials menu, MESH 5 Merge'],
['W', 'Edit Mode: Specials menu, MESH 6 Remove Double'],
['W', 'Edit Mode: Specials menu, MESH 7 Hide'],
['W', 'Edit Mode: Specials menu, MESH 8 Reveal'],
['W', 'Edit Mode: Specials menu, MESH 9 Select Swap'],
['W', 'Edit Mode: Specials menu, MESH 10 Flip Normal'],
['W', 'Edit Mode: Specials menu, MESH 11 Smooth'],
['W', 'Edit Mode: Specials menu, MESH 12 Bevel'],
['W', 'Edit Mode: Specials menu, MESH 13 Set Smooth'],
['W', 'Edit Mode : Specials menu, MESH 14 Set Solid'],
['W', 'Object Mode : on MESH objects, Boolean Tools menu'],
['W', 'Object Mode : on MESH objects, Boolean Tools 1 Intersect'],
['W', 'Object Mode : on MESH objects, Boolean Tools 2 union'],
['W', 'Object Mode : on MESH objects, Boolean Tools 3 difference'],
['W', 'Object Mode : on MESH objects, Boolean Tools 4 Add an intersect Modifier'],
['W', 'Object Mode : on MESH objects, Boolean Tools 5 Add an union Modifier'],
['W', 'Object Mode : on MESH objects, Boolean Tools 6 Add a difference Modifier'],
['W', 'Object mode : on TEXT object, Split characters, a new TEXT object by character in the selected string '],
['W', 'UV Image Editor: Weld/Align'],
['WX', 'UV Image Editor: Weld/Align X axis'],
['WY', 'UV Image Editor: Weld/Align Y axis'],
['Ctrl-W', 'Save current file'] ,
['Shift-W', 'Warp/bend selected vertices around cursor'],
['.', '...']
],
"X":[
['X', 'Delete menu'] ,
['X', 'TimeLine : Remove marker'],
['X', 'NLA : Remove marker'],
['X', 'IPO : Remove marker'],
['X', 'NODE window : delete'], #243
['Alt-X', 'Text Editor : Cut '],
['Alt-X', 'Grease Pencil: Delete menu'],
['Ctrl-X', 'Restore default state (Erase all)'],
['.', '...']
],
"Y":[
['Y', 'Edit Mode & Mesh : Split selected vertices/faces from the rest'],
['Ctrl-Y', 'Object Mode : Redo'],
['.', '...']
],
"Z":[
['Z', 'Render Window: 200% zoom from mouse position'],
['Z', 'Switch 3d draw type : solide/ wireframe (see also D)'],
['Alt-Z', 'Switch 3d draw type : solid / textured (see also D)'],
['Alt-Z,','Text editor : undo '],
['Ctrl-Z', 'Object Mode : Undo'],
['Ctrl-Z,','Text editor : undo '],
['Ctrl-Shift-Z,','Text editor : Redo '],
['Shift-Z', 'Switch 3d draw type : shaded / wireframe (see also D)'],
['.', '...']
]}]}
up=128
down=129
UP=0
SEARCH=131
OLDSEARCHLINE=''
SEARCHLINE=Create('')
LINE=130
FINDED=[]
LEN=0
for k in hotkeys.keys():
hotkeys[k].append(Create(0))
for k in hotkeys['Letters '][0]:
hotkeys['Letters '][0][k].append(Create(0))
hotL=hotkeys['Letters '][0].keys()
hotL.sort()
hot=hotkeys.keys()
hot.sort()
def searchfor(SEARCHLINE):
global hotkeys, hot
FINDLIST=[]
for k in hot:
if k not in ['Letters ', 'Search '] :
for l in hotkeys[k][:-1]:
#print 'k, l : ', k, l, l[1]
if l[1].upper().find(SEARCHLINE.upper())!=-1:
FINDLIST.append(l)
elif k == 'Letters ':
for l in hotL :
for l0 in hotkeys['Letters '][0][l][:-1]:
#print 'k, l : ',l, k, l0
if l0[1].upper().find(SEARCHLINE.upper())!=-1:
FINDLIST.append(l0)
#print 'FINDLIST',FINDLIST
FINDLIST.append(['Find list','Entry'])
return FINDLIST
glCr=glRasterPos2d
glCl3=glColor3f
glCl4=glColor4f
glRct=glRectf
cf=[0.95,0.95,0.9,0.0]
c1=[0.95,0.95,0.9,0.0]
c=cf
r=[0,0,0,0]
def trace_rectangle4(r,c):
glCl4(c[0],c[1],c[2],c[3])
glRct(r[0],r[1],r[2],r[3])
def trace_rectangle3(r,c,c1):
glCl3(c[0],c[1],c[2])
glRct(r[0],r[1],r[2],r[3])
glCl3(c1[0],c1[1],c1[2])
def draw():
global r,c,c1,hotkeys, hot, hotL, up, down, UP, SEARCH, SEARCHLINE,LINE
global OLDSEARCHLINE, FINDED, SCROLL, LEN
size=Buffer(GL_FLOAT, 4)
glGetFloatv(GL_SCISSOR_BOX, size)
size= size.list
for s in [0,1,2,3]: size[s]=int(size[s])
c=[0.75,0.75,0.75,0]
c1=[0.6,0.6,0.6,0]
r=[0,size[3],size[2],0]
trace_rectangle4(r,c)
c=[0.64,0.64,0.64,0]
c1=[0.95,0.95,0.9,0.0]
r=[0,size[3],size[2],size[3]-40]
trace_rectangle4(r,c)
c1=[0.7,0.7,0.9,0.0]
c=[0.2,0.2,0.4,0.0]
c2=[0.71,0.71,0.71,0.0]
glColor3f(1, 1, 1)
glRasterPos2f(42, size[3]-25)
Text("HotKey and MouseAction Reference")
l=0
listed=0
Llisted=0
size[3]=size[3]-18
BeginAlign()
for i, k in enumerate(hot):
hotkeys[k][-1]=Toggle(k, i+10, 78*i, size[3]-(47), 78, 24, hotkeys[k][-1].val )
l+=len(k)
if hotkeys[k][-1].val==1.0:
listed= i
EndAlign()
l=0
size[3]=size[3]-4
if hot[listed]!='Letters ' and hot[listed]!='Search ' :
size[3]=size[3]-8
SCROLL=size[3]/21
END=-1
if SCROLL < len(hotkeys[hot[listed]][:-1]):
BeginAlign()
Button('/\\',up,4,size[3]+8,20,14,'Scroll up')
Button('\\/',down,4,size[3]-8,20,14,'Scroll down')
EndAlign()
if (SCROLL+UP)<len(hotkeys[hot[listed]][:-1]):
END=(UP+SCROLL)
else:
END=-1
UP=len(hotkeys[hot[listed]][:-1])-SCROLL
else :
UP=0
for n in hotkeys[hot[listed]][:-1][UP:END]:
if l%2==0:
r=[0,size[3]-(21*l+66),
size[2], size[3]-(21*l+43)]
trace_rectangle4(r,c2)
glColor3f(0,0,0)
glRasterPos2f(4+8, size[3]-(58+21*l))
Text(n[0])
glRasterPos2f(4+8*15, size[3]-(58+21*l))
Text(' : '+n[1])
l+=1
elif hot[listed]=='Search ' :
r=[0,size[3]-70,
size[2], size[3]-44]
trace_rectangle4(r,c2)
SEARCHLINE=String(' ', LINE, 42, size[3]-68,200,18,SEARCHLINE.val, 256,'')
if len(FINDED)>0:
LEN=len(FINDED)
size[3]=size[3]-8
SCROLL=size[3]/21
END=-1
if SCROLL < len(FINDED):
BeginAlign()
Button('/\\',up,4,size[3]+8,20,14,'Scroll up')
Button('\\/',down,4,size[3]-8,20,14,'Scroll down')
EndAlign()
if (SCROLL+UP)<len(FINDED):
END=(UP+SCROLL-1)
else:
END=-1
#UP=len(FINDED)-SCROLL
else:
UP=0
for n in FINDED[UP:END]:
if l%2==0:
r=[0,size[3]-(21*l+66+24),
size[2], size[3]-(21*l+43+24)]
trace_rectangle4(r,c2)
glColor3f(0,0,0)
glRasterPos2f(4+8, size[3]-(58+24+21*l))
Text(n[0])
glRasterPos2f(4+8*15, size[3]-(58+24+21*l))
Text(' : '+n[1])
l+=1
else:
BeginAlign()
for pos, k in enumerate(hotL):
hotkeys['Letters '][0][k][-1]=Toggle(k,pos+20,pos*21, size[3]-(52+18), 21, 18, hotkeys['Letters '][0][k][-1].val )
if hotkeys['Letters '][0][k][-1].val==1.0:
Llisted=pos
EndAlign()
size[3]=size[3]-8
SCROLL=(size[3]-88)/21
END=-1
if SCROLL < len(hotkeys['Letters '][0][hotL[Llisted]]):
LEN=len(hotkeys['Letters '][0][hotL[Llisted]])
BeginAlign()
Button('/\\',up,4,size[3]+8,20,14,'Scroll up, you can use arrow or page keys too ')
Button('\\/',down,4,size[3]-8,20,14,'Scroll down, you can use arrow or page keys too ')
EndAlign()
if (UP+SCROLL)<len(hotkeys['Letters '][0][hotL[Llisted]]):
END=(UP+SCROLL)
else:
END=-1
UP=len(hotkeys['Letters '][0][hotL[Llisted]])-SCROLL
else :
UP=0
for n in hotkeys['Letters '][0][hotL[Llisted]][UP:END]:
if l%2==0:
r=[4,size[3]-(21*l+92),
size[2], size[3]-(69+21*l+1)]
trace_rectangle4(r,c2)
glColor3f(0.1, 0.1, 0.15)
glRasterPos2f(4+8, (size[3]-(88+21*l))+3)
Text(n[0])
glRasterPos2f(4+8*15, (size[3]-(88+21*l))+3)
Text(' : '+n[1])
l+=1
def event(evt, val):
global hotkeys, UP, SCROLL , LEN
if (evt== QKEY or evt== ESCKEY):
Exit()
elif val:
if (evt== PAGEUPKEY):
if (UP+SCROLL)<LEN-5:
UP+=5
elif (evt== PAGEDOWNKEY):
if UP>4:
UP-=5
elif (evt== UPARROWKEY):
if (UP+SCROLL)<LEN-1:
UP+=1
elif (evt== DOWNARROWKEY):
if UP>0:
UP-=1
Redraw()
def bevent(evt):
global hotkeysmhot, hotL, up,down,UP, FINDED
global SEARCH, SEARCHLINE,LINE, OLDSEARCHLINE
if (evt== 1):
Exit()
elif 9 < evt < 20:
for i, k in enumerate(hot):
if i+10!=evt:
hotkeys[k][-1].val=0
UP=0
Blender.Window.Redraw()
elif 19 < evt < 46:
for i, k in enumerate(hotL):
if i+20!=evt:
hotkeys['Letters '][0][k][-1].val=0
UP=0
Blender.Window.Redraw()
elif (evt==up):
UP+=1
Blender.Window.Redraw()
elif (evt==down):
if UP>0: UP-=1
Blender.Window.Redraw()
elif (evt==LINE):
if SEARCHLINE.val!='' and SEARCHLINE.val!=OLDSEARCHLINE:
OLDSEARCHLINE=SEARCHLINE.val
FINDED=searchfor(OLDSEARCHLINE)
Blender.Window.Redraw()
if __name__ == '__main__':
Register(draw, event, bevent)

View File

@@ -1,559 +0,0 @@
#!BPY
"""
Name: '2D Cutout Image Importer'
Blender: 249
Group: 'Image'
Tooltip: 'Batch UV Map images to Planes'
"""
__author__ = "Kevin Morgan (forTe)"
__url__ = ("Home page, http://gamulabs.freepgs.com")
__version__ = "1.2.1"
__bpydoc__ = """\
This Script will take an image and
UV map it to a plane sharing the same width to height ratio as the image.
Import options allow for the image to be a still or sequence type image
<br><br>
Imports can be single images or whole directories of images depending on the chosen
option.
"""
####################################################
#Copyright (C) 2008: Kevin Morgan
####################################################
#-------------GPL LICENSE BLOCK-------------
#This program is free software: you can redistribute it and/or modify
#it under the terms of the GNU General Public License as published by
#the Free Software Foundation, either version 3 of the License, or
#(at your option) any later version.
#
#This program is distributed in the hopes that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
#GNU General Public License for more details.
#
#You should have received a copy of the GNU General Public License
#along with this program. If not, see <http://www.gnu.org/licenses>.
####################################################
####################################################
#V1.0
#Basic Functionality
#Published June 28, 2007
####################################################
#V1.1
#Added Support for enabling viewport transparency
#Added more options to the UI for materials
#Added Proportionality code (Pixels per unit)
#Added GPL License Block
#Published June 29, 2007
####################################################
#V1.2
#Added Support for Copying Existing Materials
#Import Images as Sequences
#Refreshed GUI - now with more clutter :(
#Miscellaneous and Housekeeping
#Published June 16, 2008
####################################################
#V1.2.1
#Added Extend Texture Mode option at request of a user
#Published September 24, 2008
####################################################
import Blender
from Blender import BGL, Draw, Image, Mesh, Material, Texture, Window
from Blender.Mathutils import *
import bpy
# Global Constants
DIR = 0
SINGLE = 1
CUROFFS = 0
# GUI CONSTANTS
NO_EVT = 0
SINGLE_IMG = 1
DIRECTORY_IMG = 2
CLR_PATH = 3
CHG_EXT = 4
EXIT = 5
DO_SCRIPT = 6
VERSIONSTRING = '1.2.1'
# Note the two parameter dicts could be combined, I just, liked them seperate...
# GUI Buttons Dict
GUIPARAMS = {
'Path': Draw.Create(''),
'ImageExt': Draw.Create(''),
'Seq': Draw.Create(0),
'PackImage': Draw.Create(0),
'PPU': Draw.Create(50),
'VPTransp': Draw.Create(1),
'XOff': Draw.Create(0.0),
'YOff': Draw.Create(0.0),
'ZOff': Draw.Create(0.0),
'CopyMat': Draw.Create(0),
'MatId': Draw.Create(0),
'MatCol': Draw.Create(1.0, 0.0, 0.0),
'Ref': Draw.Create(0.8),
'Spec': Draw.Create(0.5),
'Hard': Draw.Create(50),
'Alpha': Draw.Create(1.0),
'ZTransp': Draw.Create(1),
'Shadeless': Draw.Create(0),
'TexChan': Draw.Create(1),
'MPTCol': Draw.Create(1),
'MPTAlpha': Draw.Create(1),
'UseAlpha': Draw.Create(1),
'CalcAlpha': Draw.Create(0),
'ExtendMode': Draw.Create(0),
'AutoRefresh': Draw.Create(0),
'Cyclic': Draw.Create(0),
'Frames': Draw.Create(100),
'Offs': Draw.Create(0),
'StartFr': Draw.Create(1),
'RedrawImp': Draw.Create(0)
}
# Script Execution Paramaters
PARAMS = {
'ImagePaths': [], # Path to images to import
'ImportType': SINGLE, # Import a Directory or a Single Image?
'ImageProp': Image.Sources.STILL, # What sources for the image, still or sequence
'PackImage': 0, # Pack the Image(s)?
'PPU': 20, # Pixels Per Blender Unit
'MakeTransp': 1, # Make face transparent in viewport
'NewMat': 1, # If true make a new material, otherwise duplicate an existing one, replacing appropriate attributes
'MaterialId': 0, # ID to take from the Materials list upon copy
'Materials': None, # Materials in Scene
'MatProps': {'Col': [1.0, 0.0, 0.0], 'Shadeless': 1, 'Ref': 0.5, 'Spec': 0.5, 'Hard': 200, 'Alpha': 1.0, 'ZTransp': 1},
'TexProps': {'UseAlpha': 1, 'CalcAlpha': 0, 'ExtendMode': 0}, # Texture Properties
'TexChannel': 0, # Texture Channel
'TexMapTo': {'Col': 1, 'Alpha': 1}, # Map to Col and/or Alpha
'SeqProps': {'AutoRefresh': 0, 'Cyclic': 0, 'Frames': 100, 'Offs': 0, 'StartFr': 1},
'ObOffset': Vector(1, 0, 0) # Offset by this vector upon creation for multifile import
}
# Get the Active Scene, of course
scn = bpy.data.scenes.active
##########################################
# MAIN SCRIPT FUNCTIONS
##########################################
def imgImport(imgPath):
global CUROFFS, PARAMS
######################################
# Load the image
######################################
try:
img = Image.Load(imgPath)
imgDimensions = img.getSize() # do this to ensure the data is available
except:
Blender.Draw.PupMenu('Error%t|Unsupported image format for "'+ imgPath.split('\\')[-1].split('/')[-1] +'"')
return
if PARAMS['PackImage']:
img.pack()
name = Blender.sys.makename(imgPath, strip = 1)
######################################
# Construct the mesh
######################################
me = Mesh.New(name)
# Calculate Dimensions from Image Size
dim = [float(i)/PARAMS['PPU'] for i in imgDimensions]
v = [[dim[0], dim[1], 0], [-dim[0], dim[1], 0], [-dim[0], -dim[1], 0], [dim[0], -dim[1], 0]]
me.verts.extend(v)
me.faces.extend([0, 1, 2, 3])
me.faces[0].image = img
me.faces[0].uv = [Vector(1.0, 1.0), Vector(0.0, 1.0), Vector(0.0, 0.0), Vector(1.0, 0.0)]
if PARAMS['MakeTransp']:
me.faces[0].transp = Mesh.FaceTranspModes.ALPHA
######################################
# Modify the Material
######################################
mat = None
if not PARAMS['NewMat']:
mat = PARAMS['Materials'][PARAMS['MaterialId']].__copy__()
mat.setName(name)
else:
mat = Material.New(name)
properties = PARAMS['MatProps']
mat.setRGBCol(properties['Col'])
mat.setRef(properties['Ref'])
mat.setSpec(properties['Spec'])
mat.setHardness(properties['Hard'])
mat.setAlpha(properties['Alpha'])
if properties['Shadeless']:
mat.mode |= Material.Modes.SHADELESS
if properties['ZTransp']:
mat.mode |= Material.Modes.ZTRANSP
properties = PARAMS['TexProps']
tex = Texture.New(name)
tex.setType('Image')
tex.setImage(img)
if properties['UseAlpha']:
tex.useAlpha = Texture.ImageFlags.USEALPHA
if properties['CalcAlpha']:
tex.calcAlpha = Texture.ImageFlags.CALCALPHA
if properties['ExtendMode']:
tex.setExtend('Extend')
if PARAMS['ImageProp'] == Image.Sources.SEQUENCE:
properties = PARAMS['SeqProps']
img.source = PARAMS['ImageProp'] # Needs to be done here, otherwise an error with earlier getSize()
tex.animStart = properties['StartFr']
tex.animOffset = properties['Offs']
tex.animFrames = properties['Frames']
tex.autoRefresh = properties['AutoRefresh']
tex.cyclic = properties['Cyclic']
texMapSetters = Texture.TexCo.UV
# PARAMS['TexMapTo']['Col'] (and alpha) will either be 0 or 1 because its from a toggle, otherwise this line doesn't work
texChanSetters = Texture.MapTo.COL * PARAMS['TexMapTo']['Col'] | Texture.MapTo.ALPHA * PARAMS['TexMapTo']['Alpha']
mat.setTexture(PARAMS['TexChannel'], tex, texMapSetters, texChanSetters)
me.materials += [mat]
######################################
# Object Construction
######################################
ob = scn.objects.new(me, name)
p = Vector(ob.getLocation()) # Should be the origin, but just to be safe, get it
ob.setLocation((CUROFFS * PARAMS['ObOffset']) + p)
return
def translateParams():
# Translates (or assigns for the most part) GUI values to those that can be read by the
# Import Function
global GUIPARAMS, PARAMS
if GUIPARAMS['Seq'].val and PARAMS['ImportType'] != DIR:
PARAMS['ImageProp'] = Image.Sources.SEQUENCE
PARAMS['PackImage'] = GUIPARAMS['PackImage'].val
PARAMS['PPU'] = GUIPARAMS['PPU'].val
PARAMS['MakeTransp'] = GUIPARAMS['VPTransp'].val
PARAMS['ObOffset'] = Vector(GUIPARAMS['XOff'].val, GUIPARAMS['YOff'].val, GUIPARAMS['ZOff'].val)
PARAMS['NewMat'] = not GUIPARAMS['CopyMat'].val
PARAMS['MaterialId'] = GUIPARAMS['MatId'].val
PARAMS['MatProps']['Col'] = list(GUIPARAMS['MatCol'].val)
PARAMS['MatProps']['Ref'] = GUIPARAMS['Ref'].val
PARAMS['MatProps']['Spec'] = GUIPARAMS['Spec'].val
PARAMS['MatProps']['Hard'] = GUIPARAMS['Hard'].val
PARAMS['MatProps']['Alpha'] = GUIPARAMS['Alpha'].val
PARAMS['MatProps']['ZTransp'] = GUIPARAMS['ZTransp'].val
PARAMS['MatProps']['Shadeless'] = GUIPARAMS['Shadeless'].val
PARAMS['TexChannel'] = GUIPARAMS['TexChan'].val - 1 #Channels are 0-9, but GUI shows 1-10
PARAMS['TexProps']['UseAlpha'] = GUIPARAMS['UseAlpha'].val
PARAMS['TexProps']['CalcAlpha'] = GUIPARAMS['CalcAlpha'].val
PARAMS['TexProps']['ExtendMode'] = GUIPARAMS['ExtendMode'].val
PARAMS['TexMapTo']['Col'] = GUIPARAMS['MPTCol'].val
PARAMS['TexMapTo']['Alpha'] = GUIPARAMS['MPTAlpha'].val
PARAMS['SeqProps']['AutoRefresh'] = GUIPARAMS['AutoRefresh'].val
PARAMS['SeqProps']['Cyclic'] = GUIPARAMS['Cyclic'].val
PARAMS['SeqProps']['Frames'] = GUIPARAMS['Frames'].val
PARAMS['SeqProps']['Offs'] = GUIPARAMS['Offs'].val
PARAMS['SeqProps']['StartFr'] = GUIPARAMS['StartFr'].val
return
def doScript():
# Main script Function
# Consists of choosing between 2 loops, one with a redraw, one without, see comments for why
global CUROFFS
translateParams()
total = len(PARAMS['ImagePaths'])
broken = 0
if GUIPARAMS['RedrawImp'].val: # Reduces the need to compare on every go through the loop
for i, path in enumerate(PARAMS['ImagePaths']):
CUROFFS = i # Could be passed to the import Function, but I chose a global instead
Window.DrawProgressBar(float(i)/total, "Importing %i of %i Images..." %(i+1, total))
imgImport(path)
Blender.Redraw()
if Blender.Get('version') >= 246:
if Window.TestBreak():
broken = 1
break
else:
for i, path in enumerate(PARAMS['ImagePaths']):
CUROFFS = i
Window.DrawProgressBar(float(i)/total, "Importing %i of %i Images..." %(i+1, total))
imgImport(path)
if Blender.Get('version') >= 246:
if Window.TestBreak():
broken = 1
break
if broken:
Window.DrawProgressBar(1.0, "Script Execution Aborted")
else:
Window.DrawProgressBar(1.0, "Finished Importing")
Blender.Redraw() # Force a refresh, since the user may have chosen to not refresh as they go along
return
##########################################
# PATH SETTERS AND CHANGERS
##########################################
def setSinglePath(filename):
global GUIPARAMS, PARAMS
GUIPARAMS['Path'].val = filename
PARAMS['ImagePaths'] = [filename]
return
def setDirPath(filename):
global GUIPARAMS, PARAMS
try:
import os
except:
Draw.PupMenu('Full install of python required to be able to set Directory Paths')
Draw.Exit()
return
path = os.path.dirname(filename) # Blender.sys.dirname fails on '/'
GUIPARAMS['Path'].val = path
ext_lower = GUIPARAMS['ImageExt'].val.lower()
for f in os.listdir(path):
if f.lower().endswith(ext_lower):
PARAMS['ImagePaths'].append(os.path.join(path, f))
return
def changeExtension():
global GUIPARAMS, PARAMS
if PARAMS['ImportType'] == SINGLE:
return
try:
import os
except:
Draw.PupMenu('Full install of python required to be able to set Directory Paths')
Draw.Exit()
return
PARAMS['ImagePaths'] = []
ext_lower = GUIPARAMS['ImageExt'].val.lower()
for f in os.listdir(GUIPARAMS['Path'].val):
if f.lower().endswith(ext_lower):
PARAMS['ImagePaths'].append(os.path.join(GUIPARAMS['Path'].val, f))
return
##########################################
# INTERFACE FUNCTIONS
##########################################
def compileMaterialList():
# Pretty straight forward, just grabs the materials in the blend file and constructs
# an appropriate string for use as a menu
mats = [mat for mat in bpy.data.materials]
PARAMS['Materials'] = mats
title = 'Materials%t|'
menStrs = [mat.name + '%x' + str(i) + '|' for i, mat in enumerate(mats)]
return title + ''.join(menStrs)
def event(evt, val):
# Disabled, since Esc is often used from the file browser
#if evt == Draw.ESCKEY:
# Draw.Exit()
return
def bevent(evt):
global GUIPARAMS, PARAMS
if evt == NO_EVT:
Draw.Redraw()
elif evt == SINGLE_IMG:
Window.FileSelector(setSinglePath, 'Image', Blender.sys.expandpath('//'))
Draw.Redraw()
PARAMS['ImportType'] = SINGLE
elif evt == DIRECTORY_IMG:
Window.FileSelector(setDirPath, 'Directory', Blender.sys.expandpath('//'))
Draw.Redraw()
PARAMS['ImportType'] = DIR
elif evt == CLR_PATH:
GUIPARAMS['Path'].val = ''
PARAMS['ImagePaths'] = []
GUIPARAMS['ImageExt'].val = ''
Draw.Redraw()
elif evt == CHG_EXT:
changeExtension()
Draw.Redraw()
elif evt == EXIT:
Draw.Exit()
elif evt == DO_SCRIPT:
doScript()
else:
print "ERROR: UNEXPECTED BUTTON EVENT"
return
# GUI Colors ######
ScreenColor = [0.7, 0.7, 0.7]
BackgroundColor = [0.8, 0.8, 0.8]
TitleBG = [0.6, 0.6, 0.6]
TitleCol = [1.0, 1.0, 1.0]
ErrCol = [1.0, 0.0, 0.0]
TextCol = [0.4, 0.4, 0.5]
###################
def GUI():
global GUIPARAMS, PARAMS
BGL.glClearColor(*(ScreenColor + [1.0]))
BGL.glClear(BGL.GL_COLOR_BUFFER_BIT)
minx = 5
maxx = 500
miny = 5
maxy = 450
lineheight = 24
buPad = 5 # Generic Button Padding, most buttons should have 24-19 (or 5) px space around them
lP = 5 # Left Padding
rP = 5 # Right Padding
# Draw Background Box
BGL.glColor3f(*BackgroundColor)
BGL.glRecti(minx, miny, maxx, maxy)
# Draw Title
BGL.glColor3f(*TitleBG)
BGL.glRecti(minx, maxy - (lineheight), maxx, maxy)
BGL.glColor3f(*TitleCol)
title = "2D Cutout Image Importer v" + VERSIONSTRING
BGL.glRasterPos2i(minx + lP, maxy - 15)
Draw.Text(title, 'large')
Draw.PushButton('Exit', EXIT, maxx-50-rP, maxy - lineheight + 2, 50, 19, "Exit Script")
# Path Buttons
if GUIPARAMS['Path'].val == '':
Draw.PushButton('Single Image', SINGLE_IMG, minx + lP, maxy - (2*lineheight), 150, 19, "Select a Single Image to Import")
Draw.PushButton('Directory', DIRECTORY_IMG, minx + lP + 150, maxy - (2*lineheight), 150, 19, "Select a Directory of Images to Import")
else:
Draw.PushButton('Clear', CLR_PATH, minx+lP, maxy - (2*lineheight), 50, 19, "Clear Path and Change Import Options")
GUIPARAMS['Path'] = Draw.String('Path: ', NO_EVT, minx + lP, maxy - (3*lineheight), (maxx-minx-lP-rP), 19, GUIPARAMS['Path'].val, 399, 'Path to Import From')
if PARAMS['ImportType'] == DIR:
GUIPARAMS['ImageExt'] = Draw.String('Image Ext: ', CHG_EXT, minx + lP, maxy - (4*lineheight), 110, 19, GUIPARAMS['ImageExt'].val, 6, 'Image extension for batch directory importing (case insensitive)')
GUIPARAMS['PackImage'] = Draw.Toggle('Pack', NO_EVT, maxx - rP - 50, maxy - (4*lineheight), 50, 19, GUIPARAMS['PackImage'].val, 'Pack Image(s) into .Blend File')
# Geometry and Viewport Options
BGL.glColor3f(*TextCol)
BGL.glRecti(minx+lP, maxy - (5*lineheight), maxx-rP, maxy - (5*lineheight) + 1)
BGL.glRasterPos2i(minx + lP, maxy-(5*lineheight) + 3)
Draw.Text('Geometry and Display Options', 'small')
GUIPARAMS['PPU'] = Draw.Slider('Pixels Per Unit: ', NO_EVT, minx + lP, maxy - (6*lineheight), (maxx-minx)/2 - lP, 19, GUIPARAMS['PPU'].val, 1, 5000, 0, 'Set the Number of Pixels Per Blender Unit to preserve Image Size Relations')
GUIPARAMS['VPTransp'] = Draw.Toggle('Viewport Transparency', NO_EVT, minx + lP, maxy - (8*lineheight), (maxx-minx)/2 - lP, 2*lineheight - buPad, GUIPARAMS['VPTransp'].val, 'Display Alpha Transparency in the Viewport')
GUIPARAMS['XOff'] = Draw.Slider('Offs X: ', NO_EVT, minx + lP + (maxx-minx)/2, maxy - (6*lineheight), (maxx-minx)/2 - lP - rP, 19, GUIPARAMS['XOff'].val, 0, 5.0, 0, 'Amount to Offset Each Imported in the X-Direction if Importing Multiple Images')
GUIPARAMS['YOff'] = Draw.Slider('Offs Y: ', NO_EVT, minx + lP + (maxx-minx)/2, maxy - (7*lineheight), (maxx-minx)/2 - lP - rP, 19, GUIPARAMS['YOff'].val, 0, 5.0, 0, 'Amount to Offset Each Imported in the Y-Direction if Importing Multiple Images')
GUIPARAMS['ZOff'] = Draw.Slider('Offs Z: ', NO_EVT, minx + lP + (maxx-minx)/2, maxy - (8*lineheight), (maxx-minx)/2 - lP - rP, 19, GUIPARAMS['ZOff'].val, 0, 5.0, 0, 'Amount to Offset Each Imported in the Z-Direction if Importing Multiple Images')
# Material and Texture Options
BGL.glColor3f(*TextCol)
BGL.glRecti(minx+lP, maxy - (9*lineheight), maxx-rP, maxy - (9*lineheight) + 1)
BGL.glRasterPos2i(minx + lP, maxy-(9*lineheight) + 3)
Draw.Text('Material and Texture Options', 'small')
half = (maxx-minx-lP-rP)/2
GUIPARAMS['CopyMat'] = Draw.Toggle('Copy Existing Material', NO_EVT, minx + lP, maxy-(10*lineheight), half, 19, GUIPARAMS['CopyMat'].val, 'Copy an Existing Material')
if GUIPARAMS['CopyMat'].val:
menStr = compileMaterialList()
GUIPARAMS['MatId'] = Draw.Menu(menStr, NO_EVT, minx + lP, maxy - (11*lineheight), half, 19, GUIPARAMS['MatId'].val, 'Material to Copy Settings From')
else:
GUIPARAMS['MatCol'] = Draw.ColorPicker(NO_EVT, minx+lP, maxy - (13*lineheight), 40, (3*lineheight) - buPad, GUIPARAMS['MatCol'].val, 'Color of Newly Created Material')
GUIPARAMS['Ref'] = Draw.Slider('Ref: ', NO_EVT, minx +lP+45, maxy - (11*lineheight), half-45, 19, GUIPARAMS['Ref'].val, 0.0, 1.0, 0, 'Set the Ref Value for Created Materials')
GUIPARAMS['Spec'] = Draw.Slider('Spec: ', NO_EVT, minx +lP+45, maxy - (12*lineheight), half-45, 19, GUIPARAMS['Spec'].val, 0.0, 2.0, 0, 'Set the Spec Value for Created Materials')
GUIPARAMS['Hard'] = Draw.Slider('Hard: ', NO_EVT, minx +lP+45, maxy - (13*lineheight), half-45, 19, GUIPARAMS['Hard'].val, 1, 500, 0, 'Set the Hardness Value for Created Materials')
GUIPARAMS['Alpha'] = Draw.Slider('A: ', NO_EVT, minx +lP, maxy - (14*lineheight), half, 19, GUIPARAMS['Alpha'].val, 0.0, 1.0, 0, 'Set the Alpha Value for Created Materials')
GUIPARAMS['ZTransp'] = Draw.Toggle('ZTransparency', NO_EVT, minx + lP, maxy - (15*lineheight), half, 19, GUIPARAMS['ZTransp'].val, 'Enable ZTransparency')
GUIPARAMS['Shadeless'] = Draw.Toggle('Shadeless', NO_EVT, minx + lP, maxy - (16*lineheight), half, 19, GUIPARAMS['Shadeless'].val, 'Enable Shadeless')
GUIPARAMS['TexChan'] = Draw.Number('Texture Channel: ', NO_EVT, minx + lP+ half + buPad, maxy - (10*lineheight), half-rP, 19, GUIPARAMS['TexChan'].val, 1, 10, 'Texture Channel for Image Texture')
GUIPARAMS['MPTCol'] = Draw.Toggle('Color', NO_EVT, minx + lP + half + buPad, maxy - (11*lineheight), half/2, 19, GUIPARAMS['MPTCol'].val, 'Map To Color Channel')
GUIPARAMS['MPTAlpha'] = Draw.Toggle('Alpha', NO_EVT, minx + lP + int((1.5)*half) + buPad, maxy - (11*lineheight), half/2 - rP, 19, GUIPARAMS['MPTAlpha'].val, 'Map To Alpha Channel')
third = int((maxx-minx-lP-rP)/6)
GUIPARAMS['UseAlpha'] = Draw.Toggle('Use Alpha', NO_EVT, minx + lP + half + buPad, maxy - (12*lineheight), third, 19, GUIPARAMS['UseAlpha'].val, "Use the Images' Alpha Values")
GUIPARAMS['CalcAlpha'] = Draw.Toggle('Calc Alpha', NO_EVT, minx + lP + half + third + buPad, maxy - (12*lineheight), third, 19, GUIPARAMS['CalcAlpha'].val, "Calculate Images' Alpha Values")
GUIPARAMS['ExtendMode'] = Draw.Toggle('Extend', NO_EVT, minx+lP+half+third+third+buPad, maxy - (12*lineheight), third-3, 19, GUIPARAMS['ExtendMode'].val, "Use Extend texture mode. If deselected, Repeat is used")
GUIPARAMS['Seq'] = Draw.Toggle('Sequence', NO_EVT, minx + lP + half + buPad, maxy - (13*lineheight), half-rP, 19, GUIPARAMS['Seq'].val, 'Set the Image(s) to use a Sequence instead of a Still')
if GUIPARAMS['Seq'].val and not PARAMS['ImportType'] == DIR:
GUIPARAMS['AutoRefresh'] = Draw.Toggle('Auto Refresh', NO_EVT, minx + lP + half + buPad, maxy - (14*lineheight), half/2, 19, GUIPARAMS['AutoRefresh'].val, 'Use Auto Refresh')
GUIPARAMS['Cyclic'] = Draw.Toggle('Cyclic', NO_EVT, minx + lP + half + buPad + half/2, maxy - (14*lineheight), half/2 - rP, 19, GUIPARAMS['Cyclic'].val, 'Repeat Frames Cyclically`')
GUIPARAMS['Frames'] = Draw.Number('Frames: ', NO_EVT, minx +lP + half + buPad, maxy - (15*lineheight), half - rP, 19, GUIPARAMS['Frames'].val, 1, 30000, 'Sets the Number of Images of a Movie to Use')
GUIPARAMS['Offs'] = Draw.Number('Offs: ', NO_EVT, minx +lP + half + buPad, maxy - (16*lineheight), half/2, 19, GUIPARAMS['Offs'].val, -30000, 30000, 'Offsets the Number of the Frame to use in the Animation')
GUIPARAMS['StartFr'] = Draw.Number('StartFr: ', NO_EVT, minx +lP + half + buPad + half/2, maxy - (16*lineheight), half/2 - rP, 19, GUIPARAMS['StartFr'].val, 1, 30000, 'Sets the Global Starting Frame of the Movie')
elif GUIPARAMS['Seq'].val and PARAMS['ImportType'] == DIR:
BGL.glColor3f(*ErrCol)
BGL.glRasterPos2i(minx + lP + half + buPad + 7, maxy-(14 * lineheight) + 5)
Draw.Text('Sequence only available for Single Image Import', 'small')
# Import Options
BGL.glColor3f(*TextCol)
BGL.glRecti(minx+lP, maxy - (17*lineheight), maxx-rP, maxy - (17*lineheight) + 1)
BGL.glRasterPos2i(minx + lP, maxy-(17*lineheight) + 3)
Draw.Text('Import', 'small')
if GUIPARAMS['Path'].val and GUIPARAMS['ImageExt'].val or GUIPARAMS['Path'].val and PARAMS['ImportType'] == SINGLE:
Draw.PushButton('Import', DO_SCRIPT, minx + lP, maxy - (18*lineheight), 75, 19, "Import Image(s)")
else:
BGL.glColor3f(*ErrCol)
BGL.glRasterPos2i(minx+lP, maxy - (18*lineheight) + 5)
Draw.Text('A path and image type must be specified to import images')
GUIPARAMS['RedrawImp'] = Draw.Toggle('Redraw During Import', NO_EVT, maxx - rP - 150, maxy - (18*lineheight), 150, 19, GUIPARAMS['RedrawImp'].val, 'Redraw the View as Images Import')
Draw.Register(GUI, event, bevent)

View File

@@ -1,455 +0,0 @@
#!BPY
"""
Name: 'Consolidate into one image'
Blender: 243
Group: 'Image'
Tooltip: 'Pack all texture images into 1 image and remap faces.'
"""
__author__ = "Campbell Barton"
__url__ = ("blender", "blenderartists.org")
__version__ = "1.1a 2009/04/01"
__bpydoc__ = """\
This script makes a new image from the used areas of all the images mapped to the selected mesh objects.
Image are packed into 1 new image that is assigned to the original faces.
This is usefull for game models where 1 image is faster then many, and saves the labour of manual texture layout in an image editor.
"""
# --------------------------------------------------------------------------
# Auto Texture Layout v1.0 by Campbell Barton (AKA Ideasman)
# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
# Function to find all the images we use
import Blender as B
from Blender.Mathutils import Vector, RotationMatrix
from Blender.Scene import Render
import BPyMathutils
BIGNUM= 1<<30
TEXMODE= B.Mesh.FaceModes.TEX
def pointBounds(points):
'''
Takes a list of points and returns the
area, center, bounds
'''
ymax= xmax= -BIGNUM
ymin= xmin= BIGNUM
for p in points:
x= p.x
y= p.y
if x>xmax: xmax=x
if y>ymax: ymax=y
if x<xmin: xmin=x
if y<ymin: ymin=y
# area and center
return\
(xmax-xmin) * (ymax-ymin),\
Vector((xmin+xmax)/2, (ymin+ymax)/2),\
(xmin, ymin, xmax, ymax)
def bestBoundsRotation(current_points):
'''
Takes a list of points and returns the best rotation for those points
so they fit into the samllest bounding box
'''
current_area, cent, bounds= pointBounds(current_points)
total_rot_angle= 0.0
rot_angle= 45
while rot_angle > 0.1:
mat_pos= RotationMatrix( rot_angle, 2)
mat_neg= RotationMatrix( -rot_angle, 2)
new_points_pos= [v*mat_pos for v in current_points]
area_pos, cent_pos, bounds_pos= pointBounds(new_points_pos)
# 45d rotations only need to be tested in 1 direction.
if rot_angle == 45:
area_neg= area_pos
else:
new_points_neg= [v*mat_neg for v in current_points]
area_neg, cent_neg, bounds_neg= pointBounds(new_points_neg)
# Works!
#print 'Testing angle', rot_angle, current_area, area_pos, area_neg
best_area= min(area_pos, area_neg, current_area)
if area_pos == best_area:
current_area= area_pos
cent= cent_pos
bounds= bounds_pos
current_points= new_points_pos
total_rot_angle+= rot_angle
elif rot_angle != 45 and area_neg == best_area:
current_area= area_neg
cent= cent_neg
bounds= bounds_neg
current_points= new_points_neg
total_rot_angle-= rot_angle
rot_angle *= 0.5
# Return the optimal rotation.
return total_rot_angle
class faceGroup(object):
'''
A Group of faces that all use the same image, each group has its UVs packed into a square.
'''
__slots__= 'xmax', 'ymax', 'xmin', 'ymin',\
'image', 'faces', 'box_pack', 'size', 'ang', 'rot_mat', 'cent'\
def __init__(self, mesh_list, image, size, PREF_IMAGE_MARGIN):
self.image= image
self.size= size
self.faces= [f for me in mesh_list for f in me.faces if f.mode & TEXMODE and f.image == image]
# Find the best rotation.
all_points= [uv for f in self.faces for uv in f.uv]
bountry_indicies= BPyMathutils.convexHull(all_points)
bountry_points= [all_points[i] for i in bountry_indicies]
# Pre Rotation bounds
self.cent= pointBounds(bountry_points)[1]
# Get the optimal rotation angle
self.ang= bestBoundsRotation(bountry_points)
self.rot_mat= RotationMatrix(self.ang, 2), RotationMatrix(-self.ang, 2)
# Post rotation bounds
bounds= pointBounds([\
((uv-self.cent) * self.rot_mat[0]) + self.cent\
for uv in bountry_points])[2]
# Break the bounds into useable values.
xmin, ymin, xmax, ymax= bounds
# Store the bounds, include the margin.
# The bounds rect will need to be rotated to the rotation angle.
self.xmax= xmax + (PREF_IMAGE_MARGIN/size[0])
self.xmin= xmin - (PREF_IMAGE_MARGIN/size[0])
self.ymax= ymax + (PREF_IMAGE_MARGIN/size[1])
self.ymin= ymin - (PREF_IMAGE_MARGIN/size[1])
self.box_pack=[\
0.0, 0.0,\
size[0]*(self.xmax - self.xmin),\
size[1]*(self.ymax - self.ymin),\
image.name]
'''
# default.
self.scale= 1.0
def set_worldspace_scale(self):
scale_uv= 0.0
scale_3d= 0.0
for f in self.faces:
for i in xrange(len(f.v)):
scale_uv+= (f.uv[i]-f.uv[i-1]).length * 0.1
scale_3d+= (f.v[i].co-f.v[i-1].co).length * 0.1
self.scale= scale_3d/scale_uv
'''
def move2packed(self, width, height):
'''
Moves the UV coords to their packed location
using self.box_pack as the offset, scaler.
box_pack must be set to its packed location.
width and weight are the w/h of the overall packed area's bounds.
'''
# packedLs is a list of [(anyUniqueID, left, bottom, width, height)...]
# Width and height in float pixel space.
# X Is flipped :/
#offset_x= (1-(self.box_pack[1]/d)) - (((self.xmax-self.xmin) * self.image.size[0])/d)
offset_x= self.box_pack[0]/width
offset_y= self.box_pack[1]/height
for f in self.faces:
for uv in f.uv:
uv_rot= ((uv-self.cent) * self.rot_mat[0]) + self.cent
uv.x= offset_x+ (((uv_rot.x-self.xmin) * self.size[0])/width)
uv.y= offset_y+ (((uv_rot.y-self.ymin) * self.size[1])/height)
def consolidate_mesh_images(mesh_list, scn, PREF_IMAGE_PATH, PREF_IMAGE_SIZE, PREF_KEEP_ASPECT, PREF_IMAGE_MARGIN): #, PREF_SIZE_FROM_UV=True):
'''
Main packing function
All meshes from mesh_list must have faceUV else this function will fail.
'''
face_groups= {}
for me in mesh_list:
for f in me.faces:
if f.mode & TEXMODE:
image= f.image
if image:
try:
face_groups[image.name] # will fail if teh groups not added.
except:
try:
size= image.size
except:
B.Draw.PupMenu('Aborting: Image cold not be loaded|' + image.name)
return
face_groups[image.name]= faceGroup(mesh_list, image, size, PREF_IMAGE_MARGIN)
if not face_groups:
B.Draw.PupMenu('No Images found in mesh(es). Aborting!')
return
if len(face_groups)<2:
B.Draw.PupMenu('Only 1 image found|Select a mesh(es) using 2 or more images.')
return
'''
if PREF_SIZE_FROM_UV:
for fg in face_groups.itervalues():
fg.set_worldspace_scale()
'''
# RENDER THE FACES.
render_scn= B.Scene.New()
render_scn.makeCurrent()
render_context= render_scn.getRenderingContext()
render_context.setRenderPath('') # so we can ignore any existing path and save to the abs path.
PREF_IMAGE_PATH_EXPAND= B.sys.expandpath(PREF_IMAGE_PATH) + '.png'
# TEST THE FILE WRITING.
try:
# Can we write to this file???
f= open(PREF_IMAGE_PATH_EXPAND, 'w')
f.close()
except:
B.Draw.PupMenu('Error%t|Could not write to path|' + PREF_IMAGE_PATH_EXPAND)
return
render_context.imageSizeX(PREF_IMAGE_SIZE)
render_context.imageSizeY(PREF_IMAGE_SIZE)
render_context.enableOversampling(True)
render_context.setOversamplingLevel(16)
render_context.setRenderWinSize(100)
render_context.setImageType(Render.PNG)
render_context.enableExtensions(True)
render_context.enablePremultiply() # No alpha needed.
render_context.enableRGBAColor()
render_context.threads = 2
#Render.EnableDispView() # Broken??
# New Mesh and Object
render_mat= B.Material.New()
render_mat.mode |= \
B.Material.Modes.SHADELESS | \
B.Material.Modes.TEXFACE | \
B.Material.Modes.TEXFACE_ALPHA | \
B.Material.Modes.ZTRANSP
render_mat.setAlpha(0.0)
render_me= B.Mesh.New()
render_me.verts.extend([Vector(0,0,0)]) # Stupid, dummy vert, preverts errors. when assigning UV's/
render_ob= B.Object.New('Mesh')
render_ob.link(render_me)
render_scn.link(render_ob)
render_me.materials= [render_mat]
# New camera and object
render_cam_data= B.Camera.New('ortho')
render_cam_ob= B.Object.New('Camera')
render_cam_ob.link(render_cam_data)
render_scn.link(render_cam_ob)
render_scn.objects.camera = render_cam_ob
render_cam_data.type= 'ortho'
render_cam_data.scale= 1.0
# Position the camera
render_cam_ob.LocZ= 1.0
render_cam_ob.LocX= 0.5
render_cam_ob.LocY= 0.5
# List to send to to boxpack function.
boxes2Pack= [ fg.box_pack for fg in face_groups.itervalues()]
packWidth, packHeight = B.Geometry.BoxPack2D(boxes2Pack)
if PREF_KEEP_ASPECT:
packWidth= packHeight= max(packWidth, packHeight)
# packedLs is a list of [(anyUniqueID, left, bottom, width, height)...]
# Re assign the face groups boxes to the face_group.
for box in boxes2Pack:
face_groups[ box[4] ].box_pack= box # box[4] is the ID (image name)
# Add geometry to the mesh
for fg in face_groups.itervalues():
# Add verts clockwise from the bottom left.
_x= fg.box_pack[0] / packWidth
_y= fg.box_pack[1] / packHeight
_w= fg.box_pack[2] / packWidth
_h= fg.box_pack[3] / packHeight
render_me.verts.extend([\
Vector(_x, _y, 0),\
Vector(_x, _y +_h, 0),\
Vector(_x + _w, _y +_h, 0),\
Vector(_x + _w, _y, 0),\
])
render_me.faces.extend([\
render_me.verts[-1],\
render_me.verts[-2],\
render_me.verts[-3],\
render_me.verts[-4],\
])
target_face= render_me.faces[-1]
target_face.image= fg.image
target_face.mode |= TEXMODE
# Set the UV's, we need to flip them HOZ?
target_face.uv[0].x= target_face.uv[1].x= fg.xmax
target_face.uv[2].x= target_face.uv[3].x= fg.xmin
target_face.uv[0].y= target_face.uv[3].y= fg.ymin
target_face.uv[1].y= target_face.uv[2].y= fg.ymax
for uv in target_face.uv:
uv_rot= ((uv-fg.cent) * fg.rot_mat[1]) + fg.cent
uv.x= uv_rot.x
uv.y= uv_rot.y
render_context.render()
Render.CloseRenderWindow()
render_context.saveRenderedImage(PREF_IMAGE_PATH_EXPAND)
#if not B.sys.exists(PREF_IMAGE_PATH_EXPAND):
# raise 'Error!!!'
# NOW APPLY THE SAVED IMAGE TO THE FACES!
#print PREF_IMAGE_PATH_EXPAND
try:
target_image= B.Image.Load(PREF_IMAGE_PATH_EXPAND)
except:
B.Draw.PupMenu('Error: Could not render or load the image at path|' + PREF_IMAGE_PATH_EXPAND)
return
# Set to the 1 image.
for me in mesh_list:
for f in me.faces:
if f.mode & TEXMODE and f.image:
f.image= target_image
for fg in face_groups.itervalues():
fg.move2packed(packWidth, packHeight)
scn.makeCurrent()
render_me.verts= None # free a tiny amount of memory.
B.Scene.Unlink(render_scn)
target_image.makeCurrent()
def main():
scn= B.Scene.GetCurrent()
scn_objects = scn.objects
ob= scn_objects.active
if not ob or ob.type != 'Mesh':
B.Draw.PupMenu('Error, no active mesh object, aborting.')
return
# Create the variables.
# Filename without path or extension.
newpath= B.Get('filename').split('/')[-1].split('\\')[-1].replace('.blend', '')
PREF_IMAGE_PATH = B.Draw.Create('//%s_grp' % newpath)
PREF_IMAGE_SIZE = B.Draw.Create(1024)
PREF_IMAGE_MARGIN = B.Draw.Create(6)
PREF_KEEP_ASPECT = B.Draw.Create(0)
PREF_ALL_SEL_OBS = B.Draw.Create(0)
pup_block = [\
'Image Path: (no ext)',\
('', PREF_IMAGE_PATH, 3, 100, 'Path to new Image. "//" for curent blend dir.'),\
'Image Options',
('Pixel Size:', PREF_IMAGE_SIZE, 64, 4096, 'Image Width and Height.'),\
('Pixel Margin:', PREF_IMAGE_MARGIN, 0, 64, 'Use a margin to stop mipmapping artifacts.'),\
('Keep Aspect', PREF_KEEP_ASPECT, 'If disabled, will stretch the images to the bounds of the texture'),\
'Texture Source',\
('All Sel Objects', PREF_ALL_SEL_OBS, 'Combine all selected objects into 1 texture, otherwise active object only.'),\
]
if not B.Draw.PupBlock('Consolidate images...', pup_block):
return
PREF_IMAGE_PATH= PREF_IMAGE_PATH.val
PREF_IMAGE_SIZE= PREF_IMAGE_SIZE.val
PREF_IMAGE_MARGIN= float(PREF_IMAGE_MARGIN.val) # important this is a float otherwise division wont work properly
PREF_KEEP_ASPECT= PREF_KEEP_ASPECT.val
PREF_ALL_SEL_OBS= PREF_ALL_SEL_OBS.val
if PREF_ALL_SEL_OBS:
mesh_list= [ob.getData(mesh=1) for ob in scn_objects.context if ob.type=='Mesh']
# Make sure we have no doubles- dict by name, then get the values back.
for me in mesh_list: me.tag = False
mesh_list_new = []
for me in mesh_list:
if me.faceUV and me.tag==False:
me.tag = True
mesh_list_new.append(me)
# replace list with possible doubles
mesh_list = mesh_list_new
else:
mesh_list= [ob.getData(mesh=1)]
if not mesh_list[0].faceUV:
B.Draw.PupMenu('Error, active mesh has no images, Aborting!')
return
consolidate_mesh_images(mesh_list, scn, PREF_IMAGE_PATH, PREF_IMAGE_SIZE, PREF_KEEP_ASPECT, PREF_IMAGE_MARGIN)
B.Window.RedrawAll()
if __name__=='__main__':
main()

View File

@@ -1,269 +0,0 @@
#!BPY
"""
Name: 'Billboard Render on Active'
Blender: 242
Group: 'Image'
Tooltip: 'Selected objects and lamps to rendered faces on the act mesh'
"""
__author__= "Campbell Barton"
__url__= ["blender", "blenderartist"]
__version__= "1.0"
__bpydoc__= """\
Render Billboard Script
This can texture a simple billboard mesh from any number of selected objects.
Renders objects in the selection to quad faces on the active mesh.
Usage
* Light your model or enable the shadless flag so it is visible
* Make a low poly mesh out of quads with 90d corners. (this will be you billboard mesh)
* Select the model and any lamps that light it
* Select the billboard mesh so that it is active
* Run this script, Adjust settings such as image size or oversampling.
* Select a place to save the PNG image.
* Once the script has finished running return to the 3d view by pressing Shift+F5
* To see the newly applied textures change the drawtype to 'Textured Solid'
"""
# ***** BEGIN GPL LICENSE BLOCK *****
#
# Script copyright (C) Campbell J Barton 2006
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
import Blender
from Blender import Mesh, Material, Draw
import BPyMathutils
import bpy
import BPyRender
from Blender.Scene import Render
# reload(BPyRender)
# reload(BPyMathutils)
import os
Vector= Blender.Mathutils.Vector
def alpha_mat(image):
# returns a material useable for
mtl= bpy.data.materials.new()
mtl.mode |= (Material.Modes.SHADELESS | Material.Modes.ZTRANSP | Material.Modes.FULLOSA | Material.Modes.TEXFACE | Material.Modes.TEXFACE_ALPHA )
return mtl
# PupBlock Settings
GLOBALS= {}
PREF_RES= Draw.Create(512)
PREF_TILE_RES= Draw.Create(256)
PREF_AA = Draw.Create(1)
PREF_ALPHA= Draw.Create(1)
PREF_Z_OFFSET = Draw.Create(10.0)
PREF_IMG_PACK= Draw.Create(1)
def save_billboard(PREF_IMAGE_PATH):
Blender.Window.WaitCursor(1)
# remove png, add it later
PREF_IMAGE_PATH= PREF_IMAGE_PATH.replace('.png', '')
ob_sel= GLOBALS['ob_sel']
me_ob = GLOBALS['me_ob']
me_data = GLOBALS['me_data']
time= Blender.sys.time()
me_mat= me_ob.matrixWorld
# Render images for all faces
face_data= [] # Store faces, images etc
boxes2Pack= []
me_data.faceUV= True
for i, f in enumerate(me_data.faces):
no= f.no
# Offset the plane by the zoffset on the faces normal
plane= [v.co * me_mat for v in f]
# Horizontal stacking, make sure 0,1 and 2,3 are the longest
if\
(plane[0]-plane[1]).length + (plane[2]-plane[3]).length < \
(plane[1]-plane[2]).length + (plane[3]-plane[0]).length:
plane.append(plane.pop(0))
rot90= True
else:
rot90= False
no= Blender.Mathutils.QuadNormal(*plane)
plane= [v + no*PREF_Z_OFFSET.val for v in plane]
cent= (plane[0]+plane[1]+plane[2]+plane[3] ) /4.0
camera_matrix= BPyMathutils.plane2mat(plane)
tmp_path= '%s_%d' % (PREF_IMAGE_PATH, i)
img= BPyRender.imageFromObjectsOrtho(ob_sel, tmp_path, PREF_TILE_RES.val, PREF_TILE_RES.val, PREF_AA.val, PREF_ALPHA.val, camera_matrix)
img.reload()
#img.pack() # se we can keep overwriting the path
#img.filename= ""
if rot90:
f.uv=Vector(1,1), Vector(0,1), Vector(0,0), Vector(1,0)
else:
f.uv= Vector(0,1), Vector(0,0), Vector(1,0), Vector(1,1)
if not PREF_IMG_PACK.val:
f.mode |= Mesh.FaceModes.TEX
f.image = img
if PREF_ALPHA.val:
f.transp |= Mesh.FaceTranspModes.ALPHA
else:
w= ((plane[0]-plane[1]).length + (plane[2]-plane[3]).length)/2
h= ((plane[1]-plane[2]).length + (plane[3]-plane[0]).length)/2
face_data.append( (f, img) )
boxes2Pack.append( [0.0,0.0,h, w, i] )
if PREF_IMG_PACK.val:
# pack the quads into a square
packWidth, packHeight = Blender.Geometry.BoxPack2D(boxes2Pack)
render_obs= []
render_mat= alpha_mat(img)
# Add geometry to the mesh
for box in boxes2Pack:
i= box[4]
orig_f, img= face_data[i]
# New Mesh and Object
render_me= bpy.data.meshes.new()
render_ob= Blender.Object.New('Mesh')
render_me.materials= [render_mat]
render_ob.link(render_me)
render_obs.append(render_ob)
# Add verts clockwise from the bottom left.
_x= box[0] / packWidth
_y= box[1] / packHeight
_w= box[2] / packWidth
_h= box[3] / packHeight
render_me.verts.extend([\
Vector(_x, _y, 0),\
Vector(_x, _y +_h, 0),\
Vector(_x + _w, _y +_h, 0),\
Vector(_x + _w, _y, 0),\
])
render_me.faces.extend(list(render_me.verts))
render_me.faceUV= True
render_me.faces[0].uv = [Vector(0,0), Vector(0,1), Vector(1,1), Vector(1,0)]
render_me.faces[0].image = img
# Set the UV's, we need to flip them HOZ?
for uv in orig_f.uv:
uv.x = _x + (uv.x * _w)
uv.y = _y + (uv.y * _h)
target_image= BPyRender.imageFromObjectsOrtho(render_obs, PREF_IMAGE_PATH, PREF_RES.val, PREF_RES.val, PREF_AA.val, PREF_ALPHA.val, None)
target_image.reload() # incase your overwriting an existing image.
# Set to the 1 image.
for f in me_data.faces:
f.image= target_image
if PREF_ALPHA.val:
f.transp |= Mesh.FaceTranspModes.ALPHA
# Free the images data and remove
for data in face_data:
img= data[1]
os.remove(img.filename)
img.reload()
# Finish pack
me_data.update()
me_ob.makeDisplayList()
Blender.Window.WaitCursor(0)
print '%.2f secs taken' % (Blender.sys.time()-time)
def main():
scn= bpy.data.scenes.active
ob_sel= list(scn.objects.context)
PREF_KEEP_ASPECT= False
# Error Checking
if len(ob_sel) < 2:
Draw.PupMenu("Error%t|Select 2 mesh objects")
return
me_ob= scn.objects.active
if not me_ob:
Draw.PupMenu("Error%t|No active mesh selected.")
try:
ob_sel.remove(me_ob)
except:
pass
if me_ob.type != 'Mesh':
Draw.PupMenu("Error%t|Active Object must be a mesh to write billboard images too")
return
me_data= me_ob.getData(mesh=1)
for f in me_data.faces:
if len(f) != 4:
Draw.PupMenu("Error%t|Active mesh must have only quads")
return
# Get user input
block = [\
'Image Pixel Size',\
("Packed Size: ", PREF_RES, 128, 2048, "Pixel width and height to render the billboard to"),\
("Tile Size: ", PREF_TILE_RES, 64, 1024, "Pixel width and height for each tile to render to"),\
'Render Settings',\
("Pack Final", PREF_IMG_PACK , "Pack the image for each face into images into a single image"),\
("Oversampling", PREF_AA , "Higher quality woth extra sampling"),\
("Alpha Clipping", PREF_ALPHA , "Render empty areas as transparent"),\
("Cam ZOffset: ", PREF_Z_OFFSET, 0.1, 100, "Distance to place the camera away from the quad when rendering")\
]
if not Draw.PupBlock("Billboard Render", block):
return
# Set globals
GLOBALS['ob_sel'] = ob_sel
GLOBALS['me_ob'] = me_ob
GLOBALS['me_data'] = me_data
Blender.Window.FileSelector(save_billboard, 'SAVE BILLBOARD', Blender.sys.makename(ext='.png'))
# save_billboard('/tmp/test.png')
if __name__=='__main__':
main()

View File

@@ -1,158 +0,0 @@
#!BPY
"""
Name: 'Edit Externally'
Blender: 242a
Group: 'Image'
Tooltip: 'Open in an application for editing. (hold Shift to configure)'
"""
__author__ = "Campbell Barton"
__url__ = ["blender", "blenderartists.org"]
__version__ = "1.0"
__bpydoc__ = """\
This script opens the current image in an external application for editing.
Usage:
Choose an image for editing in the UV/Image view.
To configure the application to open the image with, hold Shift as you
click on this menu item.
For first time users try running the default application for your
operating system. If the application does not open you can type in
the full path. You can choose that the last entered application will
be saved as a default.
* Note, default commants for opening an image are "start" for win32
and "open" for macos. This will use the system default associated
application.
"""
# ***** BEGIN GPL LICENSE BLOCK *****
#
# Script copyright (C) Campbell J Barton 2006
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
import Blender
from Blender import Image, sys, Draw, Registry
try:
import subprocess
import sys as py_sys
platform = py_sys.platform
except:
Draw.PupMenu('Error: Recent version of Python not installed.')
subprocess=None
def os_run(appstring, filename):
'''
Run the app, take into account different python versions etc
looks like python 2.6 wants a list for
'''
# evil trick, temp replace spaces so we can allow spaces in filenames
# also allows multiple instances of %f
appstring = appstring.replace(' ', '\t')
appstring = appstring.replace('%f', filename)
appstring = appstring.split('\t')
print ' '.join(appstring)
try: # only python 2.6 wants a list?
p = subprocess.Popen(appstring)
except:
p = subprocess.Popen(' '.join(appstring))
def edit_extern(image=None):
if not image:
image = Image.GetCurrent()
if not image: # Image is None
Draw.PupMenu('ERROR: Please select active Image.')
return
if image.packed:
Draw.PupMenu('ERROR: Image is packed, unpack before editing.')
return
imageFileName = sys.expandpath( image.filename )
if not sys.exists(imageFileName):
Draw.PupMenu('ERROR: Image path does not exist.')
return
pupblock = [imageFileName.split('/')[-1].split('\\')[-1]]
new_text= False
try:
appstring = Registry.GetKey('ExternalImageEditor', True)
appstring = appstring['path']
# for ZanQdo if he removed the path from the textbox totaly. ;) - Cam
if not appstring or appstring.find('%f')==-1:
new_text= True
except:
new_text= True
if new_text:
pupblock.append('first time, set path.')
if platform == 'win32':
# Example of path to popular image editor... ;-)
# appstring = '"C:\\Program Files\\Adobe\\Photoshop CS\\photoshop.exe" "%f"'
# Have to add "cmd /c" to make sure we're using Windows shell.
appstring = 'cmd /c start "" /B "%f"'
elif platform == 'darwin':
appstring = 'open "%f"'
else:
appstring = 'gimp %f'
appstring_but = Draw.Create(appstring)
save_default_but = Draw.Create(0)
pupblock.append(('editor: ', appstring_but, 0, 99, 'Path to application, %f will be replaced with the image path.'))
pupblock.append(('Set Default', save_default_but, 'Store this path in the blender registry.'))
# Only configure if Shift is held,
if Blender.Window.GetKeyQualifiers() & Blender.Window.Qual.SHIFT:
if not Draw.PupBlock('External Image Editor...', pupblock):
return
appstring = appstring_but.val
save_default= save_default_but.val
if save_default:
Registry.SetKey('ExternalImageEditor', {'path':appstring}, True)
if appstring.find('%f') == -1:
Draw.PupMenu('ERROR: No filename specified! ("%f")')
return
# -------------------------------
os_run(appstring, imageFileName)
def main():
edit_extern()
if __name__ == '__main__' and subprocess:
main()

File diff suppressed because it is too large Load Diff

View File

@@ -1,961 +0,0 @@
#!BPY
"""
Name: 'Video Sequence (.edl)...'
Blender: 248
Group: 'Import'
Tooltip: 'Load a CMX formatted EDL into the sequencer'
"""
# ***** BEGIN GPL LICENSE BLOCK *****
#
# Copyright (C) 2009: Campbell Barton, ideasman42@gmail.com
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# --------------------------------------------------------------------------
class TimeCode(object):
'''
Simple timecode class
also supports conversion from other time strings used by EDL
'''
def __init__(self, data, fps):
self.fps= fps
if type(data)==str:
self.fromString(data)
frame = self.asFrame()
self.fromFrame(frame)
else:
self.fromFrame(data)
def fromString(self, text):
# hh:mm:ss:ff
# No dropframe support yet
if text.lower().endswith('mps'): # 5.2mps
return self.fromFrame( int( float(text[:-3]) * self.fps ) )
elif text.lower().endswith('s'): # 5.2s
return self.fromFrame( int( float(text[:-1]) * self.fps ) )
elif text.isdigit(): # 1234
return self.fromFrame( int(text) )
elif ':' in text: # hh:mm:ss:ff
text= text.replace(';', ':').replace(',', ':').replace('.', ':')
text= text.split(':')
self.hours= int(text[0])
self.minutes= int(text[1])
self.seconds= int(text[2])
self.frame= int(text[3])
return self
else:
print 'ERROR: could not convert this into timecode "%s"' % test
return self
def fromFrame(self, frame):
if frame < 0:
frame = -frame;
neg=True
else:
neg=False
fpm = 60 * self.fps
fph = 60 * fpm
if frame < fph:
self.hours= 0
else:
self.hours= int(frame/fph)
frame = frame % fph
if frame < fpm:
self.minutes= 0
else:
self.minutes= int(frame/fpm)
frame = frame % fpm
if frame < self.fps:
self.seconds= 0
else:
self.seconds= int(frame/self.fps)
frame = frame % self.fps
self.frame= frame
if neg:
self.frame = -self.frame
self.seconds = -self.seconds
self.minutes = -self.minutes
self.hours = -self.hours
return self
def asFrame(self):
abs_frame= self.frame
abs_frame += self.seconds * self.fps
abs_frame += self.minutes * 60 * self.fps
abs_frame += self.hours * 60 * 60 * self.fps
return abs_frame
def asString(self):
self.fromFrame(int(self))
return '%.2d:%.2d:%.2d:%.2d' % (self.hours, self.minutes, self.seconds, self.frame)
def __repr__(self):
return self.asString()
# Numeric stuff, may as well have this
def __neg__(self): return TimeCode(-int(self), self.fps)
def __int__(self): return self.asFrame()
def __sub__(self, other): return TimeCode(int(self)-int(other), self.fps)
def __add__(self, other): return TimeCode(int(self)+int(other), self.fps)
def __mul__(self, other): return TimeCode(int(self)*int(other), self.fps)
def __div__(self, other): return TimeCode(int(self)/int(other), self.fps)
def __abs__(self): return TimeCode(abs(int(self)), self.fps)
def __iadd__(self, other): return self.fromFrame(int(self)+int(other))
def __imul__(self, other): return self.fromFrame(int(self)*int(other))
def __idiv__(self, other): return self.fromFrame(int(self)/int(other))
# end timecode
'''Comments
Comments can appear at the beginning of the EDL file (header) or between the edit lines in the EDL. The first block of comments in the file is defined to be the header comments and they are associated with the EDL as a whole. Subsequent comments in the EDL file are associated with the first edit line that appears after them.
Edit Entries
<filename|tag> <EditMode> <TransitionType>[num] [duration] [srcIn] [srcOut] [recIn] [recOut]
* <filename|tag>: Filename or tag value. Filename can be for an MPEG file, Image file, or Image file template. Image file templates use the same pattern matching as for command line glob, and can be used to specify images to encode into MPEG. i.e. /usr/data/images/image*.jpg
* <EditMode>: 'V' | 'A' | 'VA' | 'B' | 'v' | 'a' | 'va' | 'b' which equals Video, Audio, Video_Audio edits (note B or b can be used in place of VA or va).
* <TransitonType>: 'C' | 'D' | 'E' | 'FI' | 'FO' | 'W' | 'c' | 'd' | 'e' | 'fi' | 'fo' | 'w'. which equals Cut, Dissolve, Effect, FadeIn, FadeOut, Wipe.
* [num]: if TransitionType = Wipe, then a wipe number must be given. At the moment only wipe 'W0' and 'W1' are supported.
* [duration]: if the TransitionType is not equal to Cut, then an effect duration must be given. Duration is in frames.
* [srcIn]: Src in. If no srcIn is given, then it defaults to the first frame of the video or the first frame in the image pattern. If srcIn isn't specified, then srcOut, recIn, recOut can't be specified.
* [srcOut]: Src out. If no srcOut is given, then it defaults to the last frame of the video - or last image in the image pattern. if srcOut isn't given, then recIn and recOut can't be specified.
* [recIn]: Rec in. If no recIn is given, then it is calculated based on its position in the EDL and the length of its input.
[recOut]: Rec out. If no recOut is given, then it is calculated based on its position in the EDL and the length of its input. first frame of the video.
For srcIn, srcOut, recIn, recOut, the values can be specified as either timecode, frame number, seconds, or mps seconds. i.e.
[tcode | fnum | sec | mps], where:
* tcode : SMPTE timecode in hh:mm:ss:ff
* fnum : frame number (the first decodable frame in the video is taken to be frame 0).
* sec : seconds with 's' suffix (e.g. 5.2s)
* mps : seconds with 'mps' suffix (e.g. 5.2mps). This corresponds to the 'seconds' value displayed by Windows MediaPlayer.
More notes,
Key
'''
enum= 0
TRANSITION_UNKNOWN= enum
TRANSITION_CUT= enum; enum+=1
TRANSITION_DISSOLVE= enum; enum+=1
TRANSITION_EFFECT= enum; enum+=1
TRANSITION_FADEIN= enum; enum+=1
TRANSITION_FADEOUT= enum; enum+=1
TRANSITION_WIPE= enum; enum+=1
TRANSITION_KEY= enum; enum+=1
TRANSITION_DICT={ \
'c':TRANSITION_CUT,
'd':TRANSITION_DISSOLVE,
'e':TRANSITION_EFFECT,
'fi':TRANSITION_FADEIN,
'fo':TRANSITION_FADEOUT,
'w':TRANSITION_WIPE,
'k':TRANSITION_KEY,
}
enum= 0
EDIT_UNKNOWN= 1<<enum; enum+=1
EDIT_VIDEO= 1<<enum; enum+=1
EDIT_AUDIO= 1<<enum; enum+=1
EDIT_AUDIO_STEREO= 1<<enum; enum+=1
EDIT_VIDEO_AUDIO= 1<<enum; enum+=1
EDIT_DICT= { \
'v':EDIT_VIDEO,
'a':EDIT_AUDIO,
'aa':EDIT_AUDIO_STEREO,
'va':EDIT_VIDEO_AUDIO,
'b':EDIT_VIDEO_AUDIO
}
enum= 0
WIPE_UNKNOWN= enum
WIPE_0= enum; enum+=1
WIPE_1= enum; enum+=1
enum= 0
KEY_UNKNOWN= enum
KEY_BG= enum; enum+=1 # K B
KEY_IN= enum; enum+=1 # This is assumed if no second type is set
KEY_OUT= enum; enum+=1 # K O
'''
Most sytems:
Non-dropframe: 1:00:00:00 - colon in last position
Dropframe: 1:00:00;00 - semicolon in last position
PAL/SECAM: 1:00:00:00 - colon in last position
SONY:
Non-dropframe: 1:00:00.00 - period in last position
Dropframe: 1:00:00,00 - comma in last position
PAL/SECAM: 1:00:00.00 - period in last position
'''
'''
t = abs(timecode('-124:-12:-43:-22', 25))
t /= 2
print t
'''
def editFlagsToText(flag):
items = []
for item, val in EDIT_DICT.items():
if val & flag:
items.append(item)
return '/'.join(items)
class EditDecision(object):
def __init__(self, text= None, fps= 25):
# print text
self.number = -1
self.reel = '' # Uniqie name for this 'file' but not filename, when BL signifies black
self.transition_duration= 0
self.edit_type= EDIT_UNKNOWN
self.transition_type= TRANSITION_UNKNOWN
self.wipe_type = WIPE_UNKNOWN
self.key_type = KEY_UNKNOWN
self.key_fade = -1 # true/false
self.srcIn = None # Where on the original field recording the event begins
self.srcOut = None # Where on the original field recording the event ends
self.recIn = None # Beginning of the original event in the edited program
self.recOut = None # End of the original event in the edited program
self.m2 = None # fps set by the m2 command
self.filename = ''
self.custom_data= [] # use for storing any data you want (blender strip for eg)
if text != None:
self.read(text, fps)
def __repr__(self):
txt= 'num: %d, ' % self.number
txt += 'reel: %s, ' % self.reel
txt += 'edit_type: '
txt += editFlagsToText(self.edit_type) + ', '
txt += 'trans_type: '
for item, val in TRANSITION_DICT.items():
if val == self.transition_type:
txt += item + ', '
break
txt += 'm2: '
if self.m2:
txt += '%g' % float(self.m2.fps)
txt += '\n\t'
txt += self.m2.data
else:
txt += 'nil'
txt += ', '
txt += 'recIn: ' + str(self.recIn) + ', '
txt += 'recOut: ' + str(self.recOut) + ', '
txt += 'srcIn: ' + str(self.srcIn) + ', '
txt += 'srcOut: ' + str(self.srcOut) + ', '
return txt
def read(self, line, fps):
line= line.split()
index= 0
self.number= int(line[index]); index+=1
self.reel= line[index].lower(); index+=1
# AA/V can be an edit type
self.edit_type= 0
for edit_type in line[index].lower().split('/'):
self.edit_type |= EDIT_DICT[edit_type];
index+=1
tx_name = ''.join([c for c in line[index].lower() if not c.isdigit()])
self.transition_type= TRANSITION_DICT[tx_name]; # advance the index later
if self.transition_type== TRANSITION_WIPE:
tx_num = ''.join([c for c in line[index].lower() if c.isdigit()])
if tx_num: tx_num = int(tx_num)
else: tx_num = 0
self.wipe_type= tx_num
elif self.transition_type== TRANSITION_KEY: # UNTESTED
val= line[index+1].lower()
if val == 'b':
self.key_type= KEY_BG
index+=1
elif val == 'o':
self.key_type= KEY_OUT
index+=1
else:
self.key_type= KEY_IN # if no args given
# there may be an (F) after, eg 'K B (F)'
# in the docs this should only be after K B but who knows, it may be after K O also?
val= line[index+1].lower()
if val == '(f)':
index+=1
self.key_fade = True
else:
self.key_fade = False
index+=1
if self.transition_type in (TRANSITION_DISSOLVE, TRANSITION_EFFECT, TRANSITION_FADEIN, TRANSITION_FADEOUT, TRANSITION_WIPE):
self.transition_duration= TimeCode(line[index], fps); index+=1
if index < len(line):
self.srcIn= TimeCode(line[index], fps); index+=1
if index < len(line):
self.srcOut= TimeCode(line[index], fps); index+=1
if index < len(line):
self.recIn= TimeCode(line[index], fps); index+=1
if index < len(line):
self.recOut= TimeCode(line[index], fps); index+=1
def renumber(self):
self.edits.sort( key=lambda e: int(e.recIn) )
for i, edit in enumerate(self.edits):
edit.number= i
def clean(self):
'''
Clean up double ups
'''
self.renumber()
# TODO
def asName(self):
cut_type = 'nil'
for k,v in TRANSITION_DICT.iteritems():
if v==self.transition_type:
cut_type = k
break
return '%d_%s_%s' % (self.number, self.reel, cut_type)
class M2(object):
def __init__(self):
self.reel = None
self.fps = None
self.time = None
self.data = None
self.index = -1
self.tot = -1
def read(self, line, fps):
# M2 TAPEC 050.5 00:08:11:08
words = line.split()
self.reel= words[1].lower()
self.fps= float(words[2])
self.time= TimeCode(words[3], fps)
self.data = line
class EditList(object):
def __init__(self):
self.edits= []
self.title= ''
def parse(self, filename, fps):
try:
file= open(filename, 'rU')
except:
return False
self.edits= []
edits_m2 = [] # edits with m2's
has_m2 = False
for line in file:
line= ' '.join(line.split())
if not line or line.startswith('*') or line.startswith('#'):
continue
elif line.startswith('TITLE:'):
self.title= ' '.join(line.split()[1:])
elif line.split()[0].lower() == 'm2':
has_m2 = True
m2 = M2()
m2.read(line, fps)
edits_m2.append( m2 )
elif not line.split()[0].isdigit():
print 'Ignoring:', line
else:
self.edits.append( EditDecision(line, fps) )
edits_m2.append( self.edits[-1] )
if has_m2:
# Group indexes
i = 0
for item in edits_m2:
if isinstance(item, M2):
item.index = i
i += 1
else:
# not an m2
i = 0
# Set total group indexes
for item in reversed(edits_m2):
if isinstance(item, M2):
if tot_m2 == -1:
tot_m2 = item.index + 1
item.tot = tot_m2
else:
# not an m2
tot_m2 = -1
for i, item in enumerate(edits_m2):
if isinstance(item, M2):
# make a list of all items that match the m2's reel name
edits_m2_tmp = [item_tmp for item_tmp in edits_m2 if (isinstance(item, M2) or item_tmp.reel == item.reel)]
# get the new index
i_tmp = edits_m2_tmp.index(item)
# Seek back to get the edit.
edit = edits_m2[i_tmp-item.tot]
# Note, docs say time should also match with edit start time
# but from final cut pro, this seems not to be the case
if not isinstance(edit, EditDecision):
print "ERROR!", 'M2 incorrect'
else:
edit.m2 = item
return True
def testOverlap(self, edit_test):
recIn= int(edit_test.recIn)
recOut= int(edit_test.recOut)
for edit in self.edits:
if edit is edit_test:
break
recIn_other= int(edit.recIn)
recOut_other= int(edit.recOut)
if recIn_other < recIn < recOut_other:
return True
if recIn_other < recOut < recOut_other:
return True
if recIn < recIn_other < recOut:
return True
if recIn < recOut_other < recOut:
return True
return False
def getReels(self):
reels = {}
for edit in self.edits:
reels.setdefault(edit.reel, []).append(edit)
return reels
# from DNA
SEQ_IMAGE= 0
SEQ_META= 1
SEQ_SCENE= 2
SEQ_MOVIE= 3
SEQ_RAM_SOUND= 4
SEQ_HD_SOUND= 5
SEQ_MOVIE_AND_HD_SOUND= 6
SEQ_EFFECT= 8
SEQ_CROSS= 8
SEQ_ADD= 9
SEQ_SUB= 10
SEQ_ALPHAOVER= 11
SEQ_ALPHAUNDER= 12
SEQ_GAMCROSS= 13
SEQ_MUL= 14
SEQ_OVERDROP= 15
SEQ_PLUGIN= 24
SEQ_WIPE= 25
SEQ_GLOW= 26
SEQ_TRANSFORM= 27
SEQ_COLOR= 28
SEQ_SPEED= 29
# Blender spesific stuff starts here
import bpy
import Blender
def scale_meta_speed(seq, mov, scale):
# Add an effect
speed= seq.new((SEQ_SPEED, mov,), 199, mov.channel+1)
speed.speedEffectFrameBlending = True
meta= seq.new([mov, speed], 199, mov.channel)
if scale >= 1.0:
mov.endStill = int(mov.length * (scale - 1.0))
else:
speed.speedEffectGlobalSpeed = 1.0/scale
meta.endOffset = mov.length - int(mov.length*scale)
speed.update()
meta.update()
return meta
def apply_dissolve_ipo(mov, blendin):
len_disp = float(mov.endDisp - mov.startDisp)
if len_disp <= 0.0:
print 'Error, strip is zero length'
return
mov.ipo= ipo= bpy.data.ipos.new("fade", "Sequence")
icu= ipo.addCurve('Fac')
icu.interpolation= Blender.IpoCurve.InterpTypes.LINEAR
icu.append((0, 0))
icu.append(((int(blendin)/len_disp) * 100, 1))
if mov.type not in (SEQ_HD_SOUND, SEQ_RAM_SOUND):
mov.blendMode = Blender.Scene.Sequence.BlendModes.ALPHAOVER
def replace_ext(path, ext):
return path[:path.rfind('.')+1] + ext
def load_edl(filename, reel_files, reel_offsets):
'''
reel_files - key:reel <--> reel:filename
'''
# For test file
# frame_offset = -769
sce= bpy.data.scenes.active
fps= sce.render.fps
elist= EditList()
if not elist.parse(filename, fps):
return 'Unable to parse "%s"' % filename
# elist.clean()
seq= sce.sequence
track= 0
edits = elist.edits[:]
# edits.sort(key = lambda edit: int(edit.recIn))
prev_edit = None
for edit in edits:
print edit
frame_offset = reel_offsets[edit.reel]
src_start= int(edit.srcIn) + frame_offset
src_end= int(edit.srcOut) + frame_offset
src_length= src_end-src_start
rec_start= int(edit.recIn) + 1
rec_end= int(edit.recOut) + 1
rec_length= rec_end-rec_start
# print src_length, rec_length, src_start
if edit.m2 != None: scale = fps/float(edit.m2.fps)
else: scale = 1.0
unedited_start= rec_start - src_start
offset_start = src_start - int(src_start*scale) # works for scaling up AND down
if edit.transition_type == TRANSITION_CUT and (not elist.testOverlap(edit)):
track = 1
strip= None
final_strips = []
if edit.reel.lower()=='bw':
strip= seq.new((0,0,0), rec_start, track+1)
strip.length= rec_length # for color its simple
final_strips.append(strip)
else:
path_full = reel_files[edit.reel]
path_fileonly= path_full.split('/')[-1].split('\\')[-1] # os.path.basename(full)
path_dironly= path_full[:-len(path_fileonly)] # os.path.dirname(full)
if edit.edit_type & EDIT_VIDEO: #and edit.transition_type == TRANSITION_CUT:
try:
strip= seq.new((path_fileonly, path_dironly, path_full, 'movie'), unedited_start + offset_start, track+1)
except:
return 'Invalid input for movie'
# Apply scaled rec in bounds
if scale != 1.0:
meta = scale_meta_speed(seq, strip, scale)
final_strip = meta
else:
final_strip = strip
final_strip.update()
final_strip.startOffset= rec_start - final_strip.startDisp
final_strip.endOffset= rec_end- final_strip.endDisp
final_strip.update()
final_strip.endOffset += (final_strip.endDisp - rec_end)
final_strip.update()
if edit.transition_duration:
if not prev_edit:
print "Error no previous strip"
else:
new_end = rec_start + int(edit.transition_duration)
for other in prev_edit.custom_data:
if other.type != SEQ_HD_SOUND and other.type != SEQ_RAM_SOUND:
other.endOffset += (other.endDisp - new_end)
other.update()
# Apply disolve
if edit.transition_type == TRANSITION_DISSOLVE:
apply_dissolve_ipo(final_strip, edit.transition_duration)
if edit.transition_type == TRANSITION_WIPE:
other_track = track + 2
for other in prev_edit.custom_data:
if other.type != SEQ_HD_SOUND and other.type != SEQ_RAM_SOUND:
strip_wipe= seq.new((SEQ_WIPE, other, final_strip), 1, other_track)
if edit.wipe_type == WIPE_0:
strip_wipe.wipeEffectAngle = 90
else:
strip_wipe.wipeEffectAngle = -90
other_track += 1
# strip.endOffset= strip.length - int(edit.srcOut)
#end_offset= (unedited_start+strip.length) - end
# print start, end, end_offset
#strip.endOffset = end_offset
# break
# print strip
final_strips.append(final_strip)
if edit.edit_type & (EDIT_AUDIO | EDIT_AUDIO_STEREO | EDIT_VIDEO_AUDIO):
if scale == 1.0: # TODO - scaled audio
try:
strip= seq.new((path_fileonly, path_dironly, path_full, 'audio_hd'), unedited_start + offset_start, track+6)
except:
# See if there is a wave file there
path_full_wav = replace_ext(path_full, 'wav')
path_fileonly_wav = replace_ext(path_fileonly, 'wav')
#try:
strip= seq.new((path_fileonly_wav, path_dironly, path_full_wav, 'audio_hd'), unedited_start + offset_start, track+6)
#except:
# return 'Invalid input for audio'
final_strip = strip
# Copied from above
final_strip.update()
final_strip.startOffset= rec_start - final_strip.startDisp
final_strip.endOffset= rec_end- final_strip.endDisp
final_strip.update()
final_strip.endOffset += (final_strip.endDisp - rec_end)
final_strip.update()
if edit.transition_type == TRANSITION_DISSOLVE:
apply_dissolve_ipo(final_strip, edit.transition_duration)
final_strips.append(final_strip)
# strip= seq.new((0.6, 0.6, 0.6), start, track+1)
if final_strips:
for strip in final_strips:
# strip.length= length
final_strip.name = edit.asName()
edit.custom_data[:]= final_strips
# track = not track
prev_edit = edit
track += 1
#break
def recursive_update(s):
s.update(1)
for s_kid in s:
recursive_update(s_kid)
for s in seq:
recursive_update(s)
return ''
#load_edl('/fe/edl/EP30CMXtrk1.edl') # /tmp/test.edl
#load_edl('/fe/edl/EP30CMXtrk2.edl') # /tmp/test.edl
#load_edl('/fe/edl/EP30CMXtrk3.edl') # /tmp/test.edl
#load_edl('/root/vid/rush/blender_edl.edl', ['/root/vid/rush/rushes3.avi',]) # /tmp/test.edl
# ---------------------- Blender UI part
from Blender import Draw, Window
import BPyWindow
if 0:
DEFAULT_FILE_EDL = '/root/vid/rush/blender_edl.edl'
DEFAULT_FILE_MEDIA = '/root/vid/rush/rushes3_wav.avi'
DEFAULT_FRAME_OFFSET = -769
else:
DEFAULT_FILE_EDL = ''
DEFAULT_FILE_MEDIA = ''
DEFAULT_FRAME_OFFSET = 0
B_EVENT_IMPORT = 1
B_EVENT_RELOAD = 2
B_EVENT_FILESEL_EDL = 3
B_EVENT_NOP = 4
B_EVENT_FILESEL = 100 # or greater
class ReelItemUI(object):
__slots__ = 'filename_but', 'offset_but', 'ui_text'
def __init__(self):
self.filename_but = Draw.Create(DEFAULT_FILE_MEDIA)
self.offset_but = Draw.Create(DEFAULT_FRAME_OFFSET)
self.ui_text = ''
REEL_UI = {} # reel:ui_string
#REEL_FILENAMES = {} # reel:filename
#REEL_OFFSETS = {} # reel:filename
PREF = {}
PREF['filename'] = Draw.Create(DEFAULT_FILE_EDL)
PREF['reel_act'] = ''
def edl_reload():
Window.WaitCursor(1)
filename = PREF['filename'].val
sce= bpy.data.scenes.active
fps= sce.render.fps
elist= EditList()
if filename:
if not elist.parse(filename, fps):
Draw.PupMenu('Error%t|Could not open the file "' + filename + '"')
reels = elist.getReels()
else:
reels = {}
REEL_UI.clear()
for reel_key, edits in reels.iteritems():
if reel_key == 'bw':
continue
flag = 0
for edit in edits:
flag |= edit.edit_type
reel_item = REEL_UI[reel_key] = ReelItemUI()
reel_item.ui_text = '%s (%s): ' % (reel_key, editFlagsToText(flag))
Window.WaitCursor(0)
def edl_set_path(filename):
PREF['filename'].val = filename
edl_reload()
Draw.Redraw()
def edl_set_path_reel(filename):
REEL_UI[PREF['reel_act']].filename_but.val = filename
Draw.Redraw()
def edl_reel_keys():
reel_keys = REEL_UI.keys()
if 'bw' in reel_keys:
reel_keys.remove('bw')
reel_keys.sort()
return reel_keys
def edl_draw():
MARGIN = 4
rect = BPyWindow.spaceRect()
but_width = int((rect[2]-MARGIN*2)/4.0) # 72
# Clamp
if but_width>100: but_width = 100
but_height = 17
x=MARGIN
y=rect[3]-but_height-MARGIN
xtmp = x
# ---------- ---------- ---------- ----------
Blender.Draw.BeginAlign()
PREF['filename'] = Draw.String('edl path: ', B_EVENT_RELOAD, xtmp, y, (but_width*3)-20, but_height, PREF['filename'].val, 256, 'EDL Path'); xtmp += (but_width*3)-20;
Draw.PushButton('..', B_EVENT_FILESEL_EDL, xtmp, y, 20, but_height, 'Select an EDL file'); xtmp += 20;
Blender.Draw.EndAlign()
Draw.PushButton('Reload', B_EVENT_RELOAD, xtmp + MARGIN, y, but_width - MARGIN, but_height, 'Read the ID Property settings from the active curve object'); xtmp += but_width;
y-=but_height + MARGIN
xtmp = x
# ---------- ---------- ---------- ----------
reel_keys = edl_reel_keys()
if reel_keys: text = 'Reel file list...'
elif PREF['filename'].val == '': text = 'No EDL loaded.'
else: text = 'No reels found!'
Draw.Label(text, xtmp + MARGIN, y, but_width*4, but_height); xtmp += but_width*4;
y-=but_height + MARGIN
xtmp = x
# ---------- ---------- ---------- ----------
for i, reel_key in enumerate(reel_keys):
reel_item = REEL_UI[reel_key]
Blender.Draw.BeginAlign()
REEL_UI[reel_key].filename_but = Draw.String(reel_item.ui_text, B_EVENT_NOP, xtmp, y, (but_width*3)-20, but_height, REEL_UI[reel_key].filename_but.val, 256, 'Select the reel path'); xtmp += (but_width*3)-20;
Draw.PushButton('..', B_EVENT_FILESEL + i, xtmp, y, 20, but_height, 'Media path to use for this reel'); xtmp += 20;
Blender.Draw.EndAlign()
reel_item.offset_but= Draw.Number('ofs:', B_EVENT_NOP, xtmp + MARGIN, y, but_width - MARGIN, but_height, reel_item.offset_but.val, -100000, 100000, 'Start offset in frames when applying timecode'); xtmp += but_width - MARGIN;
y-=but_height + MARGIN
xtmp = x
# ---------- ---------- ---------- ----------
Draw.PushButton('Import CMX-EDL Sequencer Strips', B_EVENT_IMPORT, xtmp + MARGIN, MARGIN, but_width*4 - MARGIN, but_height, 'Load the EDL file into the sequencer'); xtmp += but_width*4;
y-=but_height + MARGIN
xtmp = x
def edl_event(evt, val):
pass
def edl_bevent(evt):
if evt == B_EVENT_NOP:
pass
elif evt == B_EVENT_IMPORT:
'''
Load the file into blender with UI settings
'''
filename = PREF['filename'].val
reel_files = {}
reel_offsets = {}
for reel_key, reel_item in REEL_UI.iteritems():
reel_files[reel_key] = reel_item.filename_but.val
reel_offsets[reel_key] = reel_item.offset_but.val
error = load_edl(filename, reel_files, reel_offsets)
if error != '':
Draw.PupMenu('Error%t|' + error)
else:
Window.RedrawAll()
elif evt == B_EVENT_RELOAD:
edl_reload()
Draw.Redraw()
elif evt == B_EVENT_FILESEL_EDL:
filename = PREF['filename'].val
if not filename: filename = Blender.sys.join(Blender.sys.expandpath('//'), '*.edl')
Window.FileSelector(edl_set_path, 'Select EDL', filename)
elif evt >= B_EVENT_FILESEL:
reel_keys = edl_reel_keys()
reel_key = reel_keys[evt - B_EVENT_FILESEL]
filename = REEL_UI[reel_key].filename_but.val
if not filename: filename = Blender.sys.expandpath('//')
PREF['reel_act'] = reel_key # so file set path knows which one to set
Window.FileSelector(edl_set_path_reel, 'Reel Media', filename)
if __name__ == '__main__':
Draw.Register(edl_draw, edl_event, edl_bevent)
edl_reload()

View File

@@ -1,244 +0,0 @@
#!BPY
""" Registration info for Blender menus: <- these words are ignored
Name: 'Lightwave Motion (.mot)...'
Blender: 245
Group: 'Import'
Tip: 'Import Loc Rot Size chanels from a Lightwave .mot file'
"""
__author__ = "Daniel Salazar (ZanQdo)"
__url__ = ("blender", "blenderartists.org",
"e-mail: zanqdo@gmail.com")
__version__ = "16/04/08"
__bpydoc__ = """\
This script loads Lightwave motion files (.mot)
into the selected objects
Usage:
Run the script with one or more objects selected (any kind)
Be sure to set the framerate correctly
"""
# $Id$
# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
# Copyright (C) 2003, 2004: A Vanpoucke
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
import math as M
import Blender as B
import bpy
def FuncionPrincipal (Dir):
B.Window.WaitCursor(1)
ObjSelect = B.Object.GetSelected()
if not ObjSelect:
B.Draw.PupMenu('Select one or more objects, aborting.')
return
SC = B.Scene.GetCurrent()
SCR = SC.getRenderingContext()
FrameRate = float(SCR.framesPerSec())
# Creating new IPO
IPO = B.Ipo.New('Object', 'LW_Motion')
# Creating Curves in the IPO
LocX = IPO.addCurve("LocX")
LocX.setInterpolation("Bezier")
LocY = IPO.addCurve("LocY")
LocX.setInterpolation("Bezier")
LocZ = IPO.addCurve("LocZ")
LocX.setInterpolation("Bezier")
RotX = IPO.addCurve("RotX")
LocX.setInterpolation("Bezier")
RotY = IPO.addCurve("RotY")
LocX.setInterpolation("Bezier")
RotZ = IPO.addCurve("RotZ")
LocX.setInterpolation("Bezier")
ScaleX = IPO.addCurve("ScaleX")
LocX.setInterpolation("Bezier")
ScaleY = IPO.addCurve("ScaleY")
LocX.setInterpolation("Bezier")
ScaleZ = IPO.addCurve("ScaleZ")
LocX.setInterpolation("Bezier")
# Opening the mot file
File = open (Dir, 'rU')
# Init flags
CurChannel = -1
ScaleFlag = 0
# Main file reading cycle
for Line in File:
'''
# Number of channels in the file
if "NumChannels" in Line:
Line = Line.split (' ')
NumChannels = int(Line[1])
'''
# Current Channel Flag
if "Channel 0" in Line:
CurChannel = 0
elif "Channel 1" in Line:
CurChannel = 1
elif "Channel 2" in Line:
CurChannel = 2
elif "Channel 3" in Line:
CurChannel = 3
elif "Channel 4" in Line:
CurChannel = 4
elif "Channel 5" in Line:
CurChannel = 5
elif "Channel 6" in Line:
CurChannel = 6
elif "Channel 7" in Line:
CurChannel = 7
elif "Channel 8" in Line:
CurChannel = 8
# Getting the data and writing to IPOs
if CurChannel == 0:
if "Key" in Line:
Line = Line.split (' ')
ValCh_0 = float (Line [3])
TimeCh_0 = float (Line [4]) * FrameRate
LocX.addBezier ((TimeCh_0, ValCh_0))
if CurChannel == 1:
if "Key" in Line:
Line = Line.split (' ')
ValCh_1 = float (Line [3])
TimeCh_1 = float (Line [4]) * FrameRate
LocZ.addBezier ((TimeCh_1, ValCh_1))
if CurChannel == 2:
if "Key" in Line:
Line = Line.split (' ')
ValCh_2 = float (Line [3])
TimeCh_2 = float (Line [4]) * FrameRate
LocY.addBezier ((TimeCh_2, ValCh_2))
if CurChannel == 3:
if "Key" in Line:
Line = Line.split (' ')
ValCh_3 = M.degrees ( - float (Line [3]) ) / 10
TimeCh_3 = float (Line [4]) * FrameRate
RotZ.addBezier ((TimeCh_3, ValCh_3))
if CurChannel == 4:
if "Key" in Line:
Line = Line.split (' ')
ValCh_4 = M.degrees ( - float (Line [3]) ) / 10
TimeCh_4 = float (Line [4]) * FrameRate
RotX.addBezier ((TimeCh_4, ValCh_4))
if CurChannel == 5:
if "Key" in Line:
Line = Line.split (' ')
ValCh_5 = M.degrees ( - float (Line [3]) ) / 10
TimeCh_5 = float (Line [4]) * FrameRate
RotY.addBezier ((TimeCh_5, ValCh_5))
if CurChannel == 6:
if "Key" in Line:
Line = Line.split (' ')
ValCh_6 = float (Line [3])
TimeCh_6 = float (Line [4]) * FrameRate
ScaleX.addBezier ((TimeCh_6, ValCh_6))
elif ScaleFlag < 3:
ScaleFlag += 1
ScaleX.addBezier ((0, 1))
if CurChannel == 7:
if "Key" in Line:
Line = Line.split (' ')
ValCh_7 = float (Line [3])
TimeCh_7 = float (Line [4]) * FrameRate
ScaleZ.addBezier ((TimeCh_7, ValCh_7))
elif ScaleFlag < 3:
ScaleFlag += 1
ScaleZ.addBezier ((0, 1))
if CurChannel == 8:
if "Key" in Line:
Line = Line.split (' ')
ValCh_8 = float (Line [3])
TimeCh_8 = float (Line [4]) * FrameRate
ScaleY.addBezier ((TimeCh_8, ValCh_8))
elif ScaleFlag < 3:
ScaleFlag += 1
ScaleY.addBezier ((0, 1))
# Link the IPO to all selected objects
for ob in ObjSelect:
ob.setIpo(IPO)
File.close()
print '\nDone, the following motion file has been loaded:\n\n%s' % Dir
B.Window.WaitCursor(0)
def main():
B.Window.FileSelector(FuncionPrincipal, "Load IPO from .mot File", B.sys.makename(ext='.mot'))
if __name__=='__main__':
main()

View File

@@ -1,158 +0,0 @@
#!BPY
"""
Name: 'Load MDD to Mesh RVKs'
Blender: 242
Group: 'Import'
Tooltip: 'baked vertex animation to active mesh object.'
"""
__author__ = "Bill L.Nieuwendorp"
__bpydoc__ = """\
This script Imports Lightwaves MotionDesigner format.
The .mdd format has become quite a popular Pipeline format<br>
for moving animations from package to package.
"""
# mdd importer
#
# Warning if the vertex order or vertex count differs from the
# origonal model the mdd was Baked out from their will be Strange
# behavior
#
#
#vertex animation to ShapeKeys with ipo and gives the frame a value of 1.0
#A modifier to read mdd files would be Ideal but thats for another day :)
#
#Please send any fixes,updates,bugs to Slow67_at_Gmail.com
#Bill Niewuendorp
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
try:
from struct import unpack
except:
unpack = None
import Blender
from Blender import Mesh, Object, Scene
import BPyMessages
def mdd_import(filepath, ob, PREF_IPONAME, PREF_START_FRAME, PREF_JUMP):
print '\n\nimporting mdd "%s"' % filepath
Blender.Window.DrawProgressBar (0.0, "Importing mdd ...")
Blender.Window.EditMode(0)
Blender.Window.WaitCursor(1)
file = open(filepath, 'rb')
frames, points = unpack(">2i", file.read(8))
time = unpack((">%df" % frames), file.read(frames * 4))
print '\tpoints:%d frames:%d' % (points,frames)
scn = Scene.GetCurrent()
ctx = scn.getRenderingContext()
Blender.Set("curframe", PREF_START_FRAME)
me = ob.getData(mesh=1)
def UpdateMesh(me,fr):
for v in me.verts:
# 12 is the size of 3 floats
x,y,z= unpack('>3f', file.read(12))
v.co[:] = x,z,y
me.update()
Blender.Window.DrawProgressBar (0.4, "4 Importing mdd ...")
curfr = ctx.currentFrame()
print'\twriting mdd data...'
for i in xrange(frames):
Blender.Set("curframe", i+PREF_START_FRAME)
if len(me.verts) > 1 and (curfr >= PREF_START_FRAME) and (curfr <= PREF_START_FRAME+frames):
UpdateMesh(me, i)
ob.insertShapeKey()
Blender.Window.DrawProgressBar (0.5, "5 Importing mdd ...")
key= me.key
# Add the key of its not there
if not key:
me.insertKey(1, 'relative')
key= me.key
key.ipo = Blender.Ipo.New('Key', PREF_IPONAME)
ipo = key.ipo
# block = key.getBlocks() # not used.
all_keys = ipo.curveConsts
for i in xrange(PREF_JUMP+1, len(all_keys), PREF_JUMP):
curve = ipo.getCurve(i)
if curve == None:
curve = ipo.addCurve(all_keys[i])
curve.append((PREF_START_FRAME+i-1,1))
curve.append((PREF_START_FRAME+i- PREF_JUMP -1,0))
curve.append((PREF_START_FRAME+i+ PREF_JUMP-1,0))
curve.setInterpolation('Linear')
curve.recalc()
print 'done'
Blender.Window.WaitCursor(0)
Blender.Window.DrawProgressBar (1.0, '')
def mdd_import_ui(filepath):
if BPyMessages.Error_NoFile(filepath):
return
scn= Scene.GetCurrent()
ob_act= scn.objects.active
if ob_act == None or ob_act.type != 'Mesh':
BPyMessages.Error_NoMeshActive()
return
PREF_IPONAME = Blender.Draw.Create(filepath.split('/')[-1].split('\\')[-1].split('.')[0])
PREF_START_FRAME = Blender.Draw.Create(1)
PREF_JUMP = Blender.Draw.Create(1)
block = [\
("Ipo Name: ", PREF_IPONAME, 0, 30, "Ipo name for the new shape key"),\
("Start Frame: ", PREF_START_FRAME, 1, 3000, "Start frame for the animation"),\
("Key Skip: ", PREF_JUMP, 1, 100, "KeyReduction, Skip every Nth Frame")\
]
if not Blender.Draw.PupBlock("Import MDD", block):
return
orig_frame = Blender.Get('curframe')
mdd_import(filepath, ob_act, PREF_IPONAME.val, PREF_START_FRAME.val, PREF_JUMP.val)
Blender.Set('curframe', orig_frame)
if __name__ == '__main__':
if not unpack:
Draw.PupMenu('Error%t|This script requires a full python install')
Blender.Window.FileSelector(mdd_import_ui, 'IMPORT MDD', '*.mdd')

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More