Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'mesh_tissue/material_tools.py')
-rw-r--r--mesh_tissue/material_tools.py231
1 files changed, 231 insertions, 0 deletions
diff --git a/mesh_tissue/material_tools.py b/mesh_tissue/material_tools.py
new file mode 100644
index 00000000..a734abeb
--- /dev/null
+++ b/mesh_tissue/material_tools.py
@@ -0,0 +1,231 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# #
+# (c) Alessandro Zomparelli #
+# (2020) #
+# #
+# http://www.co-de-it.com/ #
+# #
+################################################################################
+
+import bpy
+import numpy as np
+
+import colorsys
+from numpy import *
+
+from bpy.types import (
+ Operator,
+ Panel
+ )
+
+from bpy.props import (
+ BoolProperty,
+ EnumProperty,
+ FloatProperty,
+ IntProperty,
+ StringProperty,
+ FloatVectorProperty,
+ IntVectorProperty
+)
+
+from .utils import *
+
+class random_materials(Operator):
+ bl_idname = "object.random_materials"
+ bl_label = "Random Materials"
+ bl_description = "Assign random materials to the faces of the mesh"
+ bl_options = {'REGISTER', 'UNDO'}
+
+ prefix : StringProperty(
+ name="Prefix", default="Random.", description="Name prefix")
+
+ color_A : FloatVectorProperty(name="Color A",
+ subtype='COLOR_GAMMA',
+ min=0,
+ max=1,
+ default=[0,0,0])
+
+ color_B : FloatVectorProperty(name="Color B",
+ subtype='COLOR_GAMMA',
+ min=0,
+ max=1,
+ default=[1,1,1])
+
+ hue : FloatProperty(name="Hue", min=0, max=1, default=0.5)
+ hue_variation : FloatProperty(name="Hue Variation", min=0, max=1, default=0.6)
+
+ seed : IntProperty(
+ name="Seed", default=0, description="Random seed")
+
+ count : IntProperty(
+ name="Count", default=3, min=2, description="Count of random materials")
+
+ generate_materials : BoolProperty(
+ name="Generate Materials", default=False, description="Automatically generates new materials")
+
+ random_colors : BoolProperty(
+ name="Random Colors", default=True, description="Colors are automatically generated")
+
+ executed = False
+
+ @classmethod
+ def poll(cls, context):
+ try: return context.object.type == 'MESH'
+ except: return False
+
+ def draw(self, context):
+ layout = self.layout
+ col = layout.column(align=True)
+ col.prop(self, "seed")
+ col.prop(self, "generate_materials")
+ if self.generate_materials:
+ col.prop(self, "prefix")
+ col.separator()
+ col.prop(self, "count")
+ #row = col.row(align=True)
+ col.separator()
+ col.label(text='Colors:')
+ col.prop(self, "hue")
+ col.prop(self, "hue_variation")
+ #col.prop(self, "random_colors")
+ if not self.random_colors:
+ col.prop(self, "color_A")
+ col.prop(self, "color_B")
+
+ def execute(self, context):
+ bpy.ops.object.mode_set(mode='OBJECT')
+ ob = context.active_object
+ if len(ob.material_slots) == 0 and not self.executed:
+ self.generate_materials = True
+ if self.generate_materials:
+ colA = self.color_A
+ colB = self.color_B
+ h1 = (self.hue - self.hue_variation/2)
+ h2 = (self.hue + self.hue_variation/2)
+ count = self.count
+ ob.data.materials.clear()
+ materials = []
+ for i in range(count):
+ mat_name = '{}{:03d}'.format(self.prefix,i)
+ mat = bpy.data.materials.new(mat_name)
+ if self.random_colors:
+ mat.diffuse_color = colorsys.hsv_to_rgb((h1 + (h2-h1)/(count)*i)%1, 1, 1)[:] + (1,)
+ else:
+ mat.diffuse_color = list(colA + (colB - colA)/(count-1)*i) + [1]
+ ob.data.materials.append(mat)
+ else:
+ count = len(ob.material_slots)
+ np.random.seed(seed=self.seed)
+ n_faces = len(ob.data.polygons)
+ if count > 0:
+ rand = list(np.random.randint(count, size=n_faces))
+ ob.data.polygons.foreach_set('material_index',rand)
+ ob.data.update()
+ self.executed = True
+ return {'FINISHED'}
+
+class weight_to_materials(Operator):
+ bl_idname = "object.weight_to_materials"
+ bl_label = "Weight to Materials"
+ bl_description = "Assign materials to the faces of the mesh according to the active Vertex Group"
+ bl_options = {'REGISTER', 'UNDO'}
+
+ prefix : StringProperty(
+ name="Prefix", default="Weight.", description="Name prefix")
+
+ hue : FloatProperty(name="Hue", min=0, max=1, default=0.5)
+ hue_variation : FloatProperty(name="Hue Variation", min=0, max=1, default=0.3)
+
+ count : IntProperty(
+ name="Count", default=3, min=2, description="Count of random materials")
+
+ generate_materials : BoolProperty(
+ name="Generate Materials", default=False, description="Automatically generates new materials")
+
+ mode : EnumProperty(
+ items=(
+ ('MIN', "Min", "Use the min weight value"),
+ ('MAX', "Max", "Use the max weight value"),
+ ('MEAN', "Mean", "Use the mean weight value")
+ ),
+ default='MEAN',
+ name="Mode"
+ )
+
+ vg = None
+
+ @classmethod
+ def poll(cls, context):
+ try: return context.object.type == 'MESH'
+ except: return False
+
+ def draw(self, context):
+ layout = self.layout
+ col = layout.column(align=True)
+ col.prop(self, "mode")
+ col.prop(self, "generate_materials")
+ if self.generate_materials:
+ col.prop(self, "prefix")
+ col.separator()
+ col.prop(self, "count")
+ #row = col.row(align=True)
+ col.separator()
+ col.label(text='Colors:')
+ col.prop(self, "hue")
+ col.prop(self, "hue_variation")
+
+ def execute(self, context):
+ ob = context.active_object
+ if self.vg == None:
+ self.vg = ob.vertex_groups.active_index
+ vg = ob.vertex_groups[self.vg]
+ if vg == None:
+ self.report({'ERROR'}, "The selected object doesn't have any Vertex Group")
+ return {'CANCELLED'}
+ weight = get_weight_numpy(vg, len(ob.data.vertices))
+ if self.generate_materials:
+ h1 = (self.hue - self.hue_variation/2)
+ h2 = (self.hue + self.hue_variation/2)
+ count = self.count
+ ob.data.materials.clear()
+ materials = []
+ for i in range(count):
+ mat_name = '{}{:03d}'.format(self.prefix,i)
+ mat = bpy.data.materials.new(mat_name)
+ mat.diffuse_color = colorsys.hsv_to_rgb((h1 + (h2-h1)/(count)*i)%1, 1, 1)[:] + (1,)
+ ob.data.materials.append(mat)
+ else:
+ count = len(ob.material_slots)
+
+ faces_weight = []
+ for p in ob.data.polygons:
+ verts_id = np.array([v for v in p.vertices])
+ face_weight = weight[verts_id]
+ if self.mode == 'MIN': w = face_weight.min()
+ if self.mode == 'MAX': w = face_weight.max()
+ if self.mode == 'MEAN': w = face_weight.mean()
+ faces_weight.append(w)
+ faces_weight = np.array(faces_weight)
+ faces_weight = faces_weight * count
+ faces_weight.astype('int')
+ ob.data.polygons.foreach_set('material_index',list(faces_weight))
+ ob.data.update()
+ bpy.ops.object.mode_set(mode='OBJECT')
+ return {'FINISHED'}