213fac1bb3c9b0e5b4a0e5ac962224dbecff64f9
[blender.git] / release / scripts / flt_toolbar.py
1 #!BPY
2
3 """
4 Name: 'FLT Toolbar'
5 Blender: 240
6 Group: 'Misc'
7 Tooltip: 'Tools for working with FLT databases'
8 """
9
10 __author__ = "Geoffrey Bantle"
11 __version__ = "1.0 11/21/07"
12 __email__ = ('scripts', 'Author, ')
13 __url__ = ('blender', 'elysiun')
14
15 __bpydoc__ ="""\
16 This script provides tools for working with OpenFlight databases in Blender. OpenFlight is a
17 registered trademark of MultiGen-Paradigm, Inc.
18
19 Feature overview and more availible at:
20 http://wiki.blender.org/index.php/Scripts/Manual/FLTools
21 """
22
23 # --------------------------------------------------------------------------
24 # flt_palettemanager.py version 0.1 2005/04/08
25 # --------------------------------------------------------------------------
26 # ***** BEGIN GPL LICENSE BLOCK *****
27 #
28 # Copyright (C) 2007: Blender Foundation
29 #
30 # This program is free software; you can redistribute it and/or
31 # modify it under the terms of the GNU General Public License
32 # as published by the Free Software Foundation; either version 2
33 # of the License, or (at your option) any later version.
34 #
35 # This program is distributed in the hope that it will be useful,
36 # but WITHOUT ANY WARRANTY; without even the implied warranty of
37 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
38 # GNU General Public License for more details.
39 #
40 # You should have received a copy of the GNU General Public License
41 # along with this program; if not, write to the Free Software Foundation,
42 # Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
43 #
44 # ***** END GPL LICENCE BLOCK *****
45 # --------------------------------------------------------------------------
46
47 import Blender.Draw as Draw
48 from Blender.BGL import *
49 import Blender
50 import flt_properties
51 reload(flt_properties)
52 from flt_properties import *
53
54 xrefprefix = ""
55 xrefstack = list()
56 vofsstack = list()
57 vquatstack = list()
58 prop_w = 256
59 prop_h = 256
60
61
62 #event codes
63 evcode = {
64         "XREF_MAKE" : 100,
65         "XREF_EDIT" : 101,
66         "XREF_FILE" : 102,
67         "XREF_PICK" : 103,
68         "XREF_SELECT" : 104,
69         "XREF_POP" : 105,
70         "XREF_PREFIX" : 106,
71         "FACE_NAME" : 200,
72         "FACE_MAKESUB" : 201,
73         "FACE_KILLSUB" : 202,
74         "FACE_SELSUB" : 203,
75         "SCENE_UPDATE" : 303,
76         "IDPROP_COPY" : 501,
77         "IDPROP_KILL" : 502,
78         "CLIGHT_MAKE" : 700,
79         "DFROMACT" : 701
80 }
81
82 XREF_PREFIX = None
83 XREF_MAKE = None
84 XREF_EDIT = None
85 XREF_SELECT = None
86 XREF_POP = None
87 FACE_MAKESUB = None
88 FACE_SELSUB = None
89 FACE_KILLSUB = None
90 IDPROP_KILL = None
91 IDPROP_COPY = None
92 SCENE_UPDATE = None
93 CLIGHT_MAKE = None
94 DFROMACT = None
95
96 def update_state():
97         state = dict()
98         state["activeScene"] = Blender.Scene.getCurrent()
99         state["activeObject"] = state["activeScene"].getActiveObject()
100         if state["activeObject"] and not state["activeObject"].sel:
101                 state["activeObject"] = None
102         state["activeMesh"] = None
103         if state["activeObject"] and state["activeObject"].type == 'Mesh':
104                 state["activeMesh"] = state["activeObject"].getData(mesh=True)
105         
106         state["activeFace"] = None
107         if state["activeMesh"]:
108                 if state["activeMesh"].faceUV and state["activeMesh"].activeFace != None:
109                         state["activeFace"] = state["activeMesh"].faces[state["activeMesh"].activeFace]
110                 
111         #update editmode
112         state["editmode"]       = Blender.Window.EditMode()
113
114         return state
115 def pack_face_index(index, intensity):
116         return ((127*intensity)+(128*index))
117 def unpack_face_index(face_index):
118         index = face_index / 128
119         intensity = float(face_index - 128.0 * index) / 127.0
120         return(index,intensity)
121         
122 def idprops_append(object, typecode, props):
123         object.properties["FLT"] = dict()
124         object.properties["FLT"]['type'] = typecode 
125         for prop in props:
126                 object.properties["FLT"][prop] = props[prop]
127         object.properties["FLT"]['3t8!id'] = object.name
128
129 def idprops_kill(object):
130         state = update_state()
131         if object and object.properties.has_key('FLT'):
132                 object.properties.pop('FLT')
133
134 def idprops_copy(source):
135         state = update_state()
136         if source.properties.has_key('FLT'):
137                 for object in state["activeScene"].objects:
138                         if object.sel and object != source and (state["activeScene"].Layers & object.Layers):
139                                 idprops_kill(object)
140                                 object.properties['FLT'] = dict()
141                                 for key in source.properties['FLT']:
142                                         object.properties['FLT'][key] = source.properties['FLT'][key]
143
144 def update_all():
145         state = update_state()
146         #update the baked FLT colors for all meshes.
147         for object in state["activeScene"].objects:
148                 if object.type == "Mesh":
149                         mesh = object.getData(mesh=True)
150                         if 'FLT_COL' in mesh.faces.properties:
151                                 mesh.activeColorLayer = "FLT_Fcol"
152                                 for face in mesh.faces:
153                                         (index,intensity) = unpack_face_index(face.getProperty('FLT_COL'))
154                                         color = struct.unpack('>BBBB',struct.pack('>I',state["colors"][index]))
155                                         #update the vertex colors for this face
156                                         for col in face.col:
157                                                 col.r = int(color[0] * intensity)
158                                                 col.g = int(color[1] * intensity)
159                                                 col.b = int(color[2] * intensity)
160                                                 col.a = 255
161
162
163 #Change this to find the deep parent
164 def xref_create():
165         global xrefprefix
166         global xrefstack
167         global vofsstack
168         global vquatstack
169         global prop_w
170         global prop_h
171         
172         state = update_state()
173         
174         def findchildren(object):
175                 children = list()
176                 for candidate in state["activeScene"].objects:
177                         if candidate.parent == object:
178                                 children.append(candidate)
179                 retlist = list(children)
180                 for child in children:
181                         retlist = retlist + findchildren(child)
182                 return retlist
183                 
184         actObject = state["activeObject"]
185         if actObject and xrefprefix:
186                 scenenames = list()
187                 for scene in Blender.Scene.Get():
188                         scenenames.append(scene.name)
189
190                 if xrefprefix in scenenames:
191                         #build a unique name for the xref...
192                         suffix = 1
193                         found = False
194                         while not found:
195                                 candidate = xrefprefix + str(suffix)
196                                 if not candidate in scenenames:
197                                         xrefname = candidate
198                                         found = True
199                                 suffix+=1
200                 else:
201                         xrefname = xrefprefix
202                 #create our XRef node
203                 xnode = state["activeScene"].objects.new('Empty')
204                 xnode.name = 'X:' + xrefname
205                 xnode.properties['FLT'] = dict()
206                 for prop in FLTXRef:
207                         xnode.properties['FLT'][prop] = FLTXRef[prop]
208                 xnode.properties['FLT']['3t200!filename'] = xrefname + '.flt'
209                 xnode.properties['FLT']['type'] = 63
210                 xnode.enableDupGroup = True
211                 xnode.DupGroup = Blender.Group.New(xrefname) #this is dangerous... be careful!
212
213                 #copy rot and loc of actObject
214                 xnode.setLocation(actObject.getLocation())
215                 xnode.setEuler(actObject.getEuler())         
216                 
217                 #build the new scene
218                 xrefscene = Blender.Scene.New(xrefname)
219                 xrefscene.properties['FLT'] = dict()
220                 xrefscene.properties['FLT']['Filename'] = xrefname
221                 xrefscene.properties['FLT']['Main'] = 0
222
223                 #find the children of actObject so that we can add them to the group
224                 linkobjects = findchildren(actObject)
225                 linkobjects.append(actObject)
226                 for object in linkobjects:
227                         xrefscene.objects.link(object)
228                         state["activeScene"].objects.unlink(object)
229                         xnode.DupGroup.objects.link(object)
230                 #clear rotation of actObject and location
231                 actObject.setLocation(0.0,0.0,0.0)
232                 actObject.setEuler(0.0,0.0,0.0)
233
234                 xrefscene.update(1)
235                 state["activeScene"].update(1)
236
237 def xref_select():
238         state = update_state()
239         candidates = list()
240         scenelist = [scene.name for scene in Blender.Scene.Get()]
241         for object in state["activeScene"].objects:
242                 if object.type == 'Empty' and object.enableDupGroup == True and object.DupGroup:
243                         candidates.append(object)
244                 
245         for object in candidates:
246                 if object.DupGroup.name in scenelist:
247                         object.sel = 1
248
249 def xref_edit():
250         global xrefprefix
251         global xrefstack
252         global vofsstack
253         global vquatstack
254         global prop_w
255         global prop_h
256         
257         state = update_state()
258
259         actObject = state["activeObject"]
260
261         if actObject and actObject.type == 'Empty' and actObject.DupGroup:
262 #               if actObject.properties.has_key('FLT') and actObject.properties['FLT']['type'] == 63:
263                 for FLTscene in Blender.Scene.Get():
264                         if FLTscene.properties.has_key('FLT') and FLTscene.name == actObject.DupGroup.name:
265                                 actObject.sel = 0
266                                 xrefstack.append(state["activeScene"])
267                                 vofsstack.append(Blender.Window.GetViewOffset())
268                                 vquatstack.append(Blender.Window.GetViewQuat())
269                                 FLTscene.makeCurrent()
270                                 Blender.Window.SetViewOffset(0.0,0.0,0.0)
271
272 def xref_finish():
273         global xrefprefix
274         global xrefstack
275         global vofsstack
276         global vquatstack
277         global prop_w
278         global prop_h
279         
280         state = update_state() 
281         if xrefstack:
282                 scene = xrefstack.pop()
283                 Blender.Window.SetViewQuat(vquatstack.pop())
284                 Blender.Window.SetViewOffset(vofsstack.pop())
285                 scene.makeCurrent()
286                 
287
288 def sortSub(a,b):
289         aindex = a.getProperty("FLT_ORIGINDEX")
290         bindex = b.getProperty("FLT_ORIGINDEX")
291         
292         if aindex > bindex:
293                 return 1
294         elif aindex < bindex:
295                 return -1
296         return 0
297
298 def subface_make():
299         global xrefprefix
300         global xrefstack
301         global vofsstack
302         global vquatstack
303         global prop_w
304         global prop_h
305         
306         editmode = 0
307         if Blender.Window.EditMode():
308                 Blender.Window.EditMode(0)
309                 editmode = 1
310
311         state = update_state()
312         
313         actmesh = state["activeMesh"]
314         activeFace = state["activeFace"]
315         if actmesh:
316                 if not "FLT_ORIGINDEX" in actmesh.faces.properties:
317                         actmesh.faces.addPropertyLayer("FLT_ORIGINDEX",Blender.Mesh.PropertyTypes["INT"])
318                         for i, face in enumerate(actmesh.faces):
319                                 face.setProperty("FLT_ORIGINDEX",i)
320                 if not "FLT_SFLEVEL" in actmesh.faces.properties:
321                         actmesh.faces.addPropertyLayer("FLT_SFLEVEL",Blender.Mesh.PropertyTypes["INT"])
322                         
323                 #attach the subfaces to the active face. Note, this doesnt really work 100 percent properly yet, just enough for one level!
324                 if activeFace:
325                         #steps:
326                         #remove actface and selected faces from the facelist
327                         #quicksort facelist
328                         #append actface and subfaces to end of facelist.
329                         #generate new indices
330                         facelist = list()
331                         sublist = list()
332                         for face in actmesh.faces:
333                                 facelist.append(face)
334                         for face in facelist:   
335                                 if face == activeFace:
336                                         face.setProperty("FLT_SFLEVEL",0)
337                                         sublist.insert(0,face)
338                                 elif face.sel:
339                                         face.setProperty("FLT_SFLEVEL",1)
340                                         sublist.append(face)
341                         for face in sublist:
342                                 facelist.remove(face)
343                         facelist.sort(sortSub)
344                         for face in sublist:
345                                 facelist.append(face)
346                         for i, face in enumerate(facelist):
347                                 face.setProperty("FLT_ORIGINDEX",i)
348                 else:
349                         pass
350         
351         if editmode:
352                 Blender.Window.EditMode(1)
353
354 def subface_kill():
355         global xrefprefix
356         global xrefstack
357         global vofsstack
358         global vquatstack
359         global prop_w
360         global prop_h
361         
362         editmode = 0
363         if Blender.Window.EditMode():
364                 Blender.Window.EditMode(0)
365                 editmode = 1
366         state = update_state()
367         
368         actmesh = state["activeMesh"]
369         if actmesh:
370                 if "FLT_ORIGINDEX" in actmesh.faces.properties and "FLT_SFLEVEL" in actmesh.faces.properties:
371                         for i,face in enumerate(actmesh.faces):
372                                 face.setProperty("FLT_ORIGINDEX",i)
373                                 face.setProperty("FLT_SFLEVEL",0)
374         if editmode:
375                 Blender.Window.EditMode(1)
376
377 def subface_select():
378         global xrefprefix
379         global xrefstack
380         global vofsstack
381         global vquatstack
382         global prop_w
383         global prop_h
384         
385         editmode = 0
386         if Blender.Window.EditMode():
387                 Blender.Window.EditMode(0)
388                 editmode = 1
389         state = update_state()
390         
391         actmesh = state["activeMesh"]
392         activeFace = state["activeFace"]
393         if actmesh and activeFace:
394                 if "FLT_ORIGINDEX" in actmesh.faces.properties and "FLT_SFLEVEL" in actmesh.faces.properties:
395                         facelist = list()
396                         actIndex = None
397                         sublevel = None
398                         for face in actmesh.faces:
399                                 facelist.append(face)
400                                 facelist.sort(sortSub)
401                         for i, face in enumerate(facelist):
402                                 if face == activeFace:
403                                         actIndex = i
404                                         sublevel = face.getProperty("FLT_SFLEVEL")+1
405                                         break
406                         leftover = facelist[actIndex+1:]
407                         for face in leftover:
408                                 if face.getProperty("FLT_SFLEVEL") == sublevel:
409                                         face.sel = 1
410                                 else:
411                                         break
412         if editmode:
413                 Blender.Window.EditMode(1)
414
415 def select_by_typecode(typecode):
416         global xrefprefix
417         global xrefstack
418         global vofsstack
419         global vquatstack
420         global prop_w
421         global prop_h
422         
423         state = update_state()
424         
425         for object in state["activeScene"].objects:
426                 if object.properties.has_key('FLT') and object.properties['FLT']['type'] == typecode and state["activeScene"].Layers & object.Layers:
427                                 object.select(1)
428 def clight_make():
429         state = update_state()
430         actmesh = state["activeMesh"]
431         actobj = state["activeObject"]
432         
433         if actobj and actmesh:
434                 actobj.properties['FLT'] = dict()
435                 actobj.properties['FLT']['type'] = 111
436                 for prop in FLTInlineLP:
437                         actobj.properties['FLT'][prop] = FLTInlineLP[prop]
438         
439                 actmesh.verts.addPropertyLayer("FLT_VCOL", Blender.Mesh.PropertyTypes["INT"])
440                 for v in actmesh.verts:
441                         v.setProperty("FLT_VCOL", 83815)
442                         
443 def dfromact():
444         state = update_state()
445         actobj = state["activeObject"]
446         actscene = state["activeScene"]
447         dof = None
448         
449         for object in actscene.objects.context:
450                 if object.sel and (object != actobj):
451                         if not dof:
452                                 dof = object
453                         else:
454                                 return 
455         
456         if 'FLT' not in dof.properties:
457                 dof.properties['FLT'] = dict()  
458         
459         #Warning! assumes 1 BU == 10 meters.
460         #do origin
461         dof.properties['FLT']['5d!ORIGX'] = actobj.getLocation('worldspace')[0]*10.0
462         dof.properties['FLT']['6d!ORIGY'] = actobj.getLocation('worldspace')[1]*10.0
463         dof.properties['FLT']['7d!ORIGZ'] = actobj.getLocation('worldspace')[2]*10.0
464         #do X axis
465         x = Blender.Mathutils.Vector(1.0,0.0,0.0)
466         x = x * actobj.getMatrix('worldspace')
467         x = x * 10.0
468         dof.properties['FLT']['8d!XAXIS-X'] = x[0]
469         dof.properties['FLT']['9d!XAXIS-Y'] = x[1]
470         dof.properties['FLT']['10d!XAXIS-Z'] = x[2]
471         #do X/Y plane
472         x = Blender.Mathutils.Vector(1.0,1.0,0.0)
473         x.normalize()
474         x = x * actobj.getMatrix('worldspace')
475         x = x * 10.0
476         dof.properties['FLT']['11d!XYPLANE-X'] = x[0]
477         dof.properties['FLT']['12d!XYPLANE-Y'] = x[1]
478         dof.properties['FLT']['13d!XZPLANE-Z'] = x[2]
479         
480         
481         
482         
483         
484 def event(evt,val):
485         if evt == Draw.ESCKEY:
486                 Draw.Exit()
487                 
488 def but_event(evt):
489         global xrefprefix
490         global xrefstack
491         global vofsstack
492         global vquatstack
493         global prop_w
494         global prop_h
495         global evcode
496         
497         state = update_state()
498         
499         #do Xref buttons
500         if evt == evcode["XREF_PREFIX"]:
501                 xrefprefix = XREF_PREFIX.val
502         if evt == evcode["XREF_EDIT"]:
503                 xref_edit()
504         if evt == evcode["XREF_SELECT"]:
505                 xref_select()
506         if evt == evcode["XREF_MAKE"]:
507                 xref_create()
508         #do scene buttons                               
509         if evt == evcode["SCENE_UPDATE"]:
510                 update_all()
511         #do face buttons
512         if evt == evcode["FACE_MAKESUB"]:
513                 subface_make()
514         if evt== evcode["FACE_KILLSUB"]:
515                 subface_kill()
516         if evt== evcode["FACE_SELSUB"]:
517                 subface_select()
518         #common buttons
519         if evt == evcode["IDPROP_KILL"]:
520                 if state["activeObject"]:
521                         idprops_kill(state["activeObject"])
522         if evt == evcode["IDPROP_COPY"]:
523                 if state["activeObject"]:
524                         idprops_copy(state["activeObject"])
525         if evt == evcode["XREF_POP"]:
526                 xref_finish()
527         if evt == evcode["CLIGHT_MAKE"]:
528                 clight_make()
529         if evt == evcode["DFROMACT"]:
530                 dfromact()
531         Draw.Redraw(1)
532         Blender.Window.RedrawAll()
533
534
535 def box(x,y,w,h,c,mode):
536         glColor3f(c[0],c[1],c[2])
537         if mode == "outline":
538                 glBegin(GL_LINE_LOOP)
539         else:
540                 glBegin(GL_POLYGON)
541         glVertex2i(x,y)
542         glVertex2i(x+w,y)
543         glVertex2i(x+w,y+h)
544         glVertex2i(x,y+h)
545         glEnd()
546
547 def draw_postcommon(x,y,finaly):
548         global sheetlabel
549         global xrefprefix
550         global xrefstack
551         global vofsstack
552         global vquatstack
553         global prop_w
554         global prop_h
555         global evcode
556         
557         state = update_state()
558         
559         width = prop_w
560         height = prop_h
561         
562         #draw the header
563         glColor3f(0.15,0.15,0.15)
564         glBegin(GL_POLYGON)
565         glVertex2i(x-1,y)
566         glVertex2i(x+width+1,y)
567         glVertex2i(x+width+1,y-25)
568         glVertex2i(x-1,y-25)
569         glEnd()
570         glColor3f(1,1,1)
571         glRasterPos2i(x,y-20)
572         sheetlabel = Blender.Draw.Text("FLT Tools Panel")
573         #draw the box outline
574         glColor3f(0,0,0)
575         glBegin(GL_LINE_LOOP)
576         glVertex2i(x-1,y)
577         glVertex2i(x+1+width,y)
578         glVertex2i(x+1+width,finaly-1)
579         glVertex2i(x-1,finaly-1)
580         glEnd()
581         return finaly
582
583
584 def draw_propsheet(x,y):
585         global XREF_PREFIX
586         global XREF_MAKE
587         global XREF_EDIT
588         global XREF_SELECT
589         global XREF_POP
590         global FACE_MAKESUB
591         global FACE_SELSUB
592         global FACE_KILLSUB
593         global IDPROP_KILL
594         global IDPROP_COPY
595         global SCENE_UPDATE
596         global CLIGHT_MAKE
597         global xrefprefix
598         global xrefstack
599         global vofsstack
600         global vquatstack
601         global prop_w
602         global prop_h
603         global evcode
604         
605         state = update_state()
606
607         width = prop_w
608         height = prop_h
609         origx = x
610         origy = y
611         
612          #draw Xref tools
613         y = y-20
614         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")
615         y = y-20
616         XREF_MAKE = Blender.Draw.PushButton("Make XRef",evcode["XREF_MAKE"],x,y,width,20,"Make External Reference")
617         y = y-20
618         XREF_EDIT = Blender.Draw.PushButton("Edit XRef",evcode["XREF_EDIT"],x,y,width,20,"Edit External Reference")
619         y = y-20
620         XREF_SELECT = Blender.Draw.PushButton("Select XRefs",evcode["XREF_SELECT"],x,y,width,20,"Select External References")
621         y = y - 20
622         XREF_POP = Blender.Draw.PushButton("Return to previous scene",evcode["XREF_POP"],x,y,width,20,"Go up one level in xref hierarchy")
623
624         #Draw facetools
625         y = y-20
626         FACE_MAKESUB = Blender.Draw.PushButton("Make Subfaces",evcode["FACE_MAKESUB"],x,y,width,20,"Make subfaces")
627         y = y-20
628         FACE_SELSUB = Blender.Draw.PushButton("Select Subfaces",evcode["FACE_SELSUB"],x,y,width,20,"Select subfaces")
629         y = y-20
630         FACE_KILLSUB = Blender.Draw.PushButton("Kill Subfaces",evcode["FACE_KILLSUB"],x,y,width,20,"Kill subfaces")
631
632         #Draw ID Property tools
633         y = y - 20
634         IDPROP_KILL = Blender.Draw.PushButton("Delete ID props",evcode["IDPROP_KILL"],x,y,width,20,"Delete ID props")
635         y = y - 20
636         IDPROP_COPY = Blender.Draw.PushButton("Copy to selected",evcode["IDPROP_COPY"],x,y,width,20, "Copy from active to all selected")
637         
638         y= y - 20
639         CLIGHT_MAKE = Blender.Draw.PushButton("Make Light Point", evcode["CLIGHT_MAKE"],x,y,width,20,"Create inline light points from current mesh")
640         #General tools
641         y = y-20
642         SCENE_UPDATE = Blender.Draw.PushButton("Update All",evcode["SCENE_UPDATE"],x,y,width,20,"Update all vertex colors")
643         
644         y=y-20
645         DFROMACT = Blender.Draw.PushButton("Dof from Active", evcode["DFROMACT"],x,y,width,20,"Get Dof origin from active object")
646         draw_postcommon(origx, origy,y)
647                 
648 def gui():
649         #draw the propsheet/toolbox.
650         psheety = 280
651         #psheetx = psheety + 10
652         draw_propsheet(0,psheety)
653 Draw.Register(gui,event,but_event)
654