#!BPY """ Name: 'Pantograph' Blender: 245 Group: 'Render' Tooltip: 'Vector Rendering Engine' """ __author__ = "Severn Clay" __url__ = ["http://severnclaystudio.wordpress.com/category/pantograph/"] __version__ = "0.5" __bpydoc__ = """\ Render the scene and save the result as a vector file. """ # ----------------------------------------------------------------------------- # Copyright (c) 2007, 2008 by Severn Clay # # 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # # ----------------------------------------------------------------------------- import Blender from Blender import Mathutils, Mesh, Draw, BGL, Image, Window from Blender.Mathutils import * import pantographLib from pantographLib import * reload(pantographLib) from copy import deepcopy, copy from bisect import insort from math import tan,atan,pi,degrees,sqrt,radians import time from time import clock import cPickle import sys, os import string import cairo GUI_VERSION = "0.5" if GUI_VERSION != LIB_VERSION: print "You have an old version of pantographLib.py installed in your search path." print ("You should remove it, and install the proper version: %f" % GUI_VERSION) sys.exit(1) #---GUI GLOBAL VARIABLES---#000000#FFFFFF------------------------------------------------------- mouseDrag = False initialMouseLoc = [0,0] curMouseX = 0 curMouseY = 0 zoomFactor = 1.0 currentMaxZoom = 0 lastEvent = None drawing = None defaultButton = None menuState = "PRERENDER" editState = "NONE" progressImage = Image.Load(HOMEDIR + 'progressImage.png') BACKGROUNDCOLOR = (0.9,0.9,0.9,1) SWATCH_ON = False SMALL_BUTTON_HEIGHT = 16 swatchWidth = 48 swatchHeight = SMALL_BUTTON_HEIGHT swatchDict = dict() buttonDict = dict() [buttonDict.__setitem__(lineType,dict()) for lineType in Pen.lineTypeList] ##def event(evt, val): ## global zoomFactor, imageWidth, imageHeight, imageLocX, imageLocY, mouseDrag, initialMouseLoc, lastEvent, currentMaxZoom ## ## if evt == Draw.MIDDLEMOUSE and mouseDrag: ## #the middle button has been released ## mouseDrag = False ## lastEvent = evt ## return ## ## elif evt == Draw.MIDDLEMOUSE and (lastEvent != Draw.WHEELUPMOUSE) and (lastEvent != Draw.WHEELDOWNMOUSE) and not mouseDrag: ## #the middle button has been pressed, but not rolled ## mouseDrag = True ## myMouseLoc = Window.GetMouseCoords() ## initialMouseLoc = (myMouseLoc[0] + imageLocX, myMouseLoc[1] + imageLocY) ## lastEvent = evt ## return ## ## elif (evt == Draw.MOUSEX or evt == Draw.MOUSEY) and mouseDrag: ## #the middle button is still being pressed, so we drag ## print "drag event" ## currentMouseLoc = Window.GetMouseCoords() ## windowSize = Window.GetAreaSize() ## imageLocX = (initialMouseLoc[0] - currentMouseLoc[0]) ## ## imageLocY = (initialMouseLoc[1] - currentMouseLoc[1]) ## ## Draw.Redraw(1) ## lastEvent = evt ## return ## ## elif evt == Draw.WHEELUPMOUSE: ## #middle button wheel event ## mouseDrag = False ## ## zoomFactor += 0.1 ## imageWidth = initWidth/zoomFactor ## imageHeight = initHeight/zoomFactor ## if imageHeight > testImage.size[1]/2: ## corrected = imageHeight-1 ## imageHeight = corrected ## ## if imageWidth > testImage.size[0]/2: ## corrected = imageWidth-1 ## imageWidth = corrected ## ## lastEvent = evt ## Draw.Redraw(1) ## ## if zoomFactor > currentMaxZoom: ## currentMaxZoom = zoomFactor ## print ("Redrawing to %f" % currentMaxZoom) ## ## return ## ## elif evt == Draw.WHEELDOWNMOUSE: ## #middle button wheel event ## mouseDrag = False ## ## if zoomFactor < 0: zoomFactor = 0.01 ## else: zoomFactor -= 0.1 ## imageWidth = initWidth/zoomFactor ## imageHeight = initHeight/zoomFactor ## if imageHeight > testImage.size[1]/2: ## corrected = imageHeight-1 ## imageHeight = corrected ## ## if imageWidth > testImage.size[0]/2: ## corrected = imageWidth-1 ## imageWidth = corrected ## ## lastEvent = evt ## Draw.Redraw(1) ## return ## ## ## elif evt == Draw.ESCKEY: ## Draw.Exit() ## return ## ## else: ## lastEvent = evt ## return def button_event(evt): global editState, menuState, drawing, swatchDict #Settings Menu if evt == 1: windowSize = Window.GetAreaSize() mouseLoc = Window.GetMouseCoords() Window.SetMouseCoords(mouseLoc[0],mouseLoc[1]+(windowSize[1]/2)) pupContents = "Settings:%t|Save|Load|Edit" result = Draw.PupMenu(pupContents) Draw.Redraw(1) if result == 1: #Save Window.FileSelector (saveSettings, 'Save File as *.pog', drawing.settings.currentSettingsFolder + '/default.pog') if result == 2: #Load Window.FileSelector (loadSettings, 'Select File *.pog', drawing.settings.currentSettingsFolder + '/default.pog') if result == 3: #Edit materialList = drawing.fillDict.keys() pupContents = "Select a material to assign:%t|" + string.join([item for item in materialList], '|') myMaterial = materialList[Draw.PupMenu(pupContents)-1] pupContents = "Select a pen to assign to "+ myMaterial +":%t|" + string.join([item.name for item in drawing.settings.penStorage], '|') myPen = drawing.settings.penStorage[Draw.PupMenu(pupContents)-1] applyMaterialToPen(myMaterial, myPen) return #Pens Menu elif evt == 2: windowSize = Window.GetAreaSize() mouseLoc = Window.GetMouseCoords() Window.SetMouseCoords(mouseLoc[0],mouseLoc[1]+(windowSize[1]/2)) pupContents = "Pens:%t|Save|Load|Edit" result = Draw.PupMenu(pupContents) Draw.Redraw(1) if result == 1: #Save penList = drawing.settings.pens.items() pupContents = "Select a pen:%t|" + string.join([item.name for item in drawing.settings.penStorage], '|') myPen = drawing.settings.penStorage[Draw.PupMenu(pupContents)-1] drawing.settings.currentPen = myPen Window.FileSelector (savePen, 'Save File as *.pen', drawing.settings.currentSettingsFolder + '/' + myPen.name + '.pen') if result == 2: #Load Window.FileSelector (loadPen, 'Select File *.pen', drawing.settings.currentSettingsFolder + '/default.pen') if result == 3: #Edit penList = drawing.settings.pens.items() pupContents = "Select a pen:%t|" + string.join([item.name for item in drawing.settings.penStorage], '|') drawing.settings.currentPen = drawing.settings.penStorage[Draw.PupMenu(pupContents)-1] swatchDict = drawing.renderSwatch(drawing.settings.currentPen) menuState = "EDIT" return #Export Menu elif evt == 3: windowSize = Window.GetAreaSize() mouseLoc = Window.GetMouseCoords() Window.SetMouseCoords(mouseLoc[0],mouseLoc[1]+(windowSize[1]/2)) pupContents = "Export to file:%t|.swf (animated)|.svg|.pdf|.png" result = Draw.PupMenu(pupContents) Draw.Redraw(1) if result == 1: #.swf Window.FileSelector (export, 'Save File as *.swf', 'filename.swf') if result == 2: #.svg Window.FileSelector (export,'Save File as *.svg', 'filename.svg') if result == 3: #.pdf Window.FileSelector (export,'Save File as *.pdf', 'filename.pdf') if result == 4: #.png Window.FileSelector (export,'Save File as *.png', 'filename.png') return #About Menu elif evt == 4: windowSize = Window.GetAreaSize() mouseLoc = Window.GetMouseCoords() Window.SetMouseCoords(mouseLoc[0],mouseLoc[1]+(windowSize[1]/2)) pupContents = [ ("PANTOGRAPH version " + GUI_VERSION), ("by Severn Clay"), (""), ("copyright 2008,"), ("all rights reserved")] if not Draw.PupBlock(("About"), pupContents): return Draw.Redraw(1) #Quit elif evt == 5: progress('Bye!') Draw.Exit() return ##EDIT MENU## #Title elif evt == 10: penList = drawing.settings.pens.items() pupContents = "Select a pen:%t|" + string.join([item.name for item in drawing.settings.penStorage], '|') drawing.settings.currentPen = drawing.settings.penStorage[Draw.PupMenu(pupContents)-1] for (lineType, callback) in zip(drawing.settings.currentPen.lineTypeList, range(11, 11+(8 * len(drawing.settings.currentPen.lineTypeList)), 8)): if evt == callback: if editState == lineType: editState = "None" else: editState = lineType #Fill if evt == 67: if editState == "FILL": editState = "NONE" else: editState = "FILL" if evt == 71: Window.FileSelector (loadRaster, 'Select File *.png', drawing.settings.currentPen.attributeDict["FILLRASTER"]["filename"]) #Global Silhouette if evt == 72: if editState == "GLOBAL SILHOUETTE": editState = "NONE" else: editState = "GLOBAL SILHOUETTE" #Done if evt == 100: menuState = "REVIEW" def preRenderMenu(): global drawing USE_ALPHA = Draw.Create(drawing.settings.USE_ALPHA) CULL_BACKFACES = Draw.Create(drawing.settings.CULL_BACKFACES) AUTO_CREASE = Draw.Create(drawing.settings.AUTO_CREASE) LOAD_PREVIOUS_SETTINGS = Draw.Create(drawing.settings.LOAD_PREVIOUS_SETTINGS) pupContents = [ ('Use alpha', USE_ALPHA, 'Render with alpha transparency'), ('Cull backfaces', CULL_BACKFACES, 'Do not render faces oriented away from the camera'), ('Auto-crease', AUTO_CREASE, 'Auto detect crease edges according to the Auto Smooth setting'), ('Load settings', LOAD_PREVIOUS_SETTINGS, 'Load previous settings')] Draw.PupBlock(("Pantograph " + str(GUI_VERSION) + " "), pupContents) return (USE_ALPHA.val, CULL_BACKFACES.val, AUTO_CREASE.val, LOAD_PREVIOUS_SETTINGS.val) def progressMenu(drawing): global defaultButton, progressImage,imageBuffer, imageToggle, zoomFactor, mouseDrag, curMouseX, curMouseY, imageLocX, imageLocY, imageWidth, imageHeight, menuState imageWidth = progressImage.size[0] imageHeight = progressImage.size[1] margin = 5 buttonWidth = 75 buttonHeight = 25 currentX = 0 currentY = 0 #Settings Menu settingsButton = Draw.PushButton("Settings", 1, currentX + margin, margin, buttonWidth, buttonHeight, "Load, save and edit Pen-to-Material assignments") currentX = (currentX + buttonWidth + margin) #Pens Menu pensButton = Draw.PushButton("Pens", 2, currentX + margin, margin, buttonWidth, buttonHeight, "Load, save and edit Pen attributes") currentX = (currentX + buttonWidth + margin) #Export Menu exportButton = Draw.PushButton("Export", 3, currentX + margin, margin, buttonWidth, buttonHeight, "Export to image file or animation") currentX = (currentX + buttonWidth + margin) #About Menu aboutButton = Draw.PushButton("About", 4, currentX + margin, margin, buttonWidth, buttonHeight, "About Pantograph") #Progress image Draw.Image(progressImage, margin, buttonHeight + 2*margin, 1, 1, 0, 0, int(imageWidth), int(imageHeight)) if menuState == "PROGRESS": menuState = "DONOTHING" blender2Pantograph(drawing) buildConnectivity(drawing) makeFrustum(drawing.scene) doVignettes(drawing.scene) doCutaways(drawing.scene) (drawing.visiblePolygons, drawing.hiddenPolygons) = occludeAndCull(drawing) #drawing.visiblePolygons = list(drawing.scene.faces) #drawing.hiddenPolygons = [] drawing.drawingQueue = BSPSort(drawing.scene, drawing.visiblePolygons) clipAndCombine(drawing) cairoSurface = drawing.render(drawing.WIDTH, drawing.HEIGHT) imageBuffer = cairoToImage(cairoSurface, drawing.WIDTH, drawing.HEIGHT) debug('mark 1', menuState) menuState = "REVIEW" Draw.Redraw(1) debug('mark 2', menuState) def reviewMenu(drawing): global defaultButton, imageBuffer, imageToggle, zoomFactor, mouseDrag, curMouseX, curMouseY, imageLocX, imageLocY, imageWidth, imageHeight margin = 5 buttonWidth = 75 buttonHeight = 25 currentX = 0 currentY = 0 #Settings Menu Draw.PushButton("Settings", 1, currentX + margin, margin, buttonWidth, buttonHeight, "Load, save and edit Pen-to-Material assignments") currentX = (currentX + buttonWidth + margin) #Pens Menu Draw.PushButton("Pens", 2, currentX + margin, margin, buttonWidth, buttonHeight, "Load, save and edit Pen attributes") currentX = (currentX + buttonWidth + margin) #Export Menu Draw.PushButton("Export", 3, currentX + margin, margin, buttonWidth, buttonHeight, "Export to image file or animation") currentX = (currentX + buttonWidth + margin) #About Menu Draw.PushButton("About", 4, currentX + margin, margin, buttonWidth, buttonHeight, "About Pantograph") currentX = (currentX + buttonWidth + margin) #Quit Draw.PushButton("Quit", 5, int(drawing.WIDTH) + margin - buttonWidth, margin, buttonWidth, buttonHeight, "Quit Pantograph") BGL.glRasterPos2i(margin, buttonHeight + 2*margin) BGL.glDrawPixels(int(drawing.WIDTH), int(drawing.HEIGHT), BGL.GL_RGB, BGL.GL_UNSIGNED_BYTE, imageBuffer) currentY = buttonHeight + 2*margin + int(drawing.HEIGHT) #Title Draw.Label(("Pantograph Vector Renderer " + GUI_VERSION), margin, currentY, 300, buttonHeight) def editMenu(drawing): global editState, imageBuffer, imageToggle, zoomFactor, mouseDrag, curMouseX, curMouseY, imageLocX, imageLocY, imageWidth, imageHeight, swatchDict, buttonDict margin = 5 buttonWidth = 75 buttonHeight = 25 currentX = 0 currentY = 0 #Settings Menu Draw.PushButton("Settings", 1, currentX + margin, margin, buttonWidth, buttonHeight, "Load, save and edit Pen-to-Material assignments") currentX = (currentX + buttonWidth + margin) #Pens Menu Draw.PushButton("Pens", 2, currentX + margin, margin, buttonWidth, buttonHeight, "Load, save and edit Pen attributes") currentX = (currentX + buttonWidth + margin) #Export Menu Draw.PushButton("Export", 3, currentX + margin, margin, buttonWidth, buttonHeight, "Export to image file or animation") currentX = (currentX + buttonWidth + margin) #About Menu Draw.PushButton("About", 4, currentX + margin, margin, buttonWidth, buttonHeight, "About Pantograph") currentX = (currentX + buttonWidth + margin) #Quit Draw.PushButton("Quit", 5, int(drawing.WIDTH) + margin - buttonWidth, margin, buttonWidth, buttonHeight, "Quit Pantograph") ###Edit Menu### myPen = drawing.settings.currentPen currentX = imageWidth + 2*margin currentY = imageHeight + buttonHeight + 2*margin margin = 5 buttonWidth = 125 buttonHeight = 15 #Title currentY = (currentY - 2*buttonHeight) Draw.PushButton(myPen.name, 10, currentX, currentY, buttonWidth, 2*buttonHeight, "Select a Pen") buttonHeight = swatchHeight buttonWidth = 125 #Line types for (lineType, callback) in zip(myPen.lineTypeList, range(11, 11+(8 * len(myPen.lineTypeList)), 8)): currentY = (currentY - buttonHeight - margin) Draw.PushButton(lineType.lower().capitalize(), callback, currentX, currentY, buttonWidth, buttonHeight, "Edit " + lineType.lower().capitalize() + " Line Attributes") #draw a swatch of the attribute if SWATCH_ON: mySwatch = cairoToImage(swatchDict[lineType], swatchWidth, swatchHeight) BGL.glRasterPos2i(currentX + buttonWidth, currentY) BGL.glDrawPixels(swatchWidth, swatchHeight, BGL.GL_RGB, BGL.GL_UNSIGNED_BYTE, mySwatch) if editState == lineType: buttonHeight = 25 buttonWidth = 150 currentX = currentX + margin currentY = (currentY - buttonHeight - margin) buttonDict[lineType]["visible"] = Draw.Toggle('Visible', callback + 1, currentX, currentY, buttonWidth, buttonHeight, int(myPen.attributeDict[lineType]["Visible"]), 'Turn ' + lineType.lower().capitalize() + ' line on and off ', setItem) #isVisible currentY = (currentY - 2*buttonHeight - margin) buttonDict[lineType]["lineColor"] = Draw.ColorPicker(callback + 2, currentX, currentY, buttonWidth, 2*buttonHeight, (float(myPen.attributeDict[lineType]["lineColor"].r),float(myPen.attributeDict[lineType]["lineColor"].g),float(myPen.attributeDict[lineType]["lineColor"].b)), 'Set the ' + lineType.lower().capitalize() + ' line color', setItem) #line color currentY = (currentY - buttonHeight - margin) buttonDict[lineType]["alpha"] = Draw.Number('Alpha', callback + 3, currentX, currentY, buttonWidth, buttonHeight, float(myPen.attributeDict[lineType]["lineColor"].a), 0.0, 1.0, 'Set the ' + lineType.lower().capitalize() + ' line alpha (transparency)', setItem) #line alpha currentY = (currentY - buttonHeight - margin) buttonDict[lineType]["lineWeight"] = Draw.Number('Line weight', callback + 4, currentX, currentY, buttonWidth, buttonHeight, float(myPen.attributeDict[lineType]["lineWidth"]), 0.0, 10.0, 'Set the ' + lineType.lower().capitalize() + ' line weight', setItem) #line weight currentY = (currentY - buttonHeight - margin) if myPen.attributeDict[lineType]["lineDash"] == Pen.DASH: defaultDash = 1 elif myPen.attributeDict[lineType]["lineDash"] == Pen.DOTDASH: defaultDash = 2 elif myPen.attributeDict[lineType]["lineDash"] == Pen.DOT: defaultDash = 3 elif myPen.attributeDict[lineType]["lineDash"] == Pen.SOLID: defaultDash = 4 buttonDict[lineType]["lineDash"] = Draw.Menu('Line dash:%t|Dash|Dot-Dash|Dot|Solid', callback + 5, currentX, currentY, buttonWidth, buttonHeight, defaultDash, 'Choose a line dash type', setItem) currentY = (currentY - buttonHeight - margin) if myPen.attributeDict[lineType]["lineCap"] == Pen.BUTT: defaultCap = 1 elif myPen.attributeDict[lineType]["lineCap"] == Pen.ROUND: defaultCap = 2 elif myPen.attributeDict[lineType]["lineCap"] == Pen.SQUARE: defaultCap = 3 buttonDict[lineType]["lineCap"] = Draw.Menu('Line cap:%t|Butt|Round|Square', callback + 6, currentX, currentY, buttonWidth, buttonHeight, defaultCap, 'Choose a line cap type', setItem) currentY = (currentY - buttonHeight - margin) if myPen.attributeDict[lineType]["lineJoin"] == Pen.MITER: defaultJoin = 1 elif myPen.attributeDict[lineType]["lineJoin"] == Pen.FILLET: defaultJoin = 2 elif myPen.attributeDict[lineType]["lineJoin"] == Pen.BEVEL: defaultJoin = 3 buttonDict[lineType]["lineJoin"] = Draw.Menu('Line join:%t|Miter|Fillet|Bevel', callback + 7, currentX, currentY, buttonWidth, buttonHeight, defaultJoin, 'Choose a line join type', setItem) buttonHeight = swatchHeight buttonWidth = 125 currentX = currentX - margin #Fill currentY = (currentY - buttonHeight - margin) Draw.PushButton("Fill", 67, currentX, currentY, buttonWidth, buttonHeight, "Edit Fill Attributes") #draw a swatch of the attribute if SWATCH_ON: mySwatch = cairoToImage(swatchDict["FILL"], swatchWidth, swatchHeight) BGL.glRasterPos2i(currentX + buttonWidth, currentY) BGL.glDrawPixels(swatchWidth, swatchHeight, BGL.GL_RGB, BGL.GL_BYTE, mySwatch) if editState == "FILL": buttonHeight = 25 buttonWidth = 150 currentX = currentX + margin currentY = (currentY - 2*buttonHeight - margin) buttonDict["fillColor"] = Draw.ColorPicker(68, currentX, currentY, buttonWidth, 2*buttonHeight, (float(myPen.attributeDict["FILLCOLOR"].r),float(myPen.attributeDict["FILLCOLOR"].g),float(myPen.attributeDict["FILLCOLOR"].b)), 'Set the material line color', setItem) #fill color currentY = (currentY - buttonHeight - margin) buttonDict["fillAlpha"] = Draw.Number('Alpha', 69, currentX, currentY, buttonWidth, buttonHeight, float(myPen.attributeDict["FILLCOLOR"].a), 0.0, 1.0, 'Set the fill alpha (transparency)', setItem) #fill alpha currentY = (currentY - buttonHeight - margin) buttonDict["fillToggle"] = Draw.Toggle('Raster Fill', 70, currentX, currentY, buttonWidth, buttonHeight, myPen.attributeDict["FILLRASTER"]["toggle"], 'Set the fill to a raster file', setItem) #fill toggle if myPen.attributeDict["FILLRASTER"]["toggle"]: currentY = (currentY - buttonHeight - margin) buttonDict["fillFilename"] = Draw.PushButton('Select Raster file', 71, currentX, currentY, buttonWidth, buttonHeight, 'Select the file for the raster fill') #fill filename buttonHeight = 15 buttonWidth = 125 currentX = currentX - margin #Global Silhouette currentY = (currentY - buttonHeight - margin) Draw.PushButton("Global Silhouette", 72, currentX, currentY, buttonWidth, buttonHeight, "Edit Global Silhouette Line Attributes") #draw a swatch of the attribute if SWATCH_ON: mySwatch = cairoToImage(swatchDict["GLOBAL SILHOUETTE"], swatchWidth, swatchHeight) #mySwatch = BGL.Buffer(BGL.GL_BYTE, [swatchHeight * swatchWidth, 3], myBuffer) BGL.glRasterPos2i(currentX + buttonWidth, currentY) BGL.glDrawPixels(swatchWidth, swatchHeight, BGL.GL_RGB, BGL.GL_BYTE, mySwatch) if editState == "GLOBAL SILHOUETTE": buttonHeight = 25 buttonWidth = 150 currentX = currentX + margin currentY = (currentY - buttonHeight - margin) buttonDict["globalLineVisible"] = Draw.Toggle('Visible', 73, currentX, currentY, buttonWidth, buttonHeight, int(drawing.settings.globalLineVisible), 'Turn Global Silhouette line on and off ', setItem) #isVisible currentY = (currentY - 2*buttonHeight - margin) buttonDict["globalLineColor"] = Draw.ColorPicker(74, currentX, currentY, buttonWidth, 2*buttonHeight, (float(drawing.settings.globalLineColor.r),float(drawing.settings.globalLineColor.g),float(drawing.settings.globalLineColor.b)), 'Set the Global Silhouette line color', setItem) #line color currentY = (currentY - buttonHeight - margin) buttonDict["globalLineAlpha"] = Draw.Number('Alpha', 75, currentX, currentY, buttonWidth, buttonHeight, float(drawing.settings.globalLineColor.a), 0.0, 1.0, 'Set the Global Silhouette line alpha (transparency)', setItem) #line alpha currentY = (currentY - buttonHeight - margin) buttonDict["globalLineWidth"] = Draw.Number('Line weight', 76, currentX, currentY, buttonWidth, buttonHeight, float(drawing.settings.globalLineWidth), 0.0, 10.0, 'Set the Global Silhouette line weight', setItem) #line weight currentY = (currentY - buttonHeight - margin) if drawing.settings.globalLineDash == Pen.DASH: defaultGlobalDash = 1 elif drawing.settings.globalLineDash == Pen.DOTDASH: defaultGlobalDash = 2 elif drawing.settings.globalLineDash == Pen.DOT: defaultGlobalDash = 3 elif drawing.settings.globalLineDash == Pen.SOLID: defaultGlobalDash = 4 buttonDict["globalLineDash"] = Draw.Menu('Line dash:%t|Dash|Dot-Dash|Dot|Solid', 77, currentX, currentY, buttonWidth, buttonHeight, defaultGlobalDash, 'Choose a line dash type', setItem) currentY = (currentY - buttonHeight - margin) if drawing.settings.globalLineCap == Pen.BUTT: defaultGlobalCap = 1 elif drawing.settings.globalLineCap == Pen.ROUND: defaultGlobalCap = 2 elif drawing.settings.globalLineCap == Pen.SQUARE: defaultGlobalCap = 3 buttonDict["globalLineCap"] = Draw.Menu('Line cap:%t|Butt|Round|Square', 78, currentX, currentY, buttonWidth, buttonHeight, defaultGlobalCap, 'Choose a line cap type', setItem) currentY = (currentY - buttonHeight - margin) if drawing.settings.globalLineJoin == Pen.MITER: defaultGlobalJoin = 1 elif drawing.settings.globalLineJoin == Pen.FILLET: defaultGlobalJoin = 2 elif drawing.settings.globalLineJoin == Pen.BEVEL: defaultGlobalJoin = 3 buttonDict["globalLineJoin"] = Draw.Menu('Line join:%t|Miter|Fillet|Bevel', 79, currentX, currentY, buttonWidth, buttonHeight, defaultGlobalJoin, 'Choose a line join type', setItem) buttonHeight = swatchHeight buttonWidth = 125 currentX = currentX - margin #Done currentY = (currentY - 2*buttonHeight - 2*margin) Draw.PushButton("Done", 100, currentX, currentY, buttonWidth, 2*buttonHeight, "Complete Changes") margin = 5 buttonWidth = 75 buttonHeight = 25 currentX = 0 currentY = 0 #Image BGL.glRasterPos2i(margin, buttonHeight + 2*margin) BGL.glDrawPixels(int(drawing.WIDTH), int(drawing.HEIGHT), BGL.GL_RGB, BGL.GL_UNSIGNED_BYTE, imageBuffer) currentY = buttonHeight + 2*margin + drawing.HEIGHT #Title Draw.Label(("Pantograph Vector Renderer " + GUI_VERSION), margin, int(currentY), 300, buttonHeight) def fileOpen(fileName): print 'The selected file was:', fileName def export(fileName): global drawing root = Blender.sys.splitext(fileName)[0] extension = Blender.sys.splitext(fileName)[1] debug(extension) if extension == '.svg': drawing.render(drawing.WIDTH, drawing.HEIGHT, fileName, canvas = 'svg') elif extension == '.swf': drawing.settings.loadDefaultSettings() #get the frame info from Blender blenderScene = Blender.Scene.GetCurrent() blenderRender = blenderScene.getRenderingContext() startFrame = blenderRender.sFrame endFrame = blenderRender.eFrame frameRate = blenderRender.fps frameWidth = blenderRender.sizeX frameHeight = blenderRender.sizeY #make a new flash movie movie = ming.SWFMovie() movie.setDimension(frameWidth,frameHeight) movie.setRate(frameRate) movie.setNumberOfFrames(endFrame-startFrame + 1) #render frames to the movie movieClip = ming.SWFMovieClip() for frame in range(startFrame, endFrame + 1): drawing.scene = Scene() drawing.drawingQueue = [] #drawing.shapes = list() blender2Pantograph(drawing, frame) buildConnectivity(drawing) makeFrustum(drawing.scene) doVignettes(drawing.scene) doCutaways(drawing.scene) (drawing.visiblePolygons, drawing.hiddenPolygons) = occludeAndCull(drawing) drawing.drawingQueue = BSPSort(drawing.scene, drawing.visiblePolygons) clipAndCombine(drawing) drawing.renderMovie(movieClip) movieClip.nextFrame() #output the movie to the given file movie.add(movieClip) #movie.nextFrame() movie.save(fileName) elif extension == '.pdf': drawing.render(drawing.WIDTH, drawing.HEIGHT, fileName, canvas = 'pdf') elif extension == '.png': drawing.render(drawing.WIDTH, drawing.HEIGHT, fileName, canvas = 'png') else: #we default to an svg file if we get an extension we don't recognize drawing.render(drawing.WIDTH, drawing.HEIGHT, root + '.svg', canvas = 'svg') drawing.settings.currentExportFolder = Blender.sys.dirname(fileName) def saveSettings(fileName): global drawing root = Blender.sys.splitext(fileName)[0] extension = Blender.sys.splitext(fileName)[1] if extension == '.pog': drawing.settings.save(fileName) else: drawing.settings.save(root + '.pog') drawing.settings.currentSettingsFolder = Blender.sys.dirname(fileName) def loadSettings(fileName): global drawing, imageBuffer root = Blender.sys.splitext(fileName)[0] extension = Blender.sys.splitext(fileName)[1] if extension == '.pog': drawing.settings.load(fileName) else: progress('File is not a Pantograph settings file (.pog)!') drawing.settings.currentSettingsFolder = Blender.sys.dirname(fileName) cairoSurface = drawing.render(drawing.WIDTH, drawing.HEIGHT) imageBuffer = cairoToImage(cairoSurface, drawing.WIDTH, drawing.HEIGHT) Draw.Redraw(1) def savePen(fileName): global drawing root = Blender.sys.splitext(fileName)[0] extension = Blender.sys.splitext(fileName)[1] if extension == '.pen': drawing.settings.savePen(fileName, drawing.settings.currentPen) else: drawing.settings.savePen(root + '.pen', drawing.settings.currentPen) drawing.settings.currentSettingsFolder = Blender.sys.dirname(fileName) def loadPen(fileName): global drawing, imageBuffer root = Blender.sys.splitext(fileName)[0] extension = Blender.sys.splitext(fileName)[1] if extension == '.pen': drawing.settings.loadPen(fileName) else: progress('File is not a Pantograph settings file (.pen)!') drawing.settings.currentSettingsFolder = Blender.sys.dirname(fileName) cairoSurface = drawing.render(drawing.WIDTH, drawing.HEIGHT) imageBuffer = cairoToImage(cairoSurface, drawing.WIDTH, drawing.HEIGHT) Draw.Redraw(1) def loadRaster(fileName): global drawing, imageBuffer root = Blender.sys.splitext(fileName)[0] extension = Blender.sys.splitext(fileName)[1] if extension == '.png': drawing.settings.currentPen.attributeDict["FILLRASTER"]["filename"] = fileName drawing.settings.currentSettingsFolder = Blender.sys.dirname(fileName) cairoSurface = drawing.render(drawing.WIDTH, drawing.HEIGHT) imageBuffer = cairoToImage(cairoSurface, drawing.WIDTH, drawing.HEIGHT) Draw.Redraw(1) else: progress('File is not a Pantograph settings file (.pen)!') def applyMaterialToPen(material, pen): global drawing, imageBuffer drawing.settings.pens[material] = pen cairoSurface = drawing.render(drawing.WIDTH, drawing.HEIGHT) imageBuffer = cairoToImage(cairoSurface, drawing.WIDTH, drawing.HEIGHT) Draw.Redraw(1) def setItem(event, value): global drawing, imageBuffer myPen = drawing.settings.currentPen #We need to unpack the same sequence of callbacks as the editMenu, and use them to set the currentPen settings for (lineType, callback) in zip(myPen.lineTypeList, range(11, 11+(8 * len(myPen.lineTypeList)), 8)): #callback is the title button - not used here if event == callback + 1: myPen.attributeDict[lineType]["Visible"] = value elif event == callback + 2: (myPen.attributeDict[lineType]["lineColor"].r, myPen.attributeDict[lineType]["lineColor"].g, myPen.attributeDict[lineType]["lineColor"].b) = value elif event == callback + 3: myPen.attributeDict[lineType]["lineColor"].a = value elif event == callback + 4: myPen.attributeDict[lineType]["lineWidth"] = value elif event == callback + 5: if value == 1: myPen.attributeDict[lineType]["lineDash"] = copy(Pen.DASH) elif value == 2: myPen.attributeDict[lineType]["lineDash"] = copy(Pen.DOTDASH) elif value == 3: myPen.attributeDict[lineType]["lineDash"] = copy(Pen.DOT) elif value == 4: myPen.attributeDict[lineType]["lineDash"] = copy(Pen.SOLID) elif event == callback + 6: if value == 1: myPen.attributeDict[lineType]["lineCap"] = copy(Pen.BUTT) elif value == 2: myPen.attributeDict[lineType]["lineCap"] = copy(Pen.ROUND) elif value == 3: myPen.attributeDict[lineType]["lineCap"] = copy(Pen.SQUARE) elif event == callback + 7: if value == 1: myPen.attributeDict[lineType]["lineJoin"] = copy(Pen.MITER) elif value == 2: myPen.attributeDict[lineType]["lineJoin"] = copy(Pen.FILLET) elif value == 3: myPen.attributeDict[lineType]["lineJoin"] = copy(Pen.BEVEL) #Fillcolor #67 is the title button - not used here if event == 68: (myPen.attributeDict["FILLCOLOR"].r, myPen.attributeDict["FILLCOLOR"].g, myPen.attributeDict["FILLCOLOR"].b) = value elif event == 69: myPen.attributeDict["FILLCOLOR"].a = float(value) elif event == 70: myPen.attributeDict["FILLRASTER"]["toggle"] = value #Global Silhouette #72 is the title button - not used here elif event == 73: drawing.settings.globalLineVisible = value elif event == 74: (drawing.settings.globalLineColor.r, drawing.settings.globalLineColor.g, drawing.settings.globalLineColor.b) = value elif event == 75: drawing.settings.globalLineColor.a = value elif event == 76: drawing.settings.globalLineWidth = value elif event == 77: if value == 1: drawing.settings.globalLineDash = copy(Pen.DASH) elif value == 2: drawing.settings.globalLineDash = copy(Pen.DOTDASH) elif value == 3: drawing.settings.globalLineDash = copy(Pen.DOT) elif value == 4: drawing.settings.globalLineDash = copy(Pen.SOLID) elif event == 78: if value == 1: drawing.settings.globalLineCap = copy(Pen.BUTT) elif value == 2: drawing.settings.globalLineCap = copy(Pen.ROUND) elif value == 3: drawing.settings.globalLineCap = copy(Pen.SQUARE) elif event == 79: if value == 1: drawing.settings.globalLineJoin = copy(Pen.MITER) elif value == 2: drawing.settings.globalLineJoin = copy(Pen.FILLET) elif value == 3: drawing.settings.globalLineJoin = copy(Pen.BEVEL) cairoSurface = drawing.render(drawing.WIDTH, drawing.HEIGHT) imageBuffer = cairoToImage(cairoSurface, drawing.WIDTH, drawing.HEIGHT) def cairoToImage(imageSurface, width, height): cairoData = imageSurface.get_data() myData = [cairoData[int(i*width*4):int((i+1)*width*4)] for i in range(0,int(len(cairoData)/(width*4)))] myData.reverse() myFlippedData = [item for row in myData for item in row] myBuffer = BGL.Buffer(BGL.GL_BYTE, [len(myFlippedData)/4, 3], [[ord(myFlippedData[i+2]),ord(myFlippedData[i+1]),ord(myFlippedData[i+0])] for i in range(0,len(myFlippedData),4)]) return myBuffer def gui(): global menuState, editState, progressImage, drawing BGL.glClearColor(BACKGROUNDCOLOR[0],BACKGROUNDCOLOR[1],BACKGROUNDCOLOR[2],BACKGROUNDCOLOR[3]) BGL.glClear(BGL.GL_COLOR_BUFFER_BIT) if not drawing: drawing = Drawing() if menuState == "PRERENDER": (drawing.settings.USE_ALPHA, drawing.settings.CULL_BACKFACES, drawing.settings.AUTO_CREASE, drawing.settings.LOAD_PREVIOUS_SETTINGS) = preRenderMenu() Window.WaitCursor(1) if drawing.settings.LOAD_PREVIOUS_SETTINGS: progress('Loading previous settings...') drawing.settings.loadDefaultSettings() menuState = "PROGRESS" elif menuState == "PROGRESS" or menuState == "DONOTHING": progressMenu(drawing) debug('mark 3', menuState) elif menuState == "REVIEW": Window.WaitCursor(0) reviewMenu(drawing) Draw.Redraw(1) elif menuState == "EDIT": editMenu(drawing) #---MAIN---#000000#FFFFFF------------------------------------------------------- def main(): menuState = "PRERENDER" Draw.Register(gui, None, button_event) if __name__ == '__main__': main()