diff options
Diffstat (limited to 'release/scripts/mesh_unfolder.py')
-rw-r--r-- | release/scripts/mesh_unfolder.py | 1582 |
1 files changed, 0 insertions, 1582 deletions
diff --git a/release/scripts/mesh_unfolder.py b/release/scripts/mesh_unfolder.py deleted file mode 100644 index f5c19a92bd0..00000000000 --- a/release/scripts/mesh_unfolder.py +++ /dev/null @@ -1,1582 +0,0 @@ -#!BPY -""" -Name: 'Unfold' -Blender: 245 -Group: 'Mesh' -Tip: 'Unfold meshes to create nets' -Version: v2.5 -Author: Matthew Chadwick -""" -import Blender -from Blender import * -from Blender.Mathutils import * -try: - import sys - import traceback - import math - import re - from math import * - import sys - import random - import xml.sax, xml.sax.handler, xml.sax.saxutils - - # annoying but need so classes dont raise errors - xml_sax_handler_ContentHandler = xml.sax.handler.ContentHandler - -except: - Draw.PupMenu('Error%t|A full python installation is required to run this script.') - xml = None - xml_sax_handler_ContentHandler = type(0) - -__author__ = 'Matthew Chadwick' -__version__ = '2.5 06102007' -__url__ = ["http://celeriac.net/unfolder/", "blender", "blenderartist"] -__email__ = ["post at cele[remove this text]riac.net", "scripts"] -__bpydoc__ = """\ - -Mesh Unfolder - -Unfolds the selected mesh onto a plane to form a net - -Not all meshes can be unfolded - -Meshes must be free of holes, -isolated edges (not part of a face), twisted quads and other rubbish. -Nice clean triangulated meshes unfold best - -This program is free software; you can distribute it and/or modify it under the terms -of the GNU General Public License as published by the Free Software Foundation; version 2 -or later, currently at http://www.gnu.org/copyleft/gpl.html - -The idea came while I was riding a bike. -""" - -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# ***** END GPL LICENCE BLOCK ***** - -# Face lookup -class FacesAndEdges: - def __init__(self, mesh): - self.nfaces = 0 - # straight from the documentation - self.edgeFaces = dict([(edge.key, []) for edge in mesh.edges]) - for face in mesh.faces: - face.sel = False - for key in face.edge_keys: - self.edgeFaces[key].append(face) - def findTakenAdjacentFace(self, bface, edge): - return self.findAdjacentFace(bface, edge) - # find the first untaken (non-selected) adjacent face in the list of adjacent faces for the given edge (allows for manifold meshes too) - def findAdjacentFace(self, bface, edge): - faces = self.edgeFaces[edge.key()] - for i in xrange(len(faces)): - if faces[i] == bface: - j = (i+1) % len(faces) - while(faces[j]!=bface): - if faces[j].sel == False: - return faces[j] - j = (j+1) % len(faces) - return None - def returnFace(self, face): - face.sel = False - self.nfaces-=1 - def facesTaken(self): - return self.nfaces - def takeAdjacentFace(self, bface, edge): - if (edge==None): - return None - face = self.findAdjacentFace(bface, edge) - if(face!=None): - face.sel = True - self.nfaces+=1 - return face - def takeFace(self, bface): - if(bface!=None): - bface.sel= True - self.nfaces+=1 - - -# A fold between two faces with a common edge -class Fold: - ids = -1 - def __init__(self, parent, refPoly, poly, edge, angle=None): - Fold.ids+=1 - self.id = Fold.ids - self.refPoly = refPoly - self.poly = poly - self.srcFace = None - self.desFace = None - self.edge = edge - self.foldedEdge = edge - self.rm = None - self.parent = parent - self.tree = None - if(refPoly!=None): - self.refPolyNormal = refPoly.normal() - self.polyNormal = poly.normal() - if(angle==None): - self.angle = self.calculateAngle() - self.foldingPoly = poly.rotated(edge, self.angle) - else: - self.angle = angle - self.foldingPoly = poly - self.unfoldedEdge = self.edge - self.unfoldedNormal = None - self.animAngle = self.angle - self.cr = None - self.nancestors = None - def reset(self): - self.foldingPoly = self.poly.rotated(self.edge, self.dihedralAngle()) - def getID(self): - return self.id - def getParent(self): - return self.parent - def ancestors(self): - if(self.nancestors==None): - self.nancestors = self.computeAncestors() - return self.nancestors - def computeAncestors(self): - if(self.parent==None): - return 0 - else: - return self.parent.ancestors()+1 - def dihedralAngle(self): - return self.angle - def unfoldTo(self, f): - self.animAngle = self.angle*f - self.foldingPoly = self.poly.rotated(self.edge, self.animAngle) - def calculateAngle(self): - sangle = Mathutils.AngleBetweenVecs(self.refPolyNormal, self.polyNormal) - if(sangle!=sangle): - sangle=0.0 - ncp = self.refPolyNormal.cross(self.polyNormal) - dp = ncp.dot(self.edge.vector) - if(dp>0.0): - return +sangle - else: - return -sangle - def alignWithParent(self): - pass - def unfoldedNormal(self): - return self.unfoldedNormal - def getEdge(self): - return self.edge - def getFace(self): - return self.poly - def testFace(self): - return Poly.fromVectors([self.edge.v1, self.edge.v2, Vector([0,0,0])]) - def unfoldedFace(self): - return self.foldingPoly - def unfold(self): - if(self.parent!=None): - self.parent.foldFace(self) - def foldFace(self, child): - child.foldingPoly.rotate(self.edge, self.animAngle) - if(self.parent!=None): - self.parent.foldFace(child) - -class Cut(Fold): - pass - -# Trees build folds by traversing the mesh according to a local measure -class Tree: - def __init__(self, net, parent,fold,otherConstructor=None): - self.net = net - self.fold = fold - self.face = fold.srcFace - self.poly = Poly.fromBlenderFace(self.face) - self.generations = net.generations - self.growing = True - self.tooLong = False - self.parent = parent - self.grown = False - if not(otherConstructor): - self.edges = net.edgeIteratorClass(self) - def goodness(self): - return self.edges.goodness() - def compare(self, other): - if(self.goodness() > other.goodness()): - return +1 - else: - return -1 - def isGrowing(self): - return self.growing - def beGrowing(self): - self.growing = True - def grow(self): - self.tooLong = self.fold.ancestors()>self.generations - if(self.edges.hasNext() and self.growing): - edge = self.edges.next() - tface = self.net.facesAndEdges.takeAdjacentFace(self.face, edge) - if(tface!=None): - self.branch(tface, edge) - if(self.parent==None): - self.grow() - else: - self.grown = True - def isGrown(self): - return self.grown - def canGrow(self): - return (self.parent!=None and self.parent.grown) - def getNet(self): - return self.net - def getFold(self): - return self.fold - def getFace(self): - return self.face - def branch(self, tface, edge): - fold = Fold(self.fold, self.poly, Poly.fromBlenderFace(tface), edge) - fold.srcFace = tface - self.net.myFacesVisited+=1 - tree = Tree(self.net, self, fold) - fold.tree = tree - fold.unfold() - overlaps = self.net.checkOverlaps(fold) - nc = len(overlaps) - self.net.overlaps+=nc - if(nc>0 and self.net.avoidsOverlaps): - self.handleOverlap(fold, overlaps) - else: - self.addFace(fold) - def handleOverlap(self, fold, overlaps): - self.net.facesAndEdges.returnFace(fold.srcFace) - self.net.myFacesVisited-=1 - for cfold in overlaps: - ttree = cfold.tree - ttree.growing = True - ttree.grow() - def addFace(self, fold): - ff = fold.unfoldedFace() - fold.desFace = self.net.addFace(ff, fold.srcFace) - self.net.folds.append(fold) - self.net.addBranch(fold.tree) - fold.tree.growing = not(self.tooLong) - if(self.net.diffuse==False): - fold.tree.grow() - -# A Net is the result of the traversal of the mesh by Trees -class Net: - def __init__(self, src, des): - self.src = src - self.des = des - self.firstFace = None - self.firstPoly = None - self.refFold = None - self.edgeIteratorClass = RandomEdgeIterator - if(src!=None): - self.srcFaces = src.faces - self.facesAndEdges = FacesAndEdges(self.src) - self.myFacesVisited = 0 - self.facesAdded = 0 - self.folds = [] - self.cuts = [] - self.branches = [] - self.overlaps = 0 - self.avoidsOverlaps = True - self.frame = 1 - self.ff = 180.0 - self.firstFaceIndex = None - self.trees = 0 - self.foldIPO = None - self.perFoldIPO = None - self.IPOCurves = {} - self.generations = 128 - self.diffuse = True - self.noise = 0.0 - self.grownBranches = 0 - self.assignsUV = True - self.animates = False - self.showProgress = False - self.feedback = None - def setSelectedFaces(self, faces): - self.srcFaces = faces - self.facesAndEdges = FacesAndEdges(self.srcFaces) - def setShowProgress(self, show): - self.showProgress = show - # this method really needs work - def unfold(self): - selectedFaces = [face for face in self.src.faces if (self.src.faceUV and face.sel)] - if(self.avoidsOverlaps): - print "unfolding with overlap detection" - if(self.firstFaceIndex==None): - self.firstFaceIndex = random.randint(0, len(self.src.faces)-1) - else: - print "Using user-selected seed face ", self.firstFaceIndex - self.firstFace = self.src.faces[self.firstFaceIndex] - z = min([v.co.z for v in self.src.verts])-0.1 - ff = Poly.fromBlenderFace(self.firstFace) - if(len(ff.v)<3): - raise Exception("This mesh contains an isolated edge - it must consist only of faces") - testFace = Poly.fromVectors( [ Vector([0.0,0.0,0.0]), Vector([0.0,1.0,0.0]), Vector([1.0,1.0,0.0]) ] ) - # hmmm. I honestly can't remember why this needs to be done, but it does. - u=0 - v=1 - w=2 - if ff.v[u].x==ff.v[u+1].x and ff.v[u].y==ff.v[u+1].y: - u=1 - v=2 - w=0 - # here we make a couple of folds, not part of the net, which serve to get the net into the xy plane - xyFace = Poly.fromList( [ [ff.v[u].x,ff.v[u].y, z] , [ff.v[v].x,ff.v[v].y, z] , [ff.v[w].x+0.1,ff.v[w].y+0.1, z] ] ) - refFace = Poly.fromVectors([ ff.v[u], ff.v[v], xyFace.v[1], xyFace.v[0] ] ) - xyFold = Fold(None, xyFace, refFace, Edge(xyFace.v[0], xyFace.v[1] )) - self.refFold = Fold(xyFold, refFace, ff, Edge(refFace.v[0], refFace.v[1] )) - self.refFold.srcFace = self.firstFace - # prepare to grow the trees - trunk = Tree(self, None, self.refFold) - trunk.generations = self.generations - self.firstPoly = ff - self.facesAndEdges.takeFace(self.firstFace) - self.myFacesVisited+=1 - self.refFold.unfold() - self.refFold.tree = trunk - self.refFold.desFace = self.addFace(self.refFold.unfoldedFace(), self.refFold.srcFace) - self.folds.append(self.refFold) - trunk.grow() - i = 0 - # keep the trees growing while they can - while(self.myFacesVisited<len(self.src.faces) and len(self.branches) > 0): - if self.edgeIteratorClass==RandomEdgeIterator: - i = random.randint(0,len(self.branches)-1) - tree = self.branches[i] - if(tree.isGrown()): - self.branches.pop(i) - else: - tree.beGrowing() - if(tree.canGrow()): - tree.grow() - i = 0 - else: - i = (i + 1) % len(self.branches) - if self.src.faceUV: - for face in self.src.faces: - face.sel = False - for face in selectedFaces: - face.sel = True - self.src.update() - Window.RedrawAll() - def assignUVs(self): - for fold in self.folds: - self.assignUV(fold.srcFace, fold.unfoldedFace()) - print " assigned uv to ", len(self.folds), len(self.src.faces) - self.src.update() - def checkOverlaps(self, fold): - #return self.getOverlapsBetween(fold, self.folds) - return self.getOverlapsBetweenGL(fold, self.folds) - def getOverlapsBetween(self, fold, folds): - if(fold.parent==None): - return [] - mf = fold.unfoldedFace() - c = [] - for afold in folds: - mdf = afold.unfoldedFace() - if(afold!=fold): - # currently need to get agreement from both polys because - # a touch by a vertex of one the other's edge is acceptable & - # they disagree on that - intersects = mf.intersects2D(mdf) and mdf.intersects2D(mf) - inside = ( mdf.containsAnyOf(mf) or mf.containsAnyOf(mdf) ) - if( intersects or inside or mdf.overlays(mf)): - c.append(afold) - return c - def getOverlapsBetweenGL(self, fold, folds): - b = fold.unfoldedFace().bounds() - polys = len(folds)*4+16 # the buffer is nhits, mindepth, maxdepth, name - buffer = BGL.Buffer(BGL.GL_INT, polys) - BGL.glSelectBuffer(polys, buffer) - BGL.glRenderMode(BGL.GL_SELECT) - BGL.glInitNames() - BGL.glPushName(0) - BGL.glPushMatrix() - BGL.glMatrixMode(BGL.GL_PROJECTION) - BGL.glLoadIdentity() - BGL.glOrtho(b[0].x, b[1].x, b[1].y, b[0].y, 0.0, 10.0) - #clip = BGL.Buffer(BGL.GL_FLOAT, 4) - #clip.list = [0,0,0,0] - #BGL.glClipPlane(BGL.GL_CLIP_PLANE1, clip) - # could use clipping planes here too - BGL.glMatrixMode(BGL.GL_MODELVIEW) - BGL.glLoadIdentity() - bx = (b[1].x - b[0].x) - by = (b[1].y - b[0].y) - cx = bx / 2.0 - cy = by / 2.0 - for f in xrange(len(folds)): - afold = folds[f] - if(fold!=afold): - BGL.glLoadName(f) - BGL.glBegin(BGL.GL_LINE_LOOP) - for v in afold.unfoldedFace().v: - BGL.glVertex2f(v.x, v.y) - BGL.glEnd() - BGL.glPopMatrix() - BGL.glFlush() - hits = BGL.glRenderMode(BGL.GL_RENDER) - buffer = [buffer[i] for i in xrange(3, 4*hits, 4)] - o = [folds[buffer[i]] for i in xrange(len(buffer))] - return self.getOverlapsBetween(fold, o) - def colourFace(self, face, cr): - for c in face.col: - c.r = int(cr[0]) - c.g = int(cr[1]) - c.b = int(cr[2]) - c.a = int(cr[3]) - self.src.update() - def setAvoidsOverlaps(self, avoids): - self.avoidsOverlaps = avoids - def addBranch(self, branch): - self.branches.append(branch) - if self.edgeIteratorClass!=RandomEdgeIterator: - self.branches.sort(lambda b1, b2: b1.compare(b2)) - def srcSize(self): - return len(self.src.faces) - def nBranches(self): - return len(self.branches) - def facesCreated(self): - return len(self.des.faces) - def facesVisited(self): - return self.myFacesVisited - def getOverlaps(self): - return self.overlaps - def sortOutIPOSource(self): - print "Sorting out IPO" - if self.foldIPO!=None: - return - o = None - try: - o = Blender.Object.Get("FoldRate") - except: - o = Blender.Object.New("Empty", "FoldRate") - Blender.Scene.GetCurrent().objects.link(o) - if(o.getIpo()==None): - ipo = Blender.Ipo.New("Object", "FoldRateIPO") - z = ipo.addCurve("RotZ") - print " added RotZ IPO curve" - z.addBezier((1,0)) - # again, why is this 10x out ? - z.addBezier((180, self.ff/10.0)) - z.addBezier((361, 0.0)) - o.setIpo(ipo) - z.recalc() - z.setInterpolation("Bezier") - z.setExtrapolation("Cyclic") - self.setIPOSource(o) - print " added IPO source" - def setIPOSource(self, object): - try: - self.foldIPO = object - for i in xrange(self.foldIPO.getIpo().getNcurves()): - self.IPOCurves[self.foldIPO.getIpo().getCurves()[i].getName()] = i - print " added ", self.foldIPO.getIpo().getCurves()[i].getName() - except: - print "Problem setting IPO object" - print sys.exc_info()[1] - traceback.print_exc(file=sys.stdout) - def setFoldFactor(self, ff): - self.ff = ff - def sayTree(self): - for fold in self.folds: - if(fold.getParent()!=None): - print fold.getID(), fold.dihedralAngle(), fold.getParent().getID() - def report(self): - p = int(float(self.myFacesVisited)/float(len(self.src.faces)) * 100) - print str(p) + "% unfolded" - print "faces created:", self.facesCreated() - print "faces visited:", self.facesVisited() - print "originalfaces:", len(self.src.faces) - n=0 - if(self.avoidsOverlaps): - print "net avoided at least ", self.getOverlaps(), " overlaps ", - n = len(self.src.faces) - self.facesCreated() - if(n>0): - print "but was unable to avoid ", n, " overlaps. Incomplete net." - else: - print "- A complete net." - else: - print "net has at least ", self.getOverlaps(), " collision(s)" - return n - # fold all my folds to a fraction of their total fold angle - def unfoldToCurrentFrame(self): - self.unfoldTo(Blender.Scene.GetCurrent().getRenderingContext().currentFrame()) - def unfoldTo(self, frame): - frames = Blender.Scene.GetCurrent().getRenderingContext().endFrame() - if(self.foldIPO!=None and self.foldIPO.getIpo()!=None): - f = self.foldIPO.getIpo().EvaluateCurveOn(self.IPOCurves["RotZ"],frame) - # err, this number seems to be 10x less than it ought to be - fff = 1.0 - (f*10.0 / self.ff) - else: - fff = 1.0-((frame)/(frames*1.0)) - for fold in self.folds: - fold.unfoldTo(fff) - for fold in self.folds: - fold.unfold() - tface = fold.unfoldedFace() - bface = fold.desFace - i = 0 - for v in bface.verts: - v.co.x = tface.v[i].x - v.co.y = tface.v[i].y - v.co.z = tface.v[i].z - i+=1 - Window.Redraw(Window.Types.VIEW3D) - return None - def addFace(self, poly, originalFace=None): - originalLength = len(self.des.verts) - self.des.verts.extend([Vector(vv.x, vv.y, vv.z) for vv in poly.v]) - self.des.faces.extend([ range(originalLength, originalLength + poly.size()) ]) - newFace = self.des.faces[len(self.des.faces)-1] - newFace.uv = [vv for vv in poly.v] - if(originalFace!=None and self.src.vertexColors): - newFace.col = [c for c in originalFace.col] - if(self.feedback!=None): - pu = str(int(self.fractionUnfolded() * 100))+"% unfolded" - howMuchDone = str(self.myFacesVisited)+" of "+str(len(self.src.faces))+" "+pu - self.feedback.say(howMuchDone) - #Window.DrawProgressBar (p, pu) - if(self.showProgress): - Window.Redraw(Window.Types.VIEW3D) - return newFace - def fractionUnfolded(self): - return float(self.myFacesVisited)/float(len(self.src.faces)) - def assignUV(self, face, uv): - face.uv = [Vector(v.x, v.y) for v in uv.v] - def unfoldAll(feedback=None): - objects = Blender.Object.Get() - for object in objects: - if(object.getType()=='Mesh' and not(object.getName().endswith("_net")) and len(object.getData(False, True).faces)>1): - net = Net.createNet(object, feedback) - net.searchForUnfolding() - svg = SVGExporter(net, object.getName()+".svg") - svg.export() - unfoldAll = staticmethod(unfoldAll) - def searchForUnfolding(self, limit=-1): - overlaps = 1 - attempts = 0 - while(overlaps > 0 or attempts<limit): - self.unfold() - overlaps = self.report() - attempts+=1 - return attempts - def fromSelected(feedback=None, netName=None): - return Net.createNet(Blender.Object.GetSelected()[0], feedback, netName) - fromSelected = staticmethod(fromSelected) - def clone(self, object=None): - if(object==None): - object = self.object - net = Net.createNet(object, self.feedback) - net.avoidsOverlaps = net.avoidsOverlaps - return net - def createNet(ob, feedback=None, netName=None): - mesh = ob.getData(mesh=1) - netObject = None - if(netName==None): - netName = ob.name[0:16]+"_net" - try: - netObject = Blender.Object.Get(netName) - netMesh = netObject.getData(False, True) - if(netMesh!=None): - netMesh.verts = None # clear the mesh - else: - netObject = Blender.Object.New("Mesh", netName) - except: - if(netObject==None): - netObject = Blender.Object.New("Mesh", netName) - netMesh = netObject.getData(False, True) # True means "as a Mesh not an NMesh" - try: - Blender.Scene.GetCurrent().objects.link(netObject) - except: - pass - try: - netMesh.materials = mesh.materials - netMesh.vertexColors = True - except: - print "Problem setting materials here" - net = Net(mesh, netMesh) - if mesh.faceUV and mesh.activeFace>=0 and (mesh.faces[mesh.activeFace].sel): - net.firstFaceIndex = mesh.activeFace - net.object = ob - net.feedback = feedback - return net - createNet = staticmethod(createNet) - def importNet(filename): - netName = filename.rstrip(".svg").replace("\\","/") - netName = netName[netName.rfind("/")+1:] - try: - netObject = Blender.Object.Get(netName) - except: - netObject = Blender.Object.New("Mesh", netName) - netObject.getData(mesh=1).name = netName - try: - Blender.Scene.GetCurrent().objects.link(netObject) - except: - pass - net = Net(None, netObject.getData(mesh=1)) - handler = NetHandler(net) - xml.sax.parse(filename, handler) - Window.Redraw(Window.Types.VIEW3D) - return net - importNet = staticmethod(importNet) - def getSourceMesh(self): - return self.src - -# determines the order in which to visit faces according to a local measure -class EdgeIterator: - def __init__(self, branch, otherConstructor=None): - self.branch = branch - self.bface = branch.getFace() - self.edge = branch.getFold().getEdge() - self.net = branch.getNet() - self.n = len(self.bface) - self.edges = [] - self.i = 0 - self.gooodness = 0 - self.createEdges() - self.computeGoodness() - if(otherConstructor==None): - self.sequenceEdges() - def createEdges(self): - edge = None - e = Edge.edgesOfBlenderFace(self.net.getSourceMesh(), self.bface) - for edge in e: - if not(edge.isBlenderSeam() and edge!=self.edge): - self.edges.append(edge) - def sequenceEdges(self): - pass - def next(self): - edge = self.edges[self.i] - self.i+=1 - return edge - def size(self): - return len(self.edges) - def reset(self): - self.i = 0 - def hasNext(self): - return (self.i<len(self.edges)) - def goodness(self): - return self.gooodness - def computeGoodness(self): - self.gooodness = 0 - def rotate(self): - self.edges.append(self.edges.pop(0)) - -class RandomEdgeIterator(EdgeIterator): - def sequenceEdges(self): - random.seed() - random.shuffle(self.edges) - def goodness(self): - return random.randint(0, self.net.srcSize()) - - -class Largest(EdgeIterator): - def sequenceEdges(self): - for e in self.edges: - f = self.net.facesAndEdges.findAdjacentFace(self.bface, e) - if(f!=None): - e.setGoodness(f.area) - self.edges.sort(lambda e1, e2: -e1.compare(e2)) - def computeGoodness(self): - self.gooodness = self.bface.area - - -class Brightest(EdgeIterator): - def sequenceEdges(self): - for edge in self.edges: - f = self.net.facesAndEdges.findAdjacentFace(self.bface, edge) - if(f!=None): - b = 0 - if self.net.src.vertexColors: - for c in f.col: - b+=(c.g+c.r+c.b) - rc = float(random.randint(0, self.net.srcSize())) / float(self.net.srcSize()) / 100.0 - b+=rc - edge.setGoodness(b) - self.edges.sort(lambda e1, e2: e1.compare(e2)) - def computeGoodness(self): - g = 0 - if self.net.src.vertexColors: - for c in self.bface.col: - g+=(c.g+c.r+c.b) - self.gooodness = g - -class OddEven(EdgeIterator): - i = True - def sequenceEdges(self): - OddEven.i = not(OddEven.i) - if(OddEven.i): - self.edges.reverse() - -class Curvature(EdgeIterator): - def sequenceEdges(self): - p1 = Poly.fromBlenderFace(self.bface) - gg = 0.0 - for edge in self.edges: - f = self.net.facesAndEdges.findAdjacentFace(self.bface, edge) - if(f!=None): - p2 = Poly.fromBlenderFace(f) - fold = Fold(None, p1, p2, edge) - fold.srcFace = f - b = Tree(self.net, self.branch, fold, self) - c = Curvature(b, False) - g = c.goodness() - gg+=g - edge.setGoodness(g) - self.edges.sort(lambda e1, e2: e1.compare(e2)) - tg = (self.gooodness + gg) - rc = float(random.randint(0, self.net.srcSize())) / float(self.net.srcSize()) / 100.0 - if(tg!=0.0): - self.gooodness = self.gooodness + rc / tg - def computeGoodness(self): - g = 0 - for edge in self.edges: - f = self.net.facesAndEdges.findAdjacentFace(self.bface, edge) - if(f!=None): - p1 = Poly.fromBlenderFace(self.bface) - p2 = Poly.fromBlenderFace(f) - f = Fold(None, p1, p2, edge) - g += f.dihedralAngle() - self.gooodness = g - - -class Edge: - def __init__(self, v1=None, v2=None, mEdge=None, i=-1): - self.idx = i - if v1 and v2: - self.v1 = v1.copy() - self.v2 = v2.copy() - else: - self.v1 = mEdge.v1.co.copy() - self.v2 = mEdge.v2.co.copy() - self.v1n = -self.v1 - self.vector = self.v1-self.v2 - self.vector.resize3D() - self.vector.normalize() - self.bmEdge = mEdge - self.gooodness = 0.0 - def fromBlenderFace(mesh, bface, i): - if(i>len(bface)-1): - return None - if(i==len(bface)-1): - j = 0 - else: - j = i+1 - edge = Edge( bface.v[i].co.copy(), bface.v[j].co.copy() ) - edge.bEdge = mesh.findEdge(bface.v[i], bface.v[j]) - edge.idx = i - return edge - fromBlenderFace=staticmethod(fromBlenderFace) - def edgesOfBlenderFace(mesh, bmFace): - edges = [mesh.edges[mesh.findEdges(edge[0], edge[1])] for edge in bmFace.edge_keys] - v = bmFace.verts - e = [] - vi = v[0] - i=0 - for j in xrange(1, len(bmFace)+1): - vj = v[j%len(bmFace)] - for ee in edges: - if((ee.v1.index==vi.index and ee.v2.index==vj.index) or (ee.v2.index==vi.index and ee.v1.index==vj.index)): - e.append(Edge(vi.co, vj.co, ee, i)) - i+=1 - vi = vj - return e - edgesOfBlenderFace=staticmethod(edgesOfBlenderFace) - def isBlenderSeam(self): - return (self.bmEdge.flag & Mesh.EdgeFlags.SEAM) - def isInFGon(self): - return (self.bmEdge.flag & Mesh.EdgeFlags.FGON) - def mapTo(self, poly): - if(self.idx==len(poly.v)-1): - j = 0 - else: - j = self.idx+1 - return Edge(poly.v[self.idx], poly.v[j]) - def isDegenerate(self): - return self.vector.length==0 - def vertices(s): - return [ [s.v1.x, s.v1.y, s.v1.z], [s.v2.x, s.v2.y,s.v2.z] ] - def key(self): - return self.bmEdge.key - def goodness(self): - return self.gooodness - def setGoodness(self, g): - self.gooodness = g - def compare(self, other): - if(self.goodness() > other.goodness()): - return +1 - else: - return -1 - # Does the given segment intersect this, for overlap detection. - # endpoints are allowed to touch the line segment - def intersects2D(self, s): - if(self.matches(s)): - return False - else: - i = Geometry.LineIntersect2D(self.v1, self.v2, s.v1, s.v2) - if(i!=None): - i.resize4D() - i.z = self.v1.z # hack to put the point on the same plane as this edge for comparison - return(i!=None and not(self.endsWith(i))) - def matches(self, s): - return ( (self.v1==s.v1 and self.v2==s.v2) or (self.v2==s.v1 and self.v1==s.v2) ) - # Is the given point on the end of this segment ? 10-5 seems to an acceptable limit for closeness in Blender - def endsWith(self, aPoint, e=0.0001): - return ( (self.v1-aPoint).length < e or (self.v2-aPoint).length < e ) - - -class Poly: - ids = -1 - def __init__(self): - Poly.ids+=1 - self.v = [] - self.id = Poly.ids - self.boundz = None - self.edges = None - def getID(self): - return self.id - def normal(self): - a =self.v[0] - b=self.v[1] - c=self.v[2] - p = b-a - p.resize3D() - q = a-c - q.resize3D() - return p.cross(q) - def makeEdges(self): - self.edges = [] - for i in xrange(self.nPoints()): - self.edges.append(Edge( self.v[i % self.nPoints()], self.v[ (i+1) % self.nPoints()] )) - def edgeAt(self, i): - if(self.edges==None): - self.makeEdges() - return self.edges[i] - def intersects2D(self, poly): - for i in xrange(self.nPoints()): - edge = self.edgeAt(i) - for j in xrange(poly.nPoints()): - if edge.intersects2D(poly.edgeAt(j)): - return True - return False - def isBad(self): - badness = 0 - for vv in self.v: - if(vv.x!=vv.x or vv.y!=vv.y or vv.z!=vv.z): # Nan check - badness+=1 - return (badness>0) - def midpoint(self): - x=y=z = 0.0 - n = 0 - for vv in self.v: - x+=vv.x - y+=vv.y - z+=vv.z - n+=1 - return [ x/n, y/n, z/n ] - def centerAtOrigin(self): - mp = self.midpoint() - mp = -mp - toOrigin = TranslationMatrix(mp) - self.v = [(vv * toOrigin) for vv in self.v] - def move(self, tv): - mv = TranslationMatrix(tv) - self.v = [(vv * mv) for vv in self.v] - def scale(self, s): - mp = Vector(self.midpoint()) - fromOrigin = TranslationMatrix(mp) - mp = -mp - toOrigin = TranslationMatrix(mp) - sm = ScaleMatrix(s, 4) - # Todo, the 3 lines below in 1 LC - self.v = [(vv * toOrigin) for vv in self.v] - self.v = [(sm * vv) for vv in self.v] - self.v = [(vv * fromOrigin) for vv in self.v] - def nPoints(self): - return len(self.v) - def size(self): - return len(self.v) - def rotated(self, axis, angle): - p = self.clone() - p.rotate(axis, angle) - return p - def rotate(self, axis, angle): - rotation = RotationMatrix(angle, 4, "r", axis.vector) - toOrigin = TranslationMatrix(axis.v1n) - fromOrigin = TranslationMatrix(axis.v1) - # Todo, the 3 lines below in 1 LC - self.v = [(vv * toOrigin) for vv in self.v] - self.v = [(rotation * vv) for vv in self.v] - self.v = [(vv * fromOrigin) for vv in self.v] - def moveAlong(self, vector, distance): - t = TranslationMatrix(vector) - s = ScaleMatrix(distance, 4) - ts = t*s - self.v = [(vv * ts) for vv in self.v] - def bounds(self): - if(self.boundz == None): - vv = [vv for vv in self.v] - vv.sort(key=lambda v: v.x) - minx = vv[0].x - maxx = vv[len(vv)-1].x - vv.sort(key=lambda v: v.y) - miny = vv[0].y - maxy = vv[len(vv)-1].y - self.boundz = [Vector(minx, miny, 0), Vector(maxx, maxy, 0)] - return self.boundz - def fromBlenderFace(bface): - p = Poly() - for vv in bface.v: - vec = Vector([vv.co[0], vv.co[1], vv.co[2] , 1.0]) - p.v.append(vec) - return p - fromBlenderFace = staticmethod(fromBlenderFace) - def fromList(list): - p = Poly() - for vv in list: - vec = Vector( [vvv for vvv in vv] ) - vec.resize4D() - p.v.append(vec) - return p - fromList = staticmethod(fromList) - def fromVectors(vectors): - p = Poly() - p.v.extend([v.copy().resize4D() for v in vectors]) - return p - fromVectors = staticmethod(fromVectors) - def clone(self): - p = Poly() - p.v.extend(self.v) - return p - def hasVertex(self, ttv): - v = Mathutils.Vector(ttv) - v.normalize() - for tv in self.v: - vv = Mathutils.Vector(tv) - vv.normalize() - t = 0.00001 - if abs(vv.x-v.x)<t and abs(vv.y-v.y)<t: - return True - return False - def overlays(self, poly): - if len(poly.v)!=len(self.v): - return False - c = 0 - for point in poly.v: - if self.hasVertex(point): - c+=1 - return c==len(self.v) - def sharesVertexWith(self, poly): - for point in poly.v: - if(self.hasVertex(point)): - return True - return False - def containsAnyOf(self, poly): - for point in poly.v: - if(not(self.hasVertex(point))): - if self.contains(point): - return True - return False - def toString(self): - return self.v - # This is the BEST algorithm for point-in-polygon detection. - # It's by W. Randolph Franklin. - # returns 1 for inside, 1 or 0 for edges - def contains(self, tp): - c = 0 - j = len(self.v)-1 - for i in xrange(len(self.v)): - if(i>0): j=i-1 - cv = self.v[i] - nv = self.v[j] - if ((((cv.y<=tp.y) and (tp.y<nv.y)) or ((nv.y<=tp.y) and (tp.y<cv.y))) and (tp.x < (nv.x - cv.x) * (tp.y - cv.y) / (nv.y - cv.y) + cv.x)): - c = not(c) - return (c == 1) - -class SVGExporter: - def __init__(self, net, filename): - self.net = net - print self.net.des.name - self.object = self.net.object - print "Exporting ", self.object - self.filename = filename - self.file = None - self.e = None - self.width = 1024 - self.height = 768 - def start(self): - print "Exporting SVG to ", self.filename - self.file = open(self.filename, 'w') - self.e = xml.sax.saxutils.XMLGenerator(self.file, "UTF-8") - atts = {} - atts["width"] = "100%" - atts["height"] = "100%" - atts["viewBox"] = str(self.vxmin)+" "+str(self.vymin)+" "+str(self.vxmax-self.vxmin)+" "+str(self.vymax-self.vymin) - atts["xmlns:nets"] = "http://celeriac.net/unfolder/rdf#" - atts["xmlns:xlink"] = "http://www.w3.org/1999/xlink" - atts["xmlns"] ="http://www.w3.org/2000/svg" - a = xml.sax.xmlreader.AttributesImpl(atts) - self.e.startDocument() - self.e.startElement("svg", a) - self.e.startElement("defs", xml.sax.xmlreader.AttributesImpl({})) - atts = {} - atts["type"]="text/css" - self.e.startElement("style", atts) - # can't find a proper way to do this - self.file.write("<![CDATA[") - self.file.write("polygon.poly{fill:white;stroke:black;stroke-width: 0.001}") - self.file.write("g#foldLines line.valley{stroke:white;stroke-width:0.01;stroke-dasharray:0.02,0.01,0.02,0.05}") - self.file.write("g#foldLines line.mountain{stroke:white;stroke-width:0.01;stroke-dasharray:0.02,0.04}") - self.file.write("]]>") - self.e.endElement("style") - self.e.endElement("defs") - #self.addClipPath() - self.addMeta() - def addMeta(self): - self.e.startElement("metadata", xml.sax.xmlreader.AttributesImpl({})) - self.e.startElement("nets:net", xml.sax.xmlreader.AttributesImpl({})) - for i in xrange(1, len(self.net.folds)): - fold = self.net.folds[i] - # AttributesNSImpl - documentation is rubbish. using this hack. - atts = {} - atts["nets:id"] = "fold"+str(fold.getID()) - if(fold.parent!=None): - atts["nets:parent"] = "fold"+str(fold.parent.getID()) - else: - atts["nets:parent"] = "null" - atts["nets:da"] = str(fold.dihedralAngle()) - if(fold.parent!=None): - atts["nets:ofPoly"] = "poly"+str(fold.parent.foldingPoly.getID()) - else: - atts["nets:ofPoly"] = "" - atts["nets:toPoly"] = "poly"+str(fold.foldingPoly.getID()) - a = xml.sax.xmlreader.AttributesImpl(atts) - self.e.startElement("nets:fold", a) - self.e.endElement("nets:fold") - self.e.endElement("nets:net") - self.e.endElement("metadata") - def end(self): - self.e.endElement("svg") - self.e.endDocument() - print "grown." - def export(self): - self.net.unfoldTo(1) - bb = self.object.getBoundBox() - print bb - self.vxmin = bb[0][0] - self.vymin = bb[0][1] - self.vxmax = bb[7][0] - self.vymax = bb[7][1] - self.start() - atts = {} - atts["id"] = self.object.getName() - a = xml.sax.xmlreader.AttributesImpl(atts) - self.e.startElement("g", a) - #self.addUVImage() - self.addPolys() - self.addFoldLines() - #self.addCutLines() - self.e.endElement("g") - self.end() - def addClipPath(self): - atts = {} - atts["id"] = "netClip" - atts["clipPathUnits"] = "userSpaceOnUse" - atts["x"] = str(self.vxmin) - atts["y"] = str(self.vymin) - atts["width"] = "100%" - atts["height"] = "100%" - self.e.startElement("clipPath", atts) - self.addPolys() - self.e.endElement("clipPath") - def addUVImage(self): - image = Blender.Image.GetCurrent() #hmm - how to determine the desired image ? - if image==None: - return - ifn = image.getFilename() - ifn = self.filename.replace(".svg", ".jpg") - image.setFilename(ifn) - ifn = ifn[ifn.rfind("/")+1:] - image.save() - atts = {} - atts["clip-path"] = "url(#netClip)" - atts["xlink:href"] = ifn - self.e.startElement("image", atts) - self.e.endElement("image") - def addPolys(self): - atts = {} - atts["id"] = "polys" - a = xml.sax.xmlreader.AttributesImpl(atts) - self.e.startElement("g", a) - for i in xrange(len(self.net.folds)): - self.addPoly(self.net.folds[i]) - self.e.endElement("g") - def addFoldLines(self): - atts = {} - atts["id"] = "foldLines" - a = xml.sax.xmlreader.AttributesImpl(atts) - self.e.startElement("g", a) - for i in xrange( 1, len(self.net.folds)): - self.addFoldLine(self.net.folds[i]) - self.e.endElement("g") - def addFoldLine(self, fold): - edge = fold.edge.mapTo(fold.parent.foldingPoly) - if fold.dihedralAngle()>0: - foldType="valley" - else: - foldType="mountain" - atts={} - atts["x1"] = str(edge.v1.x) - atts["y1"] = str(edge.v1.y) - atts["x2"] = str(edge.v2.x) - atts["y2"] = str(edge.v2.y) - atts["id"] = "fold"+str(fold.getID()) - atts["class"] = foldType - a = xml.sax.xmlreader.AttributesImpl(atts) - self.e.startElement("line", a) - self.e.endElement("line") - def addCutLines(self): - atts = {} - atts["id"] = "cutLines" - a = xml.sax.xmlreader.AttributesImpl(atts) - self.e.startElement("g", a) - for i in xrange( 1, len(self.net.cuts)): - self.addCutLine(self.net.cuts[i]) - self.e.endElement("g") - def addCutLine(self, cut): - edge = cut.edge.mapTo(cut.parent.foldingPoly) - if cut.dihedralAngle()>0: - foldType="valley" - else: - foldType="mountain" - atts={} - atts["x1"] = str(edge.v1.x) - atts["y1"] = str(edge.v1.y) - atts["x2"] = str(edge.v2.x) - atts["y2"] = str(edge.v2.y) - atts["id"] = "cut"+str(cut.getID()) - atts["class"] = foldType - a = xml.sax.xmlreader.AttributesImpl(atts) - self.e.startElement("line", a) - self.e.endElement("line") - def addPoly(self, fold): - face = fold.foldingPoly - atts = {} - if fold.desFace.col: - col = fold.desFace.col[0] - rgb = "rgb("+str(col.r)+","+str(col.g)+","+str(col.b)+")" - atts["fill"] = rgb - atts["class"] = "poly" - atts["id"] = "poly"+str(face.getID()) - points = "" - first = True - for vv in face.v: - if(not(first)): - points+=',' - first = False - points+=str(vv[0]) - points+=' ' - points+=str(vv[1]) - atts["points"] = points - a = xml.sax.xmlreader.AttributesImpl(atts) - self.e.startElement("polygon", a) - self.e.endElement("polygon") - def fileSelected(filename): - try: - net = Registry.GetKey('unfolder')['net'] - exporter = SVGExporter(net, filename) - exporter.export() - except: - print "Problem exporting SVG" - traceback.print_exc(file=sys.stdout) - fileSelected = staticmethod(fileSelected) - -# for importing nets saved by the above exporter -class NetHandler(xml.sax.handler.ContentHandler): - def __init__(self, net): - self.net = net - self.first = (41==41) - self.currentElement = None - self.chars = None - self.currentAction = None - self.foldsPending = {} - self.polys = {} - self.actions = {} - self.actions["nets:fold"] = self.foldInfo - self.actions["line"] = self.cutOrFold - self.actions["polygon"] = self.createPoly - def setDocumentLocator(self, locator): - pass - def startDocument(self): - pass - def endDocument(self): - for fold in self.foldsPending.values(): - face = self.net.addFace(fold.unfoldedFace()) - fold.desFace = face - self.net.folds.append(fold) - self.net.addFace(self.first) - self.foldsPending = None - self.polys = None - def startPrefixMapping(self, prefix, uri): - pass - def endPrefixMapping(self, prefix): - pass - def startElement(self, name, attributes): - self.currentAction = None - try: - self.currentAction = self.actions[name] - except: - pass - if(self.currentAction!=None): - self.currentAction(attributes) - def endElement(self, name): - pass - def startElementNS(self, name, qname, attrs): - self.currentAction = self.actions[name] - if(self.currentAction!=None): - self.currentAction(attributes) - def endElementNS(self, name, qname): - pass - def characters(self, content): - pass - def ignorableWhitespace(self): - pass - def processingInstruction(self, target, data): - pass - def skippedEntity(self, name): - pass - def foldInfo(self, atts): - self.foldsPending[atts["nets:id"]] = atts - def createPoly(self, atts): - xy = re.split('[, ]' , atts["points"]) - vectors = [] - for i in xrange(0, len(xy)-1, 2): - v = Vector([float(xy[i]), float(xy[i+1]), 0.0]) - vectors.append(v) - poly = Poly.fromVectors(vectors) - if(self.first==True): - self.first = poly - self.polys[atts["id"]] = poly - def cutOrFold(self, atts): - fid = atts["id"] - try: - fi = self.foldsPending[fid] - except: - pass - p1 = Vector([float(atts["x1"]), float(atts["y1"]), 0.0]) - p2 = Vector([float(atts["x2"]), float(atts["y2"]), 0.0]) - edge = Edge(p1, p2) - parent = None - ofPoly = None - toPoly = None - try: - parent = self.foldsPending[fi["nets:parent"]] - except: - pass - try: - ofPoly = self.polys[fi["nets:ofPoly"]] - except: - pass - try: - toPoly = self.polys[fi["nets:toPoly"]] - except: - pass - fold = Fold(parent, ofPoly , toPoly, edge, float(fi["nets:da"])) - self.foldsPending[fid] = fold - def fileSelected(filename): - try: - net = Net.importNet(filename) - try: - Registry.GetKey('unfolder')['net'] = net - except: - Registry.SetKey('unfolder', {}) - Registry.GetKey('unfolder')['net'] = net - Registry.GetKey('unfolder')['lastpath'] = filename - except: - print "Problem importing SVG" - traceback.print_exc(file=sys.stdout) - fileSelected = staticmethod(fileSelected) - - -class GUI: - def __init__(self): - self.overlaps = Draw.Create(0) - self.ani = Draw.Create(0) - self.selectedFaces =0 - self.search = Draw.Create(0) - self.diffuse = True - self.ancestors = Draw.Create(0) - self.noise = Draw.Create(0.0) - self.shape = Draw.Create(0) - self.nOverlaps = 1==2 - self.iterators = [RandomEdgeIterator,Brightest,Curvature,EdgeIterator,OddEven,Largest] - self.iterator = RandomEdgeIterator - self.overlapsText = "*" - self.message = " " - def makePopupGUI(self): - useRandom = Draw.Create(0) - pub = [] - pub.append(("Search", self.search, "Search for non-overlapping net (maybe forever)")) - pub.append(("Random", useRandom, "Random style net")) - ok = True - while ok: - ok = Blender.Draw.PupBlock("Unfold", pub) - if ok: - if useRandom.val: - self.iterator = RandomEdgeIterator - else: - self.iterator = Curvature - self.unfold() - def makeStandardGUI(self): - Draw.Register(self.draw, self.keyOrMouseEvent, self.buttonEvent) - def installScriptLink(self): - print "Adding script link for animation" - s = Blender.Scene.GetCurrent().getScriptLinks("FrameChanged") - if(s!=None and s.count("frameChanged.py")>0): - return - try: - script = Blender.Text.Get("frameChanged.py") - except: - script = Blender.Text.New("frameChanged.py") - script.write("import Blender\n") - script.write("import mesh_unfolder as Unfolder\n") - script.write("u = Blender.Registry.GetKey('unfolder')\n") - script.write("if u!=None:\n") - script.write("\tn = u['net']\n") - script.write("\tif(n!=None and n.animates):\n") - script.write("\t\tn.unfoldToCurrentFrame()\n") - Blender.Scene.GetCurrent().addScriptLink("frameChanged.py", "FrameChanged") - def unfold(self): - anc = self.ancestors.val - n = 0.0 - s = True - self.nOverlaps = 0 - searchLimit = 10 - search = 1 - Draw.Redraw(1) - net = None - name = None - try: - self.say("Unfolding...") - Draw.Redraw(1) - while(s):# and search < searchLimit): - if(net!=None): - name = net.des.name - net = Net.fromSelected(self, name) - net.setAvoidsOverlaps(not(self.overlaps.val)) - print - print "Unfolding selected object" - net.edgeIteratorClass = self.iterator - print "Using ", net.edgeIteratorClass - net.animates = self.ani.val - self.diffuse = (self.ancestors.val==0) - net.diffuse = self.diffuse - net.generations = self.ancestors.val - net.noise = self.noise.val - print "even:", net.diffuse, " depth:", net.generations - net.unfold() - n = net.report() - t = "." - if(n<1.0): - t = "Overlaps>="+str(n) - else: - t = "A complete net." - self.nOverlaps = (n>=1) - if(self.nOverlaps): - self.say(self.message+" - unfolding failed - try again ") - elif(not(self.overlaps.val)): - self.say("Success. Complete net - no overlaps ") - else: - self.say("Unfolding complete") - self.ancestors.val = anc - s = (self.search.val and n>=1.0) - dict = Registry.GetKey('unfolder') - if(not(dict)): - dict = {} - dict['net'] = net - Registry.SetKey('unfolder', dict) - if(s): - net = net.clone() - search += 1 - except(IndexError): - self.say("Please select an object to unfold") - except: - self.say("Problem unfolding selected object - see console for details") - print "Problem unfolding selected object:" - print sys.exc_info()[1] - traceback.print_exc(file=sys.stdout) - if(self.ani): - if Registry.GetKey('unfolder')==None: - print "no net!" - return - Registry.GetKey('unfolder')['net'].sortOutIPOSource() - self.installScriptLink() - Draw.Redraw(1) - def keyOrMouseEvent(self, evt, val): - if (evt == Draw.ESCKEY and not val): - Draw.Exit() - def buttonEvent(self, evt): - if (evt == 1): - self.unfold() - if (evt == 5): - try: - Registry.GetKey('unfolder')['net'].setAvoidsOverlaps(self.overlaps.val) - except: - pass - if (evt == 2): - print "Trying to set IPO curve" - try: - s = Blender.Object.GetSelected() - if(s!=None): - Registry.GetKey('unfolder')['net'].setIPOSource( s[0] ) - print "Set IPO curve" - else: - print "Please select an object to use the IPO of" - except: - print "Problem setting IPO source" - Draw.Redraw(1) - if (evt == 6): - Draw.Exit() - if (evt == 7): - try: - if (Registry.GetKey('unfolder')['net']!=None): - Registry.GetKey('unfolder')['net'].animates = self.ani.val - if(self.ani): - Registry.GetKey('unfolder')['net'].sortOutIPOSource() - self.installScriptLink() - except: - print sys.exc_info()[1] - traceback.print_exc(file=sys.stdout) - Draw.Redraw(1) - if (evt == 19): - pass - if (evt == 87): - try: - if (Registry.GetKey('unfolder')['net']!=None): - Registry.GetKey('unfolder')['net'].assignUVs() - self.say("Assigned UVs") - except: - print sys.exc_info()[1] - traceback.print_exc(file=sys.stdout) - Draw.Redraw(1) - if(evt==91): - if( testOverlap() == True): - self.nOverlaps = 1 - else: - self.nOverlaps = 0 - Draw.Redraw(1) - if(evt==233): - f1 = Poly.fromBlenderFace(Blender.Object.GetSelected()[0].getData().faces[0]) - f2 = Poly.fromBlenderFace(Blender.Object.GetSelected()[1].getData().faces[0]) - print - print Blender.Object.GetSelected()[0].getName() - print Blender.Object.GetSelected()[1].getName() - print f1.intersects2D(f2) - print f2.intersects2D(f1) - if(evt==714): - Net.unfoldAll(self) - Draw.Redraw(1) - if(evt==713): - self.iterator = self.iterators[self.shape.val] - Draw.Redraw(1) - if(evt==92): - if( testContains() == True): - self.nOverlaps = 1 - else: - self.nOverlaps = 0 - Draw.Redraw(1) - if(evt==104): - try: - filename = "net.svg" - s = Blender.Object.GetSelected() - if(s!=None and len(s)>0): - filename = s[0].getName()+".svg" - else: - if (Registry.GetKey('unfolder')['net']!=None): - filename = Registry.GetKey('unfolder')['net'].des.name - if(filename==None): - filename="net.svg" - else: - filename=filename+".svg" - Window.FileSelector(SVGExporter.fileSelected, "Select filename", filename) - except: - print "Problem exporting SVG" - traceback.print_exc(file=sys.stdout) - if(evt==107): - try: - Window.FileSelector(NetHandler.fileSelected, "Select file") - except: - print "Problem importing SVG" - traceback.print_exc(file=sys.stdout) - def say(self, m): - self.message = m - Draw.Redraw(1) - Window.Redraw(Window.Types.SCRIPT) - def draw(self): - cw = 64 - ch = 16 - l = FlowLayout(32, cw, ch, 350, 64) - l.y = 70 - self.search = Draw.Toggle("search", 19, l.nx(), l.ny(), l.cw, l.ch, self.search.val, "Search for non-overlapping mesh (potentially indefinitely)") - self.overlaps = Draw.Toggle("overlaps", 5, l.nx(), l.ny(), l.cw, l.ch, self.overlaps.val, "Allow overlaps / avoid overlaps - if off, will not place overlapping faces") - self.ani = Draw.Toggle("ani", 7, l.nx(), l.ny(), l.cw, l.ch, self.ani.val, "Animate net") - Draw.Button("uv", 87, l.nx(), l.ny(), l.cw, l.ch, "Assign net as UV to source mesh (overwriting existing UV)") - Draw.Button("Unfold", 1, l.nx(), l.ny(), l.cw, l.ch, "Unfold selected mesh to net") - Draw.Button("save", 104, l.nx(), l.ny(), l.cw, l.ch, "Save net as SVG") - Draw.Button("load", 107, l.nx(), l.ny(), l.cw, l.ch, "Load net from SVG") - #Draw.Button("test", 233, l.nx(), l.ny(), l.cw, l.ch, "test") - # unfolding enthusiasts - try uncommenting this - self.ancestors = Draw.Number("depth", 654, l.nx(), l.ny(), cw, ch, self.ancestors.val, 0, 9999, "depth of branching 0=diffuse") - #self.noise = Draw.Number("noise", 631, l.nx(), l.ny(), cw, ch, self.noise.val, 0.0, 1.0, "noisyness of branching") - #Draw.Button("UnfoldAll", 714, l.nx(), l.ny(), l.cw, l.ch, "Unfold all meshes and save their nets") - options = "order %t|random %x0|brightest %x1|curvature %x2|winding %x3| 1010 %x4|largest %x5" - self.shape = Draw.Menu(options, 713, l.nx(), l.ny(), cw, ch, self.shape.val, "shape of net") - Draw.Button("exit", 6, l.nx(), l.ny(), l.cw, l.ch, "exit") - BGL.glClearColor(0.3, 0.3, 0.3, 1) - BGL.glColor3f(0.3,0.3,0.3) - l.newLine() - BGL.glRasterPos2i(32, 100) - Draw.Text(self.message) - -class FlowLayout: - def __init__(self, margin, cw, ch, w, h): - self.x = margin-cw-4 - self.y = margin - self.cw = cw - self.ch = ch - self.width = w - self.height = h - self.margin = margin - def nx(self): - self.x+=(self.cw+4) - if(self.x>self.width): - self.x = self.margin - self.y-=self.ch+4 - return self.x - def ny(self): - return self.y - def newLine(self): - self.y-=self.ch+self.margin - self.x = self.margin - -# if xml is None, then dont bother running the script -if xml: - try: - sys.setrecursionlimit(10000) - gui = GUI() - gui.makeStandardGUI() - #gui.makePopupGUI() - except: - traceback.print_exc(file=sys.stdout) |