1 # SPDX-License-Identifier: GPL-2.0-or-later
4 # (c) Alessandro Zomparelli #
7 # http://www.co-de-it.com/ #
9 ################################################################################
17 from bpy
.types
import (
22 from bpy
.props
import (
34 class random_materials(Operator
):
35 bl_idname
= "object.random_materials"
36 bl_label
= "Random Materials"
37 bl_description
= "Assign random materials to the faces of the mesh"
38 bl_options
= {'REGISTER', 'UNDO'}
40 prefix
: StringProperty(
41 name
="Prefix", default
="Random.", description
="Name prefix")
43 color_A
: FloatVectorProperty(name
="Color A",
44 subtype
='COLOR_GAMMA',
49 color_B
: FloatVectorProperty(name
="Color B",
50 subtype
='COLOR_GAMMA',
55 hue
: FloatProperty(name
="Hue", min=0, max=1, default
=0.5)
56 hue_variation
: FloatProperty(name
="Hue Variation", min=0, max=1, default
=0.6)
59 name
="Seed", default
=0, description
="Random seed")
62 name
="Count", default
=3, min=2, description
="Count of random materials")
64 generate_materials
: BoolProperty(
65 name
="Generate Materials", default
=False, description
="Automatically generates new materials")
67 random_colors
: BoolProperty(
68 name
="Random Colors", default
=True, description
="Colors are automatically generated")
73 def poll(cls
, context
):
74 try: return context
.object.type == 'MESH'
77 def draw(self
, context
):
79 col
= layout
.column(align
=True)
80 col
.prop(self
, "seed")
81 col
.prop(self
, "generate_materials")
82 if self
.generate_materials
:
83 col
.prop(self
, "prefix")
85 col
.prop(self
, "count")
86 #row = col.row(align=True)
88 col
.label(text
='Colors:')
90 col
.prop(self
, "hue_variation")
91 #col.prop(self, "random_colors")
92 if not self
.random_colors
:
93 col
.prop(self
, "color_A")
94 col
.prop(self
, "color_B")
96 def execute(self
, context
):
97 bpy
.ops
.object.mode_set(mode
='OBJECT')
98 ob
= context
.active_object
99 if len(ob
.material_slots
) == 0 and not self
.executed
:
100 self
.generate_materials
= True
101 if self
.generate_materials
:
104 h1
= (self
.hue
- self
.hue_variation
/2)
105 h2
= (self
.hue
+ self
.hue_variation
/2)
107 ob
.data
.materials
.clear()
109 for i
in range(count
):
110 mat_name
= '{}{:03d}'.format(self
.prefix
,i
)
111 mat
= bpy
.data
.materials
.new(mat_name
)
112 if self
.random_colors
:
113 mat
.diffuse_color
= colorsys
.hsv_to_rgb((h1
+ (h2
-h1
)/(count
)*i
)%1, 1, 1)[:] + (1,)
115 mat
.diffuse_color
= list(colA
+ (colB
- colA
)/(count
-1)*i
) + [1]
116 ob
.data
.materials
.append(mat
)
118 count
= len(ob
.material_slots
)
119 np
.random
.seed(seed
=self
.seed
)
120 n_faces
= len(ob
.data
.polygons
)
122 rand
= list(np
.random
.randint(count
, size
=n_faces
))
123 ob
.data
.polygons
.foreach_set('material_index',rand
)
128 class weight_to_materials(Operator
):
129 bl_idname
= "object.weight_to_materials"
130 bl_label
= "Weight to Materials"
131 bl_description
= "Assign materials to the faces of the mesh according to the active Vertex Group"
132 bl_options
= {'REGISTER', 'UNDO'}
134 prefix
: StringProperty(
135 name
="Prefix", default
="Weight.", description
="Name prefix")
137 hue
: FloatProperty(name
="Hue", min=0, max=1, default
=0.5)
138 hue_variation
: FloatProperty(name
="Hue Variation", min=0, max=1, default
=0.3)
141 name
="Count", default
=3, min=2, description
="Count of random materials")
143 generate_materials
: BoolProperty(
144 name
="Generate Materials", default
=False, description
="Automatically generates new materials")
148 ('MIN', "Min", "Use the min weight value"),
149 ('MAX', "Max", "Use the max weight value"),
150 ('MEAN', "Mean", "Use the mean weight value")
159 def poll(cls
, context
):
160 try: return context
.object.type == 'MESH'
163 def draw(self
, context
):
165 col
= layout
.column(align
=True)
166 col
.prop(self
, "mode")
167 col
.prop(self
, "generate_materials")
168 if self
.generate_materials
:
169 col
.prop(self
, "prefix")
171 col
.prop(self
, "count")
172 #row = col.row(align=True)
174 col
.label(text
='Colors:')
175 col
.prop(self
, "hue")
176 col
.prop(self
, "hue_variation")
178 def execute(self
, context
):
179 ob
= context
.active_object
181 self
.vg
= ob
.vertex_groups
.active_index
182 vg
= ob
.vertex_groups
[self
.vg
]
184 self
.report({'ERROR'}, "The selected object doesn't have any Vertex Group")
186 weight
= get_weight_numpy(vg
, len(ob
.data
.vertices
))
187 if self
.generate_materials
:
188 h1
= (self
.hue
- self
.hue_variation
/2)
189 h2
= (self
.hue
+ self
.hue_variation
/2)
191 ob
.data
.materials
.clear()
193 for i
in range(count
):
194 mat_name
= '{}{:03d}'.format(self
.prefix
,i
)
195 mat
= bpy
.data
.materials
.new(mat_name
)
196 mat
.diffuse_color
= colorsys
.hsv_to_rgb((h1
+ (h2
-h1
)/(count
)*i
)%1, 1, 1)[:] + (1,)
197 ob
.data
.materials
.append(mat
)
199 count
= len(ob
.material_slots
)
202 for p
in ob
.data
.polygons
:
203 verts_id
= np
.array([v
for v
in p
.vertices
])
204 face_weight
= weight
[verts_id
]
205 if self
.mode
== 'MIN': w
= face_weight
.min()
206 if self
.mode
== 'MAX': w
= face_weight
.max()
207 if self
.mode
== 'MEAN': w
= face_weight
.mean()
208 faces_weight
.append(w
)
209 faces_weight
= np
.array(faces_weight
)
210 faces_weight
= faces_weight
* count
211 faces_weight
.astype('int')
212 ob
.data
.polygons
.foreach_set('material_index',list(faces_weight
))
214 bpy
.ops
.object.mode_set(mode
='OBJECT')