Advertisement
Guest User

Untitled

a guest
Mar 28th, 2017
64
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.93 KB | None | 0 0
  1. bl_info = {
  2. "name": "Assign random vertex color to each loose part of a mesh",
  3. "author": "lemon",
  4. "version": (1, 0),
  5. "blender": (2, 78, 0),
  6. "location": "Properties Editor > Object data",
  7. "description": "",
  8. "warning": "",
  9. "wiki_url": "",
  10. "category": "Mesh"}
  11.  
  12. import bpy
  13. import time
  14. import random
  15. from mathutils import Color
  16.  
  17. def LoosePartsMakeVertPaths( verts, edges ):
  18. #Initialize the path with all vertices indexes
  19. result = {v.index: set() for v in verts}
  20. #Add the possible paths via edges
  21. for e in edges:
  22. result[e.vertices[0]].add(e.vertices[1])
  23. result[e.vertices[1]].add(e.vertices[0])
  24. return result
  25.  
  26. def LoosePartsFollowEdges( startingIndex, paths ):
  27. current = [startingIndex]
  28. result = set( current )
  29.  
  30. follow = True
  31. while follow:
  32. #Get indexes that are still in the paths
  33. eligible = set( [ind for ind in current if ind in paths] )
  34. if len( eligible ) == 0:
  35. follow = False #Stops is no more
  36. else:
  37. #Get the corresponding links
  38. next = [paths.pop( i ) for i in eligible]
  39. #Get the new links as new inputs
  40. current = set( [ind for sub in next for ind in sub] )
  41. result = result.union( current )
  42.  
  43. return result
  44.  
  45. def LoosePartsCountIslands( obj ):
  46. #Prepare the paths/links from each vertex to others
  47. paths = LoosePartsMakeVertPaths( obj.data.vertices, obj.data.edges )
  48. found = True
  49. n = 0
  50. while found:
  51. try:
  52. #Get one input as long there is one
  53. startingIndex = next( iter( paths.keys() ) )
  54. n = n + 1
  55. #Deplete the paths dictionary following this starting index
  56. LoosePartsFollowEdges( startingIndex, paths )
  57. except:
  58. found = False
  59. return n
  60.  
  61. def LoosePartGetIslands( obj ):
  62. paths = LoosePartsMakeVertPaths( obj.data.vertices, obj.data.edges )
  63.  
  64. result = []
  65.  
  66. found = True
  67. while found:
  68. try:
  69. #Get one input as long there is one
  70. startingIndex = next( iter( paths.keys() ) )
  71. #Deplete the paths dictionary following this starting index and append the result
  72. result.append( LoosePartsFollowEdges( startingIndex, paths ) )
  73. except:
  74. found = False
  75.  
  76. return result
  77.  
  78. def RandomColor( rnd ):
  79. return Color( (rnd.random(), rnd.random(), rnd.random()) )
  80.  
  81. def RandomColors( rnd, count ):
  82. return [RandomColor( rnd ) for i in range( count )]
  83.  
  84. def ColorFromVertexIndex( vertexIndex, looseParts, colors ):
  85. for c, lp in zip( colors, looseParts ):
  86. if vertexIndex in lp:
  87. return c
  88. return Color()
  89.  
  90. def RandomVertexColorsByLooseParts( obj, vcolName, useSeed, seed ):
  91.  
  92. rnd = random.Random()
  93. if useSeed:
  94. rnd.seed( seed )
  95.  
  96. mesh = obj.data
  97.  
  98. #Create vertex colors if it does not already exist
  99. if vcolName not in mesh.vertex_colors:
  100. mesh.vertex_colors.new( vcolName )
  101. #Update it so that it is available below
  102. mesh.vertex_colors.update()
  103. #Get the vertex colors
  104. vertexColors = mesh.vertex_colors[vcolName]
  105.  
  106. #Get loose parts
  107. looseParts = LoosePartGetIslands( obj )
  108. #Generate random colors
  109. colors = RandomColors( rnd, len(looseParts) )
  110.  
  111. mesh.loops.update()
  112.  
  113. #Follow the loops
  114. for i, vertexIndex in enumerate( [loop.vertex_index for loop in mesh.loops] ):
  115. #Assign vertex colors from loop index and vertex index
  116. vertexColors.data[i].color = ColorFromVertexIndex( vertexIndex, looseParts, colors )
  117.  
  118. def InitProperties():
  119. bpy.types.Scene.VertexColorsName = bpy.props.StringProperty( name = "Vertex colors", description = "Vertex colors to use or create", default = "Col" )
  120. bpy.types.Scene.VertexColorsUseSeed = bpy.props.BoolProperty( name = "Use seed", description = "Use fixed seed to generate random values" )
  121. bpy.types.Scene.VertexColorsSeed = bpy.props.IntProperty( name = "Seed", description = "Seed for random values" )
  122. bpy.types.Scene.VertexColorsAllSelected = bpy.props.BoolProperty( name = "All selected objects", description = "Apply to all selected object or only active one" )
  123.  
  124. class RndVColToLoosePartsPanel(bpy.types.Panel):
  125. bl_label = "Random vcol to loose parts"
  126. bl_space_type = "PROPERTIES";
  127. bl_region_type = "WINDOW";
  128. bl_context = ""
  129.  
  130. @classmethod
  131. def poll(self, context):
  132. return context.object and context.scene
  133.  
  134. def draw(self,context):
  135. layout = self.layout
  136. scn = context.scene
  137.  
  138. layout.prop( scn, 'VertexColorsName', icon='GROUP_VCOL' )
  139. layout.prop( scn, 'VertexColorsUseSeed' )
  140. layout.prop( scn, 'VertexColorsSeed' )
  141. layout.operator( "rndvcoltolooseparts.ope")
  142. layout.prop( scn, 'VertexColorsAllSelected' )
  143.  
  144. class RndVColToLooseParts(bpy.types.Operator):
  145. bl_idname="rndvcoltolooseparts.ope"
  146. bl_label="Generate random vcol to each loose parts"
  147.  
  148. def execute(self, context):
  149.  
  150. scene = context.scene
  151. obj = context.object
  152.  
  153. if scene and obj and obj.type == 'MESH':
  154.  
  155. prevMode = obj.mode
  156. bpy.ops.object.mode_set( mode='OBJECT', toggle=False )
  157.  
  158. if scene.VertexColorsAllSelected:
  159. for obj in [obj for obj in context.selected_objects if obj.type == 'MESH']:
  160. RandomVertexColorsByLooseParts( obj, scene.VertexColorsName, scene.VertexColorsUseSeed, scene.VertexColorsSeed )
  161. else:
  162. RandomVertexColorsByLooseParts( obj, scene.VertexColorsName, scene.VertexColorsUseSeed, scene.VertexColorsSeed )
  163.  
  164. bpy.ops.object.mode_set( mode=prevMode, toggle=False )
  165.  
  166. return {'FINISHED'}
  167.  
  168.  
  169. def register():
  170. InitProperties()
  171. bpy.utils.register_class(RndVColToLooseParts)
  172. bpy.utils.register_class(RndVColToLoosePartsPanel)
  173.  
  174.  
  175. def unregister():
  176. bpy.utils.unregister_class(RndVColToLooseParts)
  177. bpy.utils.unregister_class(RndVColToLoosePartsPanel)
  178.  
  179.  
  180. if __name__ == "__main__":
  181. register()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement