1 # SPDX-FileCopyrightText: 2020 Alessandro Zomparelli
3 # SPDX-License-Identifier: GPL-2.0-or-later
6 # (c) Alessandro Zomparelli #
9 # http://www.co-de-it.com/ #
11 ################################################################################
19 from bpy
.types
import (
24 from bpy
.props
import (
36 class random_materials(Operator
):
37 bl_idname
= "object.random_materials"
38 bl_label
= "Random Materials"
39 bl_description
= "Assign random materials to the faces of the mesh"
40 bl_options
= {'REGISTER', 'UNDO'}
42 prefix
: StringProperty(
43 name
="Prefix", default
="Random.", description
="Name prefix")
45 color_A
: FloatVectorProperty(name
="Color A",
46 subtype
='COLOR_GAMMA',
51 color_B
: FloatVectorProperty(name
="Color B",
52 subtype
='COLOR_GAMMA',
57 hue
: FloatProperty(name
="Hue", min=0, max=1, default
=0.5)
58 hue_variation
: FloatProperty(name
="Hue Variation", min=0, max=1, default
=0.6)
61 name
="Seed", default
=0, description
="Random seed")
64 name
="Count", default
=3, min=2, description
="Count of random materials")
66 generate_materials
: BoolProperty(
67 name
="Generate Materials", default
=False, description
="Automatically generates new materials")
69 random_colors
: BoolProperty(
70 name
="Random Colors", default
=True, description
="Colors are automatically generated")
75 def poll(cls
, context
):
76 try: return context
.object.type == 'MESH'
79 def draw(self
, context
):
81 col
= layout
.column(align
=True)
82 col
.prop(self
, "seed")
83 col
.prop(self
, "generate_materials")
84 if self
.generate_materials
:
85 col
.prop(self
, "prefix")
87 col
.prop(self
, "count")
88 #row = col.row(align=True)
90 col
.label(text
='Colors:')
92 col
.prop(self
, "hue_variation")
93 #col.prop(self, "random_colors")
94 if not self
.random_colors
:
95 col
.prop(self
, "color_A")
96 col
.prop(self
, "color_B")
98 def execute(self
, context
):
99 bpy
.ops
.object.mode_set(mode
='OBJECT')
100 ob
= context
.active_object
101 if len(ob
.material_slots
) == 0 and not self
.executed
:
102 self
.generate_materials
= True
103 if self
.generate_materials
:
106 h1
= (self
.hue
- self
.hue_variation
/2)
107 h2
= (self
.hue
+ self
.hue_variation
/2)
109 ob
.data
.materials
.clear()
111 for i
in range(count
):
112 mat_name
= '{}{:03d}'.format(self
.prefix
,i
)
113 mat
= bpy
.data
.materials
.new(mat_name
)
114 if self
.random_colors
:
115 mat
.diffuse_color
= colorsys
.hsv_to_rgb((h1
+ (h2
-h1
)/(count
)*i
)%1, 1, 1)[:] + (1,)
117 mat
.diffuse_color
= list(colA
+ (colB
- colA
)/(count
-1)*i
) + [1]
118 ob
.data
.materials
.append(mat
)
120 count
= len(ob
.material_slots
)
121 np
.random
.seed(seed
=self
.seed
)
122 n_faces
= len(ob
.data
.polygons
)
124 rand
= list(np
.random
.randint(count
, size
=n_faces
))
125 ob
.data
.polygons
.foreach_set('material_index',rand
)
130 class weight_to_materials(Operator
):
131 bl_idname
= "object.weight_to_materials"
132 bl_label
= "Weight to Materials"
133 bl_description
= "Assign materials to the faces of the mesh according to the active Vertex Group"
134 bl_options
= {'REGISTER', 'UNDO'}
136 prefix
: StringProperty(
137 name
="Prefix", default
="Weight.", description
="Name prefix")
139 hue
: FloatProperty(name
="Hue", min=0, max=1, default
=0.5)
140 hue_variation
: FloatProperty(name
="Hue Variation", min=0, max=1, default
=0.3)
143 name
="Count", default
=3, min=2, description
="Count of random materials")
145 generate_materials
: BoolProperty(
146 name
="Generate Materials", default
=False, description
="Automatically generates new materials")
150 ('MIN', "Min", "Use the min weight value"),
151 ('MAX', "Max", "Use the max weight value"),
152 ('MEAN', "Mean", "Use the mean weight value")
161 def poll(cls
, context
):
162 try: return context
.object.type == 'MESH'
165 def draw(self
, context
):
167 col
= layout
.column(align
=True)
168 col
.prop(self
, "mode")
169 col
.prop(self
, "generate_materials")
170 if self
.generate_materials
:
171 col
.prop(self
, "prefix")
173 col
.prop(self
, "count")
174 #row = col.row(align=True)
176 col
.label(text
='Colors:')
177 col
.prop(self
, "hue")
178 col
.prop(self
, "hue_variation")
180 def execute(self
, context
):
181 ob
= context
.active_object
183 self
.vg
= ob
.vertex_groups
.active_index
184 vg
= ob
.vertex_groups
[self
.vg
]
186 self
.report({'ERROR'}, "The selected object doesn't have any Vertex Group")
188 weight
= get_weight_numpy(vg
, len(ob
.data
.vertices
))
189 if self
.generate_materials
:
190 h1
= (self
.hue
- self
.hue_variation
/2)
191 h2
= (self
.hue
+ self
.hue_variation
/2)
193 ob
.data
.materials
.clear()
195 for i
in range(count
):
196 mat_name
= '{}{:03d}'.format(self
.prefix
,i
)
197 mat
= bpy
.data
.materials
.new(mat_name
)
198 mat
.diffuse_color
= colorsys
.hsv_to_rgb((h1
+ (h2
-h1
)/(count
)*i
)%1, 1, 1)[:] + (1,)
199 ob
.data
.materials
.append(mat
)
201 count
= len(ob
.material_slots
)
204 for p
in ob
.data
.polygons
:
205 verts_id
= np
.array([v
for v
in p
.vertices
])
206 face_weight
= weight
[verts_id
]
207 if self
.mode
== 'MIN': w
= face_weight
.min()
208 if self
.mode
== 'MAX': w
= face_weight
.max()
209 if self
.mode
== 'MEAN': w
= face_weight
.mean()
210 faces_weight
.append(w
)
211 faces_weight
= np
.array(faces_weight
)
212 faces_weight
= faces_weight
* count
213 faces_weight
= list(faces_weight
.astype('int'))
214 ob
.data
.polygons
.foreach_set('material_index', faces_weight
)
216 bpy
.ops
.object.mode_set(mode
='OBJECT')