1 # ##### BEGIN GPL LICENSE BLOCK #####
3 # This program is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU General Public License
5 # as published by the Free Software Foundation; either version 2
6 # of the License, or (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software Foundation,
15 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 # ##### END GPL LICENSE BLOCK #####
20 # (c) Alessandro Zomparelli #
23 # http://www.co-de-it.com/ #
25 ################################################################################
33 from bpy
.types
import (
38 from bpy
.props
import (
50 class random_materials(Operator
):
51 bl_idname
= "object.random_materials"
52 bl_label
= "Random Materials"
53 bl_description
= "Assign random materials to the faces of the mesh"
54 bl_options
= {'REGISTER', 'UNDO'}
56 prefix
: StringProperty(
57 name
="Prefix", default
="Random.", description
="Name prefix")
59 color_A
: FloatVectorProperty(name
="Color A",
60 subtype
='COLOR_GAMMA',
65 color_B
: FloatVectorProperty(name
="Color B",
66 subtype
='COLOR_GAMMA',
71 hue
: FloatProperty(name
="Hue", min=0, max=1, default
=0.5)
72 hue_variation
: FloatProperty(name
="Hue Variation", min=0, max=1, default
=0.6)
75 name
="Seed", default
=0, description
="Random seed")
78 name
="Count", default
=3, min=2, description
="Count of random materials")
80 generate_materials
: BoolProperty(
81 name
="Generate Materials", default
=False, description
="Automatically generates new materials")
83 random_colors
: BoolProperty(
84 name
="Random Colors", default
=True, description
="Colors are automatically generated")
89 def poll(cls
, context
):
90 try: return context
.object.type == 'MESH'
93 def draw(self
, context
):
95 col
= layout
.column(align
=True)
96 col
.prop(self
, "seed")
97 col
.prop(self
, "generate_materials")
98 if self
.generate_materials
:
99 col
.prop(self
, "prefix")
101 col
.prop(self
, "count")
102 #row = col.row(align=True)
104 col
.label(text
='Colors:')
105 col
.prop(self
, "hue")
106 col
.prop(self
, "hue_variation")
107 #col.prop(self, "random_colors")
108 if not self
.random_colors
:
109 col
.prop(self
, "color_A")
110 col
.prop(self
, "color_B")
112 def execute(self
, context
):
113 bpy
.ops
.object.mode_set(mode
='OBJECT')
114 ob
= context
.active_object
115 if len(ob
.material_slots
) == 0 and not self
.executed
:
116 self
.generate_materials
= True
117 if self
.generate_materials
:
120 h1
= (self
.hue
- self
.hue_variation
/2)
121 h2
= (self
.hue
+ self
.hue_variation
/2)
123 ob
.data
.materials
.clear()
125 for i
in range(count
):
126 mat_name
= '{}{:03d}'.format(self
.prefix
,i
)
127 mat
= bpy
.data
.materials
.new(mat_name
)
128 if self
.random_colors
:
129 mat
.diffuse_color
= colorsys
.hsv_to_rgb((h1
+ (h2
-h1
)/(count
)*i
)%1, 1, 1)[:] + (1,)
131 mat
.diffuse_color
= list(colA
+ (colB
- colA
)/(count
-1)*i
) + [1]
132 ob
.data
.materials
.append(mat
)
134 count
= len(ob
.material_slots
)
135 np
.random
.seed(seed
=self
.seed
)
136 n_faces
= len(ob
.data
.polygons
)
138 rand
= list(np
.random
.randint(count
, size
=n_faces
))
139 ob
.data
.polygons
.foreach_set('material_index',rand
)
144 class weight_to_materials(Operator
):
145 bl_idname
= "object.weight_to_materials"
146 bl_label
= "Weight to Materials"
147 bl_description
= "Assign materials to the faces of the mesh according to the active Vertex Group"
148 bl_options
= {'REGISTER', 'UNDO'}
150 prefix
: StringProperty(
151 name
="Prefix", default
="Weight.", description
="Name prefix")
153 hue
: FloatProperty(name
="Hue", min=0, max=1, default
=0.5)
154 hue_variation
: FloatProperty(name
="Hue Variation", min=0, max=1, default
=0.3)
157 name
="Count", default
=3, min=2, description
="Count of random materials")
159 generate_materials
: BoolProperty(
160 name
="Generate Materials", default
=False, description
="Automatically generates new materials")
164 ('MIN', "Min", "Use the min weight value"),
165 ('MAX', "Max", "Use the max weight value"),
166 ('MEAN', "Mean", "Use the mean weight value")
175 def poll(cls
, context
):
176 try: return context
.object.type == 'MESH'
179 def draw(self
, context
):
181 col
= layout
.column(align
=True)
182 col
.prop(self
, "mode")
183 col
.prop(self
, "generate_materials")
184 if self
.generate_materials
:
185 col
.prop(self
, "prefix")
187 col
.prop(self
, "count")
188 #row = col.row(align=True)
190 col
.label(text
='Colors:')
191 col
.prop(self
, "hue")
192 col
.prop(self
, "hue_variation")
194 def execute(self
, context
):
195 ob
= context
.active_object
197 self
.vg
= ob
.vertex_groups
.active_index
198 vg
= ob
.vertex_groups
[self
.vg
]
200 self
.report({'ERROR'}, "The selected object doesn't have any Vertex Group")
202 weight
= get_weight_numpy(vg
, len(ob
.data
.vertices
))
203 if self
.generate_materials
:
204 h1
= (self
.hue
- self
.hue_variation
/2)
205 h2
= (self
.hue
+ self
.hue_variation
/2)
207 ob
.data
.materials
.clear()
209 for i
in range(count
):
210 mat_name
= '{}{:03d}'.format(self
.prefix
,i
)
211 mat
= bpy
.data
.materials
.new(mat_name
)
212 mat
.diffuse_color
= colorsys
.hsv_to_rgb((h1
+ (h2
-h1
)/(count
)*i
)%1, 1, 1)[:] + (1,)
213 ob
.data
.materials
.append(mat
)
215 count
= len(ob
.material_slots
)
218 for p
in ob
.data
.polygons
:
219 verts_id
= np
.array([v
for v
in p
.vertices
])
220 face_weight
= weight
[verts_id
]
221 if self
.mode
== 'MIN': w
= face_weight
.min()
222 if self
.mode
== 'MAX': w
= face_weight
.max()
223 if self
.mode
== 'MEAN': w
= face_weight
.mean()
224 faces_weight
.append(w
)
225 faces_weight
= np
.array(faces_weight
)
226 faces_weight
= faces_weight
* count
227 faces_weight
.astype('int')
228 ob
.data
.polygons
.foreach_set('material_index',list(faces_weight
))
230 bpy
.ops
.object.mode_set(mode
='OBJECT')