blender/release/scripts/flt_toolbar.py

809 lines
22 KiB
Python

#!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)