Add edge coloring
[vrm.git] / vrm.py
diff --git a/vrm.py b/vrm.py
index fc7cb5d..c7d7a87 100755 (executable)
--- a/vrm.py
+++ b/vrm.py
@@ -50,7 +50,6 @@ __bpydoc__ = """\
 #   - Implement clipping of primitives and do handle object intersections.
 #     (for now only clipping for whole objects is supported).
 #   - Implement Edge Styles (silhouettes, contours, etc.) (partially done).
 #   - Implement clipping of primitives and do handle object intersections.
 #     (for now only clipping for whole objects is supported).
 #   - Implement Edge Styles (silhouettes, contours, etc.) (partially done).
-#   - Implement Edge coloring
 #   - Use multiple lighting sources in color calculation
 #   - Implement Shading Styles? (for now we use Flat Shading).
 #   - Use a data structure other than Mesh to represent the 2D image? 
 #   - Use multiple lighting sources in color calculation
 #   - Implement Shading Styles? (for now we use Flat Shading).
 #   - Use a data structure other than Mesh to represent the 2D image? 
@@ -82,21 +81,22 @@ from math import *
 
 class config:
     polygons = dict()
 
 class config:
     polygons = dict()
-    polygons['FILL'] = True
-    polygons['STYLE'] = None
+    polygons['SHOW'] = True
+    polygons['SHADING'] = 'TOON'
     # Hidden to the user for now
     polygons['EXPANSION_TRICK'] = True
 
     edges = dict()
     edges['SHOW'] = True
     edges['SHOW_HIDDEN'] = False
     # Hidden to the user for now
     polygons['EXPANSION_TRICK'] = True
 
     edges = dict()
     edges['SHOW'] = True
     edges['SHOW_HIDDEN'] = False
-    edges['STYLE'] = 'silhouette'
+    edges['STYLE'] = 'SILHOUETTE'
     edges['WIDTH'] = 2
     edges['WIDTH'] = 2
+    edges['COLOR'] = [0, 0, 0]
 
     output = dict()
     output['FORMAT'] = 'SVG'
     output['ANIMATION'] = False
 
     output = dict()
     output['FORMAT'] = 'SVG'
     output['ANIMATION'] = False
-    output['MERGED_OBJECTS'] = True
+    output['JOIN_OBJECTS'] = True
 
 
 
 
 
 
@@ -120,10 +120,10 @@ class MeshUtils:
 
         return adjface_list
 
 
         return adjface_list
 
-    def isVisibleEdge(e, mesh):
-        """Normal edge selection rule.
+    def isMeshEdge(e, mesh):
+        """Mesh edge rule.
 
 
-        An edge is visible if _any_ of its adjacent faces is selected.
+        A mesh edge is visible if _any_ of its adjacent faces is selected.
         Note: if the edge has no adjacent faces we want to show it as well,
         useful for "edge only" portion of objects.
         """
         Note: if the edge has no adjacent faces we want to show it as well,
         useful for "edge only" portion of objects.
         """
@@ -178,7 +178,7 @@ class MeshUtils:
 
 
     getEdgeAdjacentFaces = staticmethod(getEdgeAdjacentFaces)
 
 
     getEdgeAdjacentFaces = staticmethod(getEdgeAdjacentFaces)
-    isVisibleEdge = staticmethod(isVisibleEdge)
+    isMeshEdge = staticmethod(isMeshEdge)
     isSilhouetteEdge = staticmethod(isSilhouetteEdge)
     toonShading = staticmethod(toonShading)
 
     isSilhouetteEdge = staticmethod(isSilhouetteEdge)
     toonShading = staticmethod(toonShading)
 
@@ -532,7 +532,7 @@ class SVGVectorWriter(VectorWriter):
 
         self.file.write("\n</svg>\n")
 
 
         self.file.write("\n</svg>\n")
 
-    def _printPolygons(self, mesh):
+    def _printPolygons(self, mesh): 
         """Print the selected (visible) polygons.
         """
 
         """Print the selected (visible) polygons.
         """
 
@@ -563,15 +563,14 @@ class SVGVectorWriter(VectorWriter):
             else:
                 color = [255, 255, 255, 255]
 
             else:
                 color = [255, 255, 255, 255]
 
+            # Convert the color to the #RRGGBB form
+            str_col = "#%02X%02X%02X" % (color[0], color[1], color[2])
+
             # use the stroke property to alleviate the "adjacent edges" problem,
             # we simulate polygon expansion using borders,
             # see http://www.antigrain.com/svg/index.html for more info
             # use the stroke property to alleviate the "adjacent edges" problem,
             # we simulate polygon expansion using borders,
             # see http://www.antigrain.com/svg/index.html for more info
-            stroke_col = color
             stroke_width = 0.5
 
             stroke_width = 0.5
 
-            # Convert the color to the #RRGGBB form
-            str_col = "#%02X%02X%02X" % (color[0], color[1], color[2])
-
             # Handle transparent polygons
             opacity_string = ""
             if color[3] != 255:
             # Handle transparent polygons
             opacity_string = ""
             if color[3] != 255:
@@ -592,8 +591,8 @@ class SVGVectorWriter(VectorWriter):
         """Print the wireframe using mesh edges.
         """
 
         """Print the wireframe using mesh edges.
         """
 
-        stroke_width=EDGES_WIDTH
-        stroke_col = [0, 0, 0]
+        stroke_width = config.edges['WIDTH']
+        stroke_col = config.edges['COLOR']
         
         self.file.write("<g>\n")
 
         
         self.file.write("<g>\n")
 
@@ -628,17 +627,19 @@ class SVGVectorWriter(VectorWriter):
 #
 # ---------------------------------------------------------------------
 
 #
 # ---------------------------------------------------------------------
 
-# A dictionary to collect all the different edge styles and their edge
-# selection criteria
-edgeSelectionStyles = {
-        'normal': MeshUtils.isVisibleEdge,
-        'silhouette': MeshUtils.isSilhouetteEdge
-        }
+# A dictionary to collect different shading style methods
+shadingStyles = dict()
+shadingStyles['FLAT'] = None
+shadingStyles['TOON'] = None
+
+# A dictionary to collect different edge style methods
+edgeStyles = dict()
+edgeStyles['MESH'] = MeshUtils.isMeshEdge
+edgeStyles['SILHOUETTE'] = MeshUtils.isSilhouetteEdge
 
 # A dictionary to collect the supported output formats
 
 # A dictionary to collect the supported output formats
-outputWriters = {
-        'SVG': SVGVectorWriter,
-        }
+outputWriters = dict()
+outputWriters['SVG'] = SVGVectorWriter
 
 
 class Renderer:
 
 
 class Renderer:
@@ -705,11 +706,11 @@ class Renderer:
         """
         
         context = self._SCENE.getRenderingContext()
         """
         
         context = self._SCENE.getRenderingContext()
-        currentFrame = context.currentFrame()
+        origCurrentFrame = context.currentFrame()
 
         # Handle the animation case
         if not animation:
 
         # Handle the animation case
         if not animation:
-            startFrame = currentFrame
+            startFrame = origCurrentFrame
             endFrame = startFrame
             outputWriter.open()
         else:
             endFrame = startFrame
             outputWriter.open()
         else:
@@ -725,22 +726,23 @@ class Renderer:
             # Use some temporary workspace, a full copy of the scene
             inputScene = self._SCENE.copy(2)
 
             # Use some temporary workspace, a full copy of the scene
             inputScene = self._SCENE.copy(2)
 
-            print "Before"
-
             try:
                 renderedScene = self.doRenderScene(inputScene)
             try:
                 renderedScene = self.doRenderScene(inputScene)
-            except:
+            except :
+                print "There was an error! Aborting."
+                import traceback
+                print traceback.print_exc()
+
                 self._SCENE.makeCurrent()
                 Scene.unlink(inputScene)
                 del inputScene
                 self._SCENE.makeCurrent()
                 Scene.unlink(inputScene)
                 del inputScene
+                return
 
             outputWriter.printCanvas(renderedScene,
 
             outputWriter.printCanvas(renderedScene,
-                    doPrintPolygons = config.polygons['FILL'],
+                    doPrintPolygons = config.polygons['SHOW'],
                     doPrintEdges    = config.edges['SHOW'],
                     showHiddenEdges = config.edges['SHOW_HIDDEN'])
             
                     doPrintEdges    = config.edges['SHOW'],
                     showHiddenEdges = config.edges['SHOW_HIDDEN'])
             
-            print "After"
-
             # clear the rendered scene
             self._SCENE.makeCurrent()
             Scene.unlink(renderedScene)
             # clear the rendered scene
             self._SCENE.makeCurrent()
             Scene.unlink(renderedScene)
@@ -748,7 +750,7 @@ class Renderer:
 
         outputWriter.close()
         print "Done!"
 
         outputWriter.close()
         print "Done!"
-        context.currentFrame(currentFrame)
+        context.currentFrame(origCurrentFrame)
 
 
     def doRenderScene(self, workScene):
 
 
     def doRenderScene(self, workScene):
@@ -764,19 +766,9 @@ class Renderer:
 
         self._doSceneClipping(workScene)
 
 
         self._doSceneClipping(workScene)
 
-
-        # XXX: Joining objects does not work in batch mode!!
-        # Do not touch the following if, please :)
-
-        global OPTIMIZE_FOR_SPACE
-        if Blender.mode == 'background':
-            print "\nWARNING! Joining objects not supported in background mode!\n"
-            OPTIMIZE_FOR_SPACE = False
-
-        if OPTIMIZE_FOR_SPACE:
+        if config.output['JOIN_OBJECTS']:
             self._joinMeshObjectsInScene(workScene)
 
             self._joinMeshObjectsInScene(workScene)
 
-
         self._doSceneDepthSorting(workScene)
         
         # Per object activities
         self._doSceneDepthSorting(workScene)
         
         # Per object activities
@@ -790,22 +782,17 @@ class Renderer:
 
             print "Rendering: ", obj.getName()
 
 
             print "Rendering: ", obj.getName()
 
-            mesh = obj.getData()
+            mesh = obj.getData(mesh=1)
 
             self._doModelToWorldCoordinates(mesh, obj.matrix)
 
             self._doObjectDepthSorting(mesh)
             
 
             self._doModelToWorldCoordinates(mesh, obj.matrix)
 
             self._doObjectDepthSorting(mesh)
             
-            # We use both Mesh and NMesh because for depth sorting we change
-            # face order and Mesh class don't let us to do that.
-            mesh.update()
-            mesh = obj.getData(mesh=1)
-            
             self._doBackFaceCulling(mesh)
             
             self._doColorAndLighting(mesh)
 
             self._doBackFaceCulling(mesh)
             
             self._doColorAndLighting(mesh)
 
-            self._doEdgesStyle(mesh, edgeSelectionStyles[EDGE_STYLE])
+            self._doEdgesStyle(mesh, edgeStyles[config.edges['STYLE']])
 
             self._doProjection(mesh, self.proj)
             
 
             self._doProjection(mesh, self.proj)
             
@@ -907,7 +894,6 @@ class Renderer:
                 me.recalcNormals()
                 me.update()
 
                 me.recalcNormals()
                 me.update()
 
-
     def _doSceneClipping(self, scene):
         """Clip objects against the View Frustum.
 
     def _doSceneClipping(self, scene):
         """Clip objects against the View Frustum.
 
@@ -967,18 +953,31 @@ class Renderer:
         """Merge all the Mesh Objects in a scene into a single Mesh Object.
         """
 
         """Merge all the Mesh Objects in a scene into a single Mesh Object.
         """
 
+        if Blender.mode == 'background':
+            print "\nWARNING! Joining objects not supported in background mode!\n"
+            return
+
         oList = [o for o in scene.getChildren() if o.getType()=='Mesh']
 
         # FIXME: Object.join() do not work if the list contains 1 object
         if len(oList) == 1:
             return
 
         oList = [o for o in scene.getChildren() if o.getType()=='Mesh']
 
         # FIXME: Object.join() do not work if the list contains 1 object
         if len(oList) == 1:
             return
 
-        mesh = Mesh.New()
+        mesh = Mesh.New('BigOne')
         bigObj = Object.New('Mesh', 'BigOne')
         bigObj.link(mesh)
 
         bigObj = Object.New('Mesh', 'BigOne')
         bigObj.link(mesh)
 
-        bigObj.join(oList)
         scene.link(bigObj)
         scene.link(bigObj)
+
+        try:
+            bigObj.join(oList)
+        except RuntimeError:
+            print "Can't Join Objects"
+            scene.unlink(bigObj)
+            return
+        except TypeError:
+            print "Objects Type error?"
+        
         for o in oList:
             scene.unlink(o)
 
         for o in oList:
             scene.unlink(o)
 
@@ -1024,6 +1023,9 @@ class Renderer:
         The faces in the object are sorted following the distance of the
         vertices from the camera position.
         """
         The faces in the object are sorted following the distance of the
         vertices from the camera position.
         """
+        if len(mesh.faces) == 0:
+            return
+
         c = self._getObjPosition(self.cameraObj)
 
         # hackish sorting of faces
         c = self._getObjPosition(self.cameraObj)
 
         # hackish sorting of faces
@@ -1043,8 +1045,19 @@ class Renderer:
                 cmp(sum([(Vector(v.co)-Vector(c)).length for v in f1])/len(f1),
                     sum([(Vector(v.co)-Vector(c)).length for v in f2])/len(f2)))
 
                 cmp(sum([(Vector(v.co)-Vector(c)).length for v in f1])/len(f1),
                     sum([(Vector(v.co)-Vector(c)).length for v in f2])/len(f2)))
 
-        mesh.faces.sort(by_max_vert_dist)
-        mesh.faces.reverse()
+
+        # FIXME: using NMesh to sort faces. We should avoid that!
+        nmesh = NMesh.GetRaw(mesh.name)
+        nmesh.faces.sort(by_max_vert_dist)
+        nmesh.faces.reverse()
+
+        mesh.faces.delete(1, range(0, len(mesh.faces)))
+
+        for i,f in enumerate(nmesh.faces):
+            fv = [v.index for v in f.v] 
+            mesh.faces.extend(fv)
+            mesh.faces[i].mat = f.mat
+
 
     def _doBackFaceCulling(self, mesh):
         """Simple Backface Culling routine.
 
     def _doBackFaceCulling(self, mesh):
         """Simple Backface Culling routine.
@@ -1065,22 +1078,10 @@ class Renderer:
             if self._isFaceVisible(f):
                 f.sel = 1
 
             if self._isFaceVisible(f):
                 f.sel = 1
 
-        # Is this the correct way to propagate the face selection info to the
-        # vertices belonging to a face ??
-        # TODO: Using the Mesh module this should come for free. Right?
-        #Mesh.Mode(Mesh.SelectModes['VERTEX'])
-        #for f in mesh.faces:
-        #    if not f.sel:
-        #        for v in f: v.sel = 0;
-
-        #for f in mesh.faces:
-        #    if f.sel:
-        #        for v in f: v.sel = 1;
-
     def _doColorAndLighting(self, mesh):
     def _doColorAndLighting(self, mesh):
-        """Apply an Illumination model to the object.
+        """Apply an Illumination ans shading model to the object.
 
 
-        The Illumination model used is the Phong one, it may be inefficient,
+        The model used is the Phong one, it may be inefficient,
         but I'm just learning about rendering and starting from Phong seemed
         the most natural way.
         """
         but I'm just learning about rendering and starting from Phong seemed
         the most natural way.
         """
@@ -1118,16 +1119,16 @@ class Renderer:
             
             L = Vector(light_pos).normalize()
 
             
             L = Vector(light_pos).normalize()
 
-            V = (Vector(camPos) - Vector(f.v[0].co)).normalize()
+            V = (Vector(camPos) - Vector(f.cent)).normalize()
 
             N = Vector(f.no).normalize()
 
             R = 2 * (N*L) * N - L
 
             # TODO: Attenuation factor (not used for now)
 
             N = Vector(f.no).normalize()
 
             R = 2 * (N*L) * N - L
 
             # TODO: Attenuation factor (not used for now)
-            a0 = 1; a1 = 0.0; a2 = 0.0
+            a0 = 1.0; a1 = 0.0; a2 = 1.0
             d = (Vector(f.v[0].co) - Vector(light_pos)).length
             d = (Vector(f.v[0].co) - Vector(light_pos)).length
-            fd = min(1, 1.0/(a0 + a1*d + a2*d*d))
+            fd = min(1, 1.0/(a0 + a1*d + a2*(d*d)))
 
             # Ambient component
             Ia = 1.0
 
             # Ambient component
             Ia = 1.0
@@ -1137,8 +1138,11 @@ class Renderer:
             # Diffuse component (add light.col for kd)
             kd = mat.getRef() * Vector(mat.getRGBCol())
             Ip = light.getEnergy()
             # Diffuse component (add light.col for kd)
             kd = mat.getRef() * Vector(mat.getRGBCol())
             Ip = light.getEnergy()
-            #Idiff = Ip * kd * int(N*L > 0.5)
-            Idiff = Ip * kd * MeshUtils.toonShading(N*L)
+            
+            if config.polygons['SHADING'] == 'FLAT':
+                Idiff = Ip * kd * (N*L)
+            elif config.polygons['SHADING'] == 'TOON':
+                Idiff = Ip * kd * MeshUtils.toonShading(N*L)
 
             # Specular component
             ks = mat.getSpec() * Vector(mat.getSpecCol())
 
             # Specular component
             ks = mat.getSpec() * Vector(mat.getSpecCol())
@@ -1148,19 +1152,18 @@ class Renderer:
             # Emissive component
             ki = Vector([mat.getEmit()]*3)
 
             # Emissive component
             ki = Vector([mat.getEmit()]*3)
 
-            I = ki + Iamb + Idiff + Ispec
+            I = ki + Iamb + (Idiff + Ispec)
 
 
             # Set Alpha component
             I = list(I)
             I.append(mat.getAlpha())
 
 
 
             # Set Alpha component
             I = list(I)
             I.append(mat.getAlpha())
 
-            # Toon shading
-            #I = [MeshUtils.toonShading(c) for c in I] 
-
             # Clamp I values between 0 and 1
             I = [ min(c, 1) for c in I]
             I = [ max(0, c) for c in I]
             # Clamp I values between 0 and 1
             I = [ min(c, 1) for c in I]
             I = [ max(0, c) for c in I]
+
+            # Convert to a value between 0 and 255
             tmp_col = [ int(c * 255.0) for c in I]
 
             for c in f.col:
             tmp_col = [ int(c * 255.0) for c in I]
 
             for c in f.col:
@@ -1229,11 +1232,17 @@ class GUI:
         GUI.evtAnimToggle = 1
 
         # Join Objects toggle button
         GUI.evtAnimToggle = 1
 
         # Join Objects toggle button
-        GUI.joinObjsToggle = Draw.Create(config.output['MERGED_OBJECTS'])
+        GUI.joinObjsToggle = Draw.Create(config.output['JOIN_OBJECTS'])
         GUI.evtJoinObjsToggle = 2
 
         # Render filled polygons
         GUI.evtJoinObjsToggle = 2
 
         # Render filled polygons
-        GUI.polygonsToggle = Draw.Create(config.polygons['FILL'])
+        GUI.polygonsToggle = Draw.Create(config.polygons['SHOW'])
+
+        # Shading Style menu 
+        shading_style = config.polygons['SHADING']
+        default_value = shadingStyles.keys().index(shading_style)+1
+        GUI.shadingStyleMenu = Draw.Create(default_value)
+        GUI.evtShadingStyleMenu = 21
 
         GUI.evtPolygonsToggle = 3
         # We hide the config.polygons['EXPANSION_TRICK'], for now
 
         GUI.evtPolygonsToggle = 3
         # We hide the config.polygons['EXPANSION_TRICK'], for now
@@ -1248,7 +1257,7 @@ class GUI:
 
         # Edge Style menu 
         edge_style = config.edges['STYLE']
 
         # Edge Style menu 
         edge_style = config.edges['STYLE']
-        default_value = edgeSelectionStyles.keys().index(edge_style)+1
+        default_value = edgeStyles.keys().index(edge_style)+1
         GUI.edgeStyleMenu = Draw.Create(default_value)
         GUI.evtEdgeStyleMenu = 6
 
         GUI.edgeStyleMenu = Draw.Create(default_value)
         GUI.evtEdgeStyleMenu = 6
 
@@ -1256,6 +1265,11 @@ class GUI:
         GUI.edgeWidthSlider = Draw.Create(config.edges['WIDTH'])
         GUI.evtEdgeWidthSlider = 7
 
         GUI.edgeWidthSlider = Draw.Create(config.edges['WIDTH'])
         GUI.evtEdgeWidthSlider = 7
 
+        # Edge Color Picker
+        c = config.edges['COLOR']
+        GUI.edgeColorPicker = Draw.Create(c[0]/255.0, c[1]/255.0, c[2]/255.0)
+        GUI.evtEdgeColorPicker = 71
+
         # Render Button
         GUI.evtRenderButton = 8
 
         # Render Button
         GUI.evtRenderButton = 8
 
@@ -1307,30 +1321,45 @@ class GUI:
                 200, 285, 160, 18, GUI.polygonsToggle.val,
                 "Render filled polygons")
 
                 200, 285, 160, 18, GUI.polygonsToggle.val,
                 "Render filled polygons")
 
+        if GUI.polygonsToggle.val == 1:
+
+            # Polygon Shading Style
+            shadingStyleMenuStruct = "Shading Style %t"
+            for t in shadingStyles.keys():
+                shadingStyleMenuStruct = shadingStyleMenuStruct + "|%s" % t.lower()
+            GUI.shadingStyleMenu = Draw.Menu(shadingStyleMenuStruct, GUI.evtShadingStyleMenu,
+                    200, 260, 160, 18, GUI.shadingStyleMenu.val,
+                    "Choose the shading style")
+
+
         # Render Edges
         GUI.showEdgesToggle = Draw.Toggle("Show Edges", GUI.evtShowEdgesToggle,
         # Render Edges
         GUI.showEdgesToggle = Draw.Toggle("Show Edges", GUI.evtShowEdgesToggle,
-                200, 260, 160, 18, GUI.showEdgesToggle.val,
+                200, 235, 160, 18, GUI.showEdgesToggle.val,
                 "Render polygon edges")
 
         if GUI.showEdgesToggle.val == 1:
             
             # Edge Style
             edgeStyleMenuStruct = "Edge Style %t"
                 "Render polygon edges")
 
         if GUI.showEdgesToggle.val == 1:
             
             # Edge Style
             edgeStyleMenuStruct = "Edge Style %t"
-            for t in edgeSelectionStyles.keys():
-               edgeStyleMenuStruct = edgeStyleMenuStruct + "|%s" % t
+            for t in edgeStyles.keys():
+                edgeStyleMenuStruct = edgeStyleMenuStruct + "|%s" % t.lower()
             GUI.edgeStyleMenu = Draw.Menu(edgeStyleMenuStruct, GUI.evtEdgeStyleMenu,
             GUI.edgeStyleMenu = Draw.Menu(edgeStyleMenuStruct, GUI.evtEdgeStyleMenu,
-                    200, 235, 160, 18, GUI.edgeStyleMenu.val,
+                    200, 210, 160, 18, GUI.edgeStyleMenu.val,
                     "Choose the edge style")
 
             # Edge size
             GUI.edgeWidthSlider = Draw.Slider("Width: ", GUI.evtEdgeWidthSlider,
                     "Choose the edge style")
 
             # Edge size
             GUI.edgeWidthSlider = Draw.Slider("Width: ", GUI.evtEdgeWidthSlider,
-                    200, 210, 160, 18, GUI.edgeWidthSlider.val,
+                    200, 185, 140, 18, GUI.edgeWidthSlider.val,
                     0.0, 10.0, 0, "Change Edge Width")
 
                     0.0, 10.0, 0, "Change Edge Width")
 
+            # Edge Color
+            GUI.edgeColorPicker = Draw.ColorPicker(GUI.evtEdgeColorPicker,
+                    342, 185, 18, 18, GUI.edgeColorPicker.val, "Choose Edge Color")
+
             # Show Hidden Edges
             GUI.showHiddenEdgesToggle = Draw.Toggle("Show Hidden Edges",
                     GUI.evtShowHiddenEdgesToggle,
             # Show Hidden Edges
             GUI.showHiddenEdgesToggle = Draw.Toggle("Show Hidden Edges",
                     GUI.evtShowHiddenEdgesToggle,
-                    200, 185, 160, 18, GUI.showHiddenEdgesToggle.val,
+                    200, 160, 160, 18, GUI.showHiddenEdgesToggle.val,
                     "Render hidden edges as dashed lines")
 
         glRasterPos2i(10, 160)
                     "Render hidden edges as dashed lines")
 
         glRasterPos2i(10, 160)
@@ -1358,10 +1387,14 @@ class GUI:
             config.outpur['ANIMATION'] = bool(GUI.animToggle.val)
 
         elif evt == GUI.evtJoinObjsToggle:
             config.outpur['ANIMATION'] = bool(GUI.animToggle.val)
 
         elif evt == GUI.evtJoinObjsToggle:
-            config.output['MERGED_OBJECTS'] = bool(GUI.joinObjsToggle.val)
+            config.output['JOIN_OBJECTS'] = bool(GUI.joinObjsToggle.val)
 
         elif evt == GUI.evtPolygonsToggle:
 
         elif evt == GUI.evtPolygonsToggle:
-            config.polygons['FILL'] = bool(GUI.polygonsToggle.val)
+            config.polygons['SHOW'] = bool(GUI.polygonsToggle.val)
+
+        elif evt == GUI.evtShadingStyleMenu:
+            i = GUI.shadingStyleMenu.val - 1
+            config.polygons['SHADING'] = shadingStyles.keys()[i]
 
         elif evt == GUI.evtShowEdgesToggle:
             config.edges['SHOW'] = bool(GUI.showEdgesToggle.val)
 
         elif evt == GUI.evtShowEdgesToggle:
             config.edges['SHOW'] = bool(GUI.showEdgesToggle.val)
@@ -1371,11 +1404,14 @@ class GUI:
 
         elif evt == GUI.evtEdgeStyleMenu:
             i = GUI.edgeStyleMenu.val - 1
 
         elif evt == GUI.evtEdgeStyleMenu:
             i = GUI.edgeStyleMenu.val - 1
-            config.edges['STYLE'] = edgeSelectionStyles.keys()[i]
+            config.edges['STYLE'] = edgeStyles.keys()[i]
 
         elif evt == GUI.evtEdgeWidthSlider:
             config.edges['WIDTH'] = float(GUI.edgeWidthSlider.val)
 
 
         elif evt == GUI.evtEdgeWidthSlider:
             config.edges['WIDTH'] = float(GUI.edgeWidthSlider.val)
 
+        elif evt == GUI.evtEdgeColorPicker:
+            config.edges['COLOR'] = [int(c*255.0) for c in GUI.edgeColorPicker.val]
+
         elif evt == GUI.evtRenderButton:
             label = "Save %s" % config.output['FORMAT']
             # Show the File Selector
         elif evt == GUI.evtRenderButton:
             label = "Save %s" % config.output['FORMAT']
             # Show the File Selector
@@ -1391,7 +1427,10 @@ class GUI:
 
     def conf_debug():
         from pprint import pprint
 
     def conf_debug():
         from pprint import pprint
-        pprint(config)
+        print "\nConfig"
+        pprint(config.output)
+        pprint(config.polygons)
+        pprint(config.edges)
 
     _init = staticmethod(_init)
     draw = staticmethod(draw)
 
     _init = staticmethod(_init)
     draw = staticmethod(draw)