Merge from trunk: 15912:16031
[blender.git] / release / scripts / flt_palettemanager.py
1 #!BPY
2
3 """
4 Name: 'FLT Palette Manager'
5 Blender: 240
6 Group: 'Misc'
7 Tooltip: 'Manage FLT colors'
8 """
9
10 __author__ = "Geoffrey Bantle"
11 __version__ = "1.0 11/21/2007"
12 __email__ = ('scripts', 'Author, ')
13 __url__ = ('blender', 'blenderartists.org')
14
15 __bpydoc__ ="""\
16
17 This script manages colors in OpenFlight databases. OpenFlight is a
18 registered trademark of MultiGen-Paradigm, Inc.
19
20 Todo:
21 -Figure out whats causing the PC speaker to beep when initializing...
22
23 Feature overview and more availible at:
24 http://wiki.blender.org/index.php/Scripts/Manual/FLTools
25 """
26
27 # --------------------------------------------------------------------------
28 # flt_palettemanager.py version 1.0 2005/04/08
29 # --------------------------------------------------------------------------
30 # ***** BEGIN GPL LICENSE BLOCK *****
31 #
32 # Copyright (C) 2007: Blender Foundation
33 #
34 # This program is free software; you can redistribute it and/or
35 # modify it under the terms of the GNU General Public License
36 # as published by the Free Software Foundation; either version 2
37 # of the License, or (at your option) any later version.
38 #
39 # This program is distributed in the hope that it will be useful,
40 # but WITHOUT ANY WARRANTY; without even the implied warranty of
41 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
42 # GNU General Public License for more details.
43 #
44 # You should have received a copy of the GNU General Public License
45 # along with this program; if not, write to the Free Software Foundation,
46 # Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
47 #
48 # ***** END GPL LICENCE BLOCK *****
49 # --------------------------------------------------------------------------
50
51 import Blender.Draw as Draw
52 from Blender.BGL import *
53 import Blender
54 import flt_properties
55 import flt_defaultp as defaultp
56 from flt_properties import *
57
58 def RGBtoHSV( r, g, b):
59         minc = min( r, g, b )
60         maxc = max( r, g, b )
61         v = maxc                                
62
63         delta = maxc - minc
64
65         if( max != 0 ):
66                 s = delta / maxc                
67         else:
68                 s = 0
69                 h = -1
70                 return (h,s,v)
71
72         if( r == maxc ):
73                 h = ( g - b ) / delta           
74         elif( g == maxc ):
75                 h = 2 + ( b - r ) / delta
76         else:
77                 h = 4 + ( r - g ) / delta
78
79         h *= 60
80         if( h < 0 ):
81                 h += 360
82
83         return(h,s,v)
84
85 def HSVtoRGB(h,s,v):
86
87         if( s == 0 ):
88                 return (v,v,v)
89         
90
91         h /= 60
92         i = math.floor( h)
93         f = h - i
94         p = v * ( 1 - s )
95         q = v * ( 1 - s * f )
96         t = v * ( 1 - s * ( 1 - f ) )
97
98         if i == 0:
99                 r = v
100                 g = t
101                 b = p
102         elif i == 1:
103                 r = q
104                 g = v
105                 b = p
106
107         elif i== 2:
108                 r = p
109                 g = v
110                 b = t
111         elif i==3:
112                 r = p
113                 g = q
114                 b = v
115         elif i==4:
116                 r = t
117                 g = p
118                 b = v
119
120         else:
121                 r = v
122                 g = p
123                 b = q
124         
125         return(r,g,b)
126
127
128 palette_size = 12
129 palette_x = 0
130 palette_y = 0
131
132 colors = list()
133 curint = 1.0
134 curswatch = 0
135 #make a default palette, not very useful.
136 cinc = 1.0 / 1024.0
137 cstep = 0.0
138 picker = None
139 ptt = ""
140
141
142 ts1=None
143 ts2=None
144 ts3=None
145 ts4=None
146 ts5=None
147
148 for i in xrange(1024):
149         colors.append([cstep,cstep,cstep])
150         cstep = cstep + cinc
151 def update_state():
152         state = dict()
153         state["activeScene"] = Blender.Scene.getCurrent()
154         state["activeObject"] = state["activeScene"].getActiveObject()
155         state["activeMesh"] = None
156         if state["activeObject"] and state["activeObject"].type == 'Mesh':
157                 state["activeMesh"] = state["activeObject"].getData(mesh=True)
158         
159         state["activeFace"] = None
160         if state["activeMesh"]:
161                 if state["activeMesh"].faceUV and state["activeMesh"].activeFace != None:
162                         state["activeFace"] = state["activeMesh"].faces[state["activeMesh"].activeFace]
163                 
164         return state
165         
166 def pack_face_index(index, intensity):
167         return ((127*intensity)+(128*index))
168 def unpack_face_index(face_index):
169         index = face_index / 128
170         intensity = float(face_index - 128.0 * index) / 127.0
171         return(index,intensity)
172
173 def event(evt,val):
174         global palette_size
175         global palette_x
176         global palette_y
177         global colors
178         global curint
179         global curswatch
180         
181         areas = Blender.Window.GetScreenInfo()
182         curarea = Blender.Window.GetAreaID()
183         curRect = None
184         editmode = 0
185
186         for area in areas:
187                 if area['id'] == curarea:
188                         curRect = area['vertices']
189                         break
190                 
191         if evt == Draw.LEFTMOUSE:
192                 mval = Blender.Window.GetMouseCoords()
193                 rastx = mval[0] - curRect[0]
194                 rasty = mval[1] - curRect[1]
195                 
196                 swatchx = (rastx -palette_x) / palette_size #+state["palette_x"]
197                 swatchy = (rasty -palette_y) / palette_size #+state["palette_y"]
198                 if rastx > palette_x and rastx < (palette_x + palette_size * 32) and rasty > palette_y and rasty < (palette_y+ palette_size* 32):
199                         if swatchx < 32 and swatchy < 32:
200                                 curswatch = (swatchx * 32) + swatchy
201                                 Draw.Redraw(1)
202                 
203                 elif swatchy < 34 and swatchx < 32:
204                         curint = 1.0 - (float(rastx-palette_x)/(palette_size*32.0))
205                         Draw.Redraw(1)
206         
207         #copy current color and intensity to selected faces.
208         elif evt == Draw.VKEY:
209                 
210                 if Blender.Window.EditMode():
211                         Blender.Window.EditMode(0)
212                         editmode = 1
213                 state = update_state()
214                 
215                 #retrieve color from palette
216                 color = struct.unpack('>BBBB',struct.pack('>i',colors[curswatch]))
217                 actmesh = state["activeMesh"]
218                 if actmesh: 
219                         if(Blender.Window.GetKeyQualifiers() != Blender.Window.Qual["CTRL"]):
220                                 selfaces = list()
221                                 for face in actmesh.faces:
222                                         if face.sel:
223                                                 selfaces.append(face)
224                                 
225                                 if not "FLT_COL" in actmesh.faces.properties:
226                                         actmesh.faces.addPropertyLayer("FLT_COL",Blender.Mesh.PropertyTypes["INT"])
227                                         for face in actmesh.faces:
228                                                 face.setProperty("FLT_COL",127) #default
229                                 try:
230                                         actmesh.activeColorLayer = "FLT_Fcol"
231                                 except:
232                                         actmesh.addColorLayer("FLT_Fcol")
233                                         actmesh.activeColorLayer = "FLT_Fcol"
234                                 
235
236                                 for face in selfaces:
237                                         #First append packed index + color and store in face property
238                                         face.setProperty("FLT_COL",int(pack_face_index(curswatch,curint))) 
239                                         #Save baked color to face vertex colors
240                                         for col in face.col:
241                                                 col.r = int(color[0] * curint)
242                                                 col.g = int(color[1] * curint)
243                                                 col.b = int(color[2] * curint)
244                                                 col.a = int(color[3] * curint)
245                         else:
246                                 if Blender.Mesh.Mode() == Blender.Mesh.SelectModes['VERTEX']:
247                                         if not 'FLT_VCOL' in actmesh.verts.properties:
248                                                 actmesh.verts.addPropertyLayer("FLT_VCOL",Blender.Mesh.PropertyTypes["INT"])
249                                                 for vert in actmesh.verts:
250                                                         vert.setProperty("FLT_VCOL",127)
251                                         else:
252                                                 for vert in actmesh.verts:
253                                                         if vert.sel:
254                                                                 vert.setProperty("FLT_VCOL",int(pack_face_index(curswatch,curint)))
255                         
256                         if editmode:
257                                 Blender.Window.EditMode(1)
258                         
259                         Blender.Window.RedrawAll()
260         
261         #grab color and intensity from active face
262         elif evt == Draw.CKEY:
263                 if Blender.Window.EditMode():
264                         Blender.Window.EditMode(0)
265                         editmode = 1
266                 state = update_state()
267                 
268                 actmesh = state["activeMesh"]
269                 activeFace = state["activeFace"]
270                 
271                 
272                 if activeFace:
273                         if not "FLT_COL" in actmesh.faces.properties:
274                                 actmesh.faces.addPropertyLayer("FLT_COL",Blender.Mesh.PropertyTypes["INT"])
275                                 for face in actmesh.faces:
276                                         face.setProperty("FLT_COL",127) #default
277                         try:
278                                 actmesh.activeColorLayer = "FLT_Fcol"
279                         except:
280                                 actmesh.addColorLayer("FLT_Fcol")
281                                 actmesh.activeColorLayer = "FLT_Fcol"
282                         tcol = activeFace.getProperty("FLT_COL")
283                         (index,intensity) = unpack_face_index(tcol)
284                         curswatch = index
285                         curint = intensity
286                         
287                 if editmode:
288                         Blender.Window.EditMode(1)
289                 
290                 Blender.Window.RedrawAll()
291                 
292         elif evt == Draw.GKEY:
293                 if Blender.Window.EditMode():
294                         Blender.Window.EditMode(0)
295                         editmode =1
296                 state = update_state()
297                 
298                 actmesh = state["activeMesh"]
299                 activeFace = state["activeFace"]
300                 
301                 if activeFace and "FLT_COL" in actmesh.faces.properties:
302                         (index,intensity) = unpack_face_index(activeFace.getProperty("FLT_COL"))
303                         for face in actmesh.faces:
304                                 (index2, intensity2) = unpack_face_index(face.getProperty("FLT_COL"))
305                                 if index == index2:
306                                         face.sel = 1
307                                 
308                         
309         elif evt == Draw.ESCKEY:
310                 Draw.Exit()
311         
312         if editmode:
313                 Blender.Window.EditMode(1)
314
315 def update_all():
316         global colors
317         state = update_state()
318         #update the baked FLT colors for all meshes.
319         for object in state["activeScene"].objects:
320                 if object.type == "Mesh":
321                         mesh = object.getData(mesh=True)
322                         if 'FLT_COL' in mesh.faces.properties and "FLT_Fcol" in mesh.getColorLayerNames():
323                                 mesh.activeColorLayer = "FLT_Fcol"
324                                 for face in mesh.faces:
325                                         (index,intensity) = unpack_face_index(face.getProperty('FLT_COL'))
326                                         color = struct.unpack('>BBBB',struct.pack('>i',colors[index]))
327                                         #update the vertex colors for this face
328                                         for col in face.col:
329                                                 col.r = int(color[0] * intensity)
330                                                 col.g = int(color[1] * intensity)
331                                                 col.b = int(color[2] * intensity)
332                                                 col.a = 255
333
334
335 def but_event(evt):
336         global palette_size
337         global palette_x
338         global palette_y
339         global colors
340         global curint
341         global curswatch
342         global picker
343         state = update_state()
344
345         if evt == 1:
346                 if picker.val:
347                         rval = (int(picker.val[0]*255),int(picker.val[1]*255),int(picker.val[2]*255),255)
348                         rval = struct.pack('>BBBB',rval[0],rval[1],rval[2],rval[3])
349                         rval = struct.unpack('>i',rval)
350                         colors[curswatch] = rval[0]     
351                         #go cd through all meshes and update their FLT colors
352                         update_all()
353
354         Draw.Redraw(1)
355 def init_pal():
356         global palette_size
357         global palette_x
358         global palette_y
359         global colors
360         global curint
361         global curswatch
362         
363         state = update_state()
364
365         if not state["activeScene"].properties.has_key('FLT'):
366                 state["activeScene"].properties['FLT'] = dict()
367
368         try:
369                 colors = state["activeScene"].properties['FLT']['Color Palette']
370         except:
371                 state["activeScene"].properties['FLT']['Color Palette'] = defaultp.pal
372                 colors = state["activeScene"].properties['FLT']['Color Palette']
373
374 def draw_palette():
375         global palette_size
376         global palette_x
377         global palette_y
378         global colors
379         global curint
380         global curswatch
381         global picker
382         global ts1
383         global ts2
384         global ts3
385         global ts4
386         global ts5
387         
388         state = update_state()
389         init_pal()
390
391         ssize = palette_size
392         xpos = palette_x
393         cid = 0
394
395         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)]
396         for x in xrange(32):
397                 ypos = palette_y
398                 for y in xrange(32):
399                         color = struct.unpack('>BBBB',struct.pack('>i',colors[cid]))
400                         glColor3f(color[0]/255.0,color[1]/255.0,color[2]/255.0)
401                         glBegin(GL_POLYGON)
402                         glVertex2i(xpos,ypos)
403                         glVertex2i(xpos+ssize,ypos)
404                         glVertex2i(xpos+ssize,ypos+ssize)
405                         glVertex2i(xpos,ypos+ssize)                             
406                         glEnd()
407                         
408                         if curswatch == cid:
409                                 highlight[0] = (xpos,ypos)
410                                 highlight[1] = (xpos+ssize,ypos)
411                                 highlight[2] = (xpos+ssize,ypos+ssize)
412                                 highlight[3] = (xpos,ypos+ssize)
413                 
414                         glColor3f(0.0,0.0,0.0)
415                         glBegin(GL_LINE_LOOP)
416                         glVertex2i(xpos,ypos)
417                         glVertex2i(xpos+ssize,ypos)
418                         glVertex2i(xpos+ssize,ypos+ssize)
419                         glVertex2i(xpos,ypos+ssize)
420                         glVertex2i(xpos,ypos)                           
421                         glEnd()                 
422                                 
423                         
424                         cid = cid + 1
425                         ypos = ypos + ssize
426                 
427                 xpos = xpos + ssize
428         
429         #draw intensity gradient
430         color = struct.unpack('>BBBB',struct.pack('>i',colors[curswatch]))
431         color = [color[0]/255.0,color[1]/255.0,color[2]/255.0]
432         colsteps = [color[0]/255.0,color[1]/255.0,color[2]/255.0]
433         stripwidth = (palette_size * 32.0) / 256
434         strippad = palette_size / 2.0
435         
436         xpos = palette_x
437         grady = (palette_y + (palette_size * 32.0)) + strippad
438         for x in xrange(256):
439                 color[0] = color[0] - colsteps[0]
440                 color[1] = color[1] - colsteps[1] 
441                 color[2] = color[2] - colsteps[2]
442
443                 glColor3f(color[0], color[1] ,color[2])
444                 glBegin(GL_POLYGON)
445                 glVertex2f(xpos,grady)
446                 glVertex2f(xpos+stripwidth,grady)
447                 glVertex2f(xpos+stripwidth,grady+palette_size)
448                 glVertex2f(xpos,grady+palette_size)
449                 glEnd()
450                 xpos = xpos + stripwidth
451                 
452         #draw intensity slider bar
453         #xposition ==  512 - ((curint) * 512)
454         xpos = ((palette_size*32) * (1.0 - curint)) + palette_x
455         glColor3f(1.0,1.0,1.0)
456         glBegin(GL_LINE_LOOP)
457         glVertex2i(int(xpos-6),int(grady-1))
458         glVertex2i(int(xpos+6),int(grady-1))
459         glVertex2i(int(xpos+6),int(grady+palette_size+1))
460         glVertex2i(int(xpos-6),int(grady+palette_size+1))
461         #glVertex2i(xpos-6,grady+7)
462         glEnd()
463
464         #draw color picker
465         color = struct.unpack('>BBBB',struct.pack('>i',colors[curswatch]))
466         pickcol = (color[0]/255.0,color[1]/255.0,color[2]/255.0)
467         picker = Blender.Draw.ColorPicker(1,highlight[0][0]+1,highlight[0][1]+1,ssize-2,ssize-2,pickcol,ptt)
468
469         #draw highlight swatch
470         glColor3f(1.0,1.0,1.0)
471         glBegin(GL_LINE_LOOP)
472         glVertex2i(highlight[0][0],highlight[0][1])
473         glVertex2i(highlight[1][0],highlight[1][1])
474         glVertex2i(highlight[2][0],highlight[2][1])
475         glVertex2i(highlight[3][0],highlight[3][1])
476         glVertex2i(highlight[0][0],highlight[0][1])
477         glEnd()                 
478
479         #draw text string explanations
480         xpos = palette_size*32+20
481         ypos = palette_size*32+10
482         glRasterPos2d(xpos,ypos)
483         ts1     = Blender.Draw.Text("FLT Palette Manager V 1.0")
484         ypos = ypos - 20
485         glRasterPos2d(xpos,ypos)
486         ts3 = Blender.Draw.Text("CKEY - Copy Active Face Color*")
487         ypos = ypos - 20
488         glRasterPos2d(xpos,ypos)
489         ts2 = Blender.Draw.Text("VKEY - Paste Color to Selected Faces")
490         ypos = ypos - 20
491         glRasterPos2d(xpos,ypos)
492         ts4 = Blender.Draw.Text("GKEY - Select Faces With Same Color")
493         ypos = ypos - 15
494         glRasterPos2d(xpos,ypos)
495         ts5 = Blender.Draw.Text("(*Requires mesh with UV coordinates)", 'small')
496
497 def gui():
498         glClearColor(0.5,0.5,0.5,1.0)
499         glClear(GL_COLOR_BUFFER_BIT)
500         draw_palette()
501
502
503 init_pal()
504 Draw.Register(gui,event,but_event)
505