-> Color Fixing tool in FLT toolbar
[blender.git] / release / scripts / flt_toolbar.py
index 213fac1bb3c9b0e5b4a0e5ac962224dbecff64f9..249c3f83dfccd72ec7d0c4a867ea288f1d383b0e 100644 (file)
@@ -76,7 +76,8 @@ evcode = {
        "IDPROP_COPY" : 501,
        "IDPROP_KILL" : 502,
        "CLIGHT_MAKE" : 700,
-       "DFROMACT" : 701
+       "DFROMACT" : 701,
+       "FIXCOL" : 702
 }
 
 XREF_PREFIX = None
@@ -92,6 +93,44 @@ 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()
@@ -141,24 +180,130 @@ def idprops_copy(source):
                                for key in source.properties['FLT']:
                                        object.properties['FLT'][key] = source.properties['FLT'][key]
 
-def update_all():
+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()
-       #update the baked FLT colors for all meshes.
-       for object in state["activeScene"].objects:
-               if object.type == "Mesh":
+       
+       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:
-                               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',state["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
+                       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()
+       
+       if state["activeScene"].properties.has_key('FLT'):
+               try:
+                       colors = state["activeScene"].properties['FLT']['Color Palette']
+               except:
+                       colors = None
+       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():
@@ -528,6 +673,8 @@ def but_event(evt):
                clight_make()
        if evt == evcode["DFROMACT"]:
                dfromact()
+       if evt == evcode["FIXCOL"]:
+               fix_colors()
        Draw.Redraw(1)
        Blender.Window.RedrawAll()
 
@@ -582,17 +729,20 @@ def draw_postcommon(x,y,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 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
@@ -643,11 +793,13 @@ def draw_propsheet(x,y):
        
        y=y-20
        DFROMACT = Blender.Draw.PushButton("Dof from Active", evcode["DFROMACT"],x,y,width,20,"Get Dof origin from active object")
-        draw_postcommon(origx, origy,y)
+       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 = 280
+       psheety = 300
        #psheetx = psheety + 10
        draw_propsheet(0,psheety)
 Draw.Register(gui,event,but_event)