Commit: ce729677db3e9934e2e2c56a9397a868c7546ee9 Author: Tamito Kajiyama Date: Tue Jun 24 13:52:12 2014 +0900 https://developer.blender.org/rBce729677db3e9934e2e2c56a9397a868c7546ee9
D319: Freestyle Python scripts update. This revision is meant to update Freestyle's Python scripts to make full usage of the new features of Python and Freestyle's Python API. Freestyle's Python scripts are pretty old already, and were never given much attention. With the 2.7x generation of Blender coming up, this is an excellent time to update Freestyle's Python scripts, hopefully adding some new features and achieving some speed improvements on the way. Main goals: * use for loops where possible * general cleanup, making use of more recent python features (generators, ternary operator, ect.) * update the documentation on the way (it's lacking atm) Differential revision: https://developer.blender.org/D319 Author: flokkievids (Folkert de Vries) Reviewed by: kjym3 (Tamito Kajiyama) =================================================================== M release/scripts/freestyle/modules/freestyle/chainingiterators.py M release/scripts/freestyle/modules/freestyle/functions.py M release/scripts/freestyle/modules/freestyle/predicates.py M release/scripts/freestyle/modules/freestyle/shaders.py M release/scripts/freestyle/modules/freestyle/utils.py =================================================================== diff --git a/release/scripts/freestyle/modules/freestyle/chainingiterators.py b/release/scripts/freestyle/modules/freestyle/chainingiterators.py index ae0a8a0..080919f 100644 --- a/release/scripts/freestyle/modules/freestyle/chainingiterators.py +++ b/release/scripts/freestyle/modules/freestyle/chainingiterators.py @@ -23,6 +23,20 @@ rules. Also intended to be a collection of examples for defining chaining iterators in Python """ +__all__ = ( + "pyChainSilhouetteIterator", + "pyChainSilhouetteGenericIterator", + "pyExternalContourChainingIterator", + "pySketchyChainSilhouetteIterator", + "pySketchyChainingIterator", + "pyFillOcclusionsRelativeChainingIterator", + "pyFillOcclusionsAbsoluteChainingIterator", + "pyFillOcclusionsAbsoluteAndRelativeChainingIterator", + "pyFillQi0AbsoluteAndRelativeChainingIterator", + "pyNoIdChainSilhouetteIterator", + ) + + # module members from _freestyle import ( ChainPredicateIterator, @@ -41,11 +55,30 @@ from freestyle.predicates import ( ) from freestyle.utils import ( ContextFunctions as CF, - stroke_normal, + get_chain_length, + find_matching_vertex, ) + import bpy +NATURES = ( + Nature.SILHOUETTE, + Nature.BORDER, + Nature.CREASE, + Nature.MATERIAL_BOUNDARY, + Nature.EDGE_MARK, + Nature.SUGGESTIVE_CONTOUR, + Nature.VALLEY, + Nature.RIDGE + ) + + +def nature_in_preceding(nature, index): + """ Returns True if given nature appears before index, else False """ + return any(nature & nat for nat in NATURES[:index]) + + class pyChainSilhouetteIterator(ChainingIterator): """Natural chaining iterator @@ -61,43 +94,28 @@ class pyChainSilhouetteIterator(ChainingIterator): pass def traverse(self, iter): - winner = None it = AdjacencyIterator(iter) - tvertex = self.next_vertex - if type(tvertex) is TVertex: - mateVE = tvertex.get_mate(self.current_edge) - while not it.is_end: - ve = it.object - if ve.id == mateVE.id: - winner = ve - break - it.increment() - else: - ## case of NonTVertex - natures = [Nature.SILHOUETTE,Nature.BORDER,Nature.CREASE,Nature.MATERIAL_BOUNDARY,Nature.EDGE_MARK, - Nature.SUGGESTIVE_CONTOUR,Nature.VALLEY,Nature.RIDGE] - for i in range(len(natures)): - currentNature = self.current_edge.nature - if (natures[i] & currentNature) != 0: - count=0 - while not it.is_end: - visitNext = 0 - oNature = it.object.nature - if (oNature & natures[i]) != 0: - if natures[i] != oNature: - for j in range(i): - if (natures[j] & oNature) != 0: - visitNext = 1 - break - if visitNext != 0: - break - count = count+1 - winner = it.object - it.increment() - if count != 1: - winner = None - break - return winner + ## case of TVertex + vertex = self.next_vertex + if type(vertex) is TVertex: + mate = vertex.get_mate(self.current_edge) + return find_matching_vertex(mate.id, it) + ## case of NonTVertex + winner = None + for i, nat in enumerate(NATURES): + if (nat & self.current_edge.nature): + for ve in it: + ve_nat = ve.nature + if (ve_nat & nat): + # search for matches in previous natures. if match -> break + if nat != ve_nat and nature_in_preceding(ve_nat, index=i): + break + # a second match must be an error + if winner is not None: + return None + # assign winner + winner = ve + return winner class pyChainSilhouetteGenericIterator(ChainingIterator): @@ -120,47 +138,30 @@ class pyChainSilhouetteGenericIterator(ChainingIterator): pass def traverse(self, iter): - winner = None it = AdjacencyIterator(iter) - tvertex = self.next_vertex - if type(tvertex) is TVertex: - mateVE = tvertex.get_mate(self.current_edge) - while not it.is_end: - ve = it.object - if ve.id == mateVE.id: - winner = ve - break - it.increment() - else: - ## case of NonTVertex - natures = [Nature.SILHOUETTE,Nature.BORDER,Nature.CREASE,Nature.MATERIAL_BOUNDARY,Nature.EDGE_MARK, - Nature.SUGGESTIVE_CONTOUR,Nature.VALLEY,Nature.RIDGE] - for i in range(len(natures)): - currentNature = self.current_edge.nature - if (natures[i] & currentNature) != 0: - count=0 - while not it.is_end: - visitNext = 0 - oNature = it.object.nature - ve = it.object - if ve.id == self.current_edge.id: - it.increment() - continue - if (oNature & natures[i]) != 0: - if natures[i] != oNature: - for j in range(i): - if (natures[j] & oNature) != 0: - visitNext = 1 - break - if visitNext != 0: - break - count = count+1 - winner = ve - it.increment() - if count != 1: - winner = None - break - return winner + ## case of TVertex + vertex = self.next_vertex + if type(vertex) is TVertex: + mate = vertex.get_mate(self.current_edge) + return find_matching_vertex(mate.id, it) + ## case of NonTVertex + winner = None + for i, nat in enumerate(NATURES): + if (nat & self.current_edge.nature): + for ve in it: + ve_nat = ve.nature + if ve.id == self.current_edge.id: + continue + if (ve_nat & nat): + if nat != ve_nat and nature_in_preceding(ve_nat, index=i): + break + + if winner is not None: + return None + + winner = ve + return winner + return None class pyExternalContourChainingIterator(ChainingIterator): @@ -168,49 +169,40 @@ class pyExternalContourChainingIterator(ChainingIterator): def __init__(self): ChainingIterator.__init__(self, False, True, None, True) - self._isExternalContour = ExternalContourUP1D() + self.ExternalContour = ExternalContourUP1D() def init(self): self._nEdges = 0 - self._isInSelection = 1 def checkViewEdge(self, ve, orientation): - if orientation != 0: - vertex = ve.second_svertex() - else: - vertex = ve.first_svertex() - it = AdjacencyIterator(vertex,1,1) - while not it.is_end: - ave = it.object - if self._isExternalContour(ave): - return True - it.increment() - if bpy.app.debug_freestyle: + vertex = (ve.first_viewvertex if orientation else + ve.last_viewvertex) + + it = AdjacencyIterator(vertex, True, True) + result = any(self.ExternalContour(ave) for ave in it) + # report if there is no result (that's bad) + if not result and bpy.app.debug_freestyle: print("pyExternalContourChainingIterator : didn't find next edge") - return False + + return result def traverse(self, iter): winner = None + self._nEdges += 1 + it = AdjacencyIterator(iter) - while not it.is_end: - ve = it.object - if self._isExternalContour(ve): - if ve.time_stamp == CF.get_time_stamp(): - winner = ve - it.increment() + time_stamp = CF.get_time_stamp() + + for ve in it: + if self.ExternalContour(ve) and ve.time_stamp == time_stamp: + winner = ve - self._nEdges = self._nEdges+1 if winner is None: - orient = 1 it = AdjacencyIterator(iter) - while not it.is_end: - ve = it.object - if it.is_incoming: - orient = 0 - good = self.checkViewEdge(ve,orient) - if good != 0: + for ve in it: + if self.checkViewEdge(ve, not it.is_incoming): winner = ve - it.increment() + return winner @@ -227,58 +219,49 @@ class pySketchyChainSilhouetteIterator(ChainingIterator): def __init__(self, nRounds=3,stayInSelection=True): ChainingIterator.__init__(self, stayInSelection, False, None, True) - self._timeStamp = CF.get_time_stamp()+nRounds + self._timeStamp = CF.get_time_stamp() + nRounds self._nRounds = nRounds def init(self): - self._timeStamp = CF.get_time_stamp()+self._nRounds + self._timeStamp = CF.get_time_stamp() + self._nRounds + + # keeping this local saves passing a reference to 'self' around + def make_sketchy(self, ve): + """ + Creates the skeychy effect by causing th @@ Diff output truncated at 10240 characters. @@ _______________________________________________ Bf-blender-cvs mailing list [email protected] http://lists.blender.org/mailman/listinfo/bf-blender-cvs
