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:
authorlijenstina <lijenstina@gmail.com>2017-06-25 17:01:21 +0300
committerlijenstina <lijenstina@gmail.com>2017-06-25 17:01:21 +0300
commit664ecb162c9beb5a19df67934866badb0ce2b3e4 (patch)
tree4a30024c2304560596f8887c53dec7fcc5956019 /mesh_tissue
parent58727bbb43c67b50a778a1cdb82e974b2d68c283 (diff)
Mesh Tissue: cleanup, fix remove base object crashes
Bumped version to 0.3.3 Pep8 Cleanup Fix crashes related to removing the base object with Settings and Refresh Move bl_info on top of the files Imports as tuples consistent prop definitions
Diffstat (limited to 'mesh_tissue')
-rw-r--r--mesh_tissue/__init__.py43
-rw-r--r--mesh_tissue/colors_groups_exchanger.py408
-rw-r--r--mesh_tissue/dual_mesh.py230
-rw-r--r--mesh_tissue/lattice.py334
-rw-r--r--mesh_tissue/tessellate_numpy.py962
-rw-r--r--mesh_tissue/uv_to_mesh.py81
6 files changed, 1263 insertions, 795 deletions
diff --git a/mesh_tissue/__init__.py b/mesh_tissue/__init__.py
index 7d8b0078..bef99625 100644
--- a/mesh_tissue/__init__.py
+++ b/mesh_tissue/__init__.py
@@ -16,8 +16,8 @@
#
# ##### END GPL LICENSE BLOCK #####
-# --------------------------------- TISSUE ------------------------------------#
-#-------------------------------- version 0.3 ---------------------------------#
+# --------------------------------- TISSUE ----------------------------------- #
+# ------------------------------- version 0.3 -------------------------------- #
# #
# Creates duplicates of selected mesh to active morphing the shape according #
# to target faces. #
@@ -28,7 +28,20 @@
# http://www.co-de-it.com/ #
# http://wiki.blender.org/index.php/Extensions:2.6/Py/Scripts/Mesh/Tissue #
# #
-################################################################################
+# ############################################################################ #
+
+bl_info = {
+ "name": "Tissue",
+ "author": "Alessandro Zomparelli (Co-de-iT)",
+ "version": (0, 3, 3),
+ "blender": (2, 7, 9),
+ "location": "",
+ "description": "Tools for Computational Design",
+ "warning": "",
+ "wiki_url": "https://wiki.blender.org/index.php/Extensions:2.6/"
+ "Py/Scripts/Mesh/Tissue",
+ "tracker_url": "https://plus.google.com/u/0/+AlessandroZomparelli/",
+ "category": "Mesh"}
if "bpy" in locals():
@@ -47,28 +60,14 @@ else:
from . import uv_to_mesh
import bpy
-from mathutils import Vector
-#bpy.types.Object.vertexgroup = bpy.props.StringProperty()
-#bpy.types.Panel.vertexgroup = bpy.props.StringProperty()
-
-bl_info = {
- "name": "Tissue",
- "author": "Alessandro Zomparelli (Co-de-iT)",
- "version": (0, 3, 2),
- "blender": (2, 7, 9),
- "location": "",
- "description": "Tools for Computational Design",
- "warning": "",
- "wiki_url": ("http://wiki.blender.org/index.php/Extensions:2.6/Py/Scripts/M"
- "esh/Tissue"),
- "tracker_url": "https://plus.google.com/u/0/+AlessandroZomparelli/",
- "category": "Mesh"}
+from bpy.props import PointerProperty
def register():
bpy.utils.register_module(__name__)
- bpy.types.Object.tissue_tessellate = bpy.props.PointerProperty(
- type=tessellate_numpy.tissue_tessellate_prop)
+ bpy.types.Object.tissue_tessellate = PointerProperty(
+ type=tessellate_numpy.tissue_tessellate_prop
+ )
def unregister():
@@ -78,6 +77,8 @@ def unregister():
lattice.unregister()
uv_to_mesh.unregister()
+ del bpy.types.Object.tissue_tessellate
+
if __name__ == "__main__":
register()
diff --git a/mesh_tissue/colors_groups_exchanger.py b/mesh_tissue/colors_groups_exchanger.py
index 49378c1e..b102a5b6 100644
--- a/mesh_tissue/colors_groups_exchanger.py
+++ b/mesh_tissue/colors_groups_exchanger.py
@@ -16,7 +16,7 @@
#
# ##### END GPL LICENSE BLOCK #####
-#-------------------------- COLORS / GROUPS EXCHANGER -------------------------#
+# ------------------------- COLORS / GROUPS EXCHANGER ------------------------ #
# #
# Vertex Color to Vertex Group allow you to convert colors channles to weight #
# maps. #
@@ -31,131 +31,172 @@
# #
# http://www.co-de-it.com/ #
# #
-################################################################################
-
-import bpy
-import math
-from math import pi, sin
+# ############################################################################ #
bl_info = {
"name": "Colors/Groups Exchanger",
"author": "Alessandro Zomparelli (Co-de-iT)",
- "version": (0, 3),
- "blender": (2, 7, 9),
+ "version": (0, 3, 1),
+ "blender": (2, 7, 8),
"location": "",
"description": ("Convert vertex colors channels to vertex groups and vertex"
" groups to colors"),
"warning": "",
"wiki_url": "",
- "tracker_url": "",
"category": "Mesh"}
-class vertex_colors_to_vertex_groups(bpy.types.Operator):
+
+import bpy
+from bpy.props import (
+ BoolProperty,
+ EnumProperty,
+ FloatProperty,
+ IntProperty,
+ )
+from bpy.types import Operator
+from math import (
+ pi, sin,
+ )
+
+
+class vertex_colors_to_vertex_groups(Operator):
bl_idname = "object.vertex_colors_to_vertex_groups"
bl_label = "Vertex Color"
+ bl_description = ("Convert the active Vertex Color into a Vertex Group")
bl_options = {'REGISTER', 'UNDO'}
- bl_description = ("Convert the active Vertex Color into a Vertex Group.")
-
- red = bpy.props.BoolProperty(
- name="red channel", default=False, description="convert red channel")
- green = bpy.props.BoolProperty(
- name="green channel", default=False,
- description="convert green channel")
- blue = bpy.props.BoolProperty(
- name="blue channel", default=False, description="convert blue channel")
- value = bpy.props.BoolProperty(
- name="value channel", default=True, description="convert value channel")
- invert = bpy.props.BoolProperty(
- name="invert", default=False, description="invert all color channels")
+
+ red = BoolProperty(
+ name="Red Channel",
+ default=False,
+ description="Convert Red Channel"
+ )
+ green = BoolProperty(
+ name="Green Channel",
+ default=False,
+ description="Convert Green Channel"
+ )
+ blue = BoolProperty(
+ name="Blue Channel",
+ default=False,
+ description="Convert Blue Channel"
+ )
+ value = BoolProperty(
+ name="Value Channel",
+ default=True,
+ description="Convert Value Channel"
+ )
+ invert = BoolProperty(
+ name="Invert",
+ default=False,
+ description="Invert all Color Channels"
+ )
def execute(self, context):
obj = bpy.context.active_object
- id = len(obj.vertex_groups)
- id_red = id
- id_green = id
- id_blue = id
- id_value = id
+ ids = len(obj.vertex_groups)
+ id_red = ids
+ id_green = ids
+ id_blue = ids
+ id_value = ids
boolCol = len(obj.data.vertex_colors)
- if(boolCol): col_name = obj.data.vertex_colors.active.name
+ if boolCol:
+ col_name = obj.data.vertex_colors.active.name
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.select_all(action='SELECT')
- if(self.red and boolCol):
+ if self.red and boolCol:
bpy.ops.object.vertex_group_add()
bpy.ops.object.vertex_group_assign()
- id_red = id
+ id_red = ids
obj.vertex_groups[id_red].name = col_name + '_red'
- id+=1
- if(self.green and boolCol):
+ ids += 1
+ if self.green and boolCol:
bpy.ops.object.vertex_group_add()
bpy.ops.object.vertex_group_assign()
- id_green = id
+ id_green = ids
obj.vertex_groups[id_green].name = col_name + '_green'
- id+=1
- if(self.blue and boolCol):
+ ids += 1
+ if self.blue and boolCol:
bpy.ops.object.vertex_group_add()
bpy.ops.object.vertex_group_assign()
- id_blue = id
+ id_blue = ids
obj.vertex_groups[id_blue].name = col_name + '_blue'
- id+=1
- if(self.value and boolCol):
+ ids += 1
+ if self.value and boolCol:
bpy.ops.object.vertex_group_add()
bpy.ops.object.vertex_group_assign()
- id_value = id
+ id_value = ids
obj.vertex_groups[id_value].name = col_name + '_value'
- id+=1
+ ids += 1
mult = 1
- if(self.invert): mult = -1
+ if self.invert:
+ mult = -1
+
bpy.ops.object.mode_set(mode='OBJECT')
sub_red = 1 + self.value + self.blue + self.green
sub_green = 1 + self.value + self.blue
sub_blue = 1 + self.value
sub_value = 1
- id = len(obj.vertex_groups)
- if(id_red <= id and id_green <= id and id_blue <= id and id_value <= \
- id and boolCol):
+ ids = len(obj.vertex_groups)
+ if (id_red <= ids and id_green <= ids and id_blue <= ids and id_value <=
+ ids and boolCol):
v_colors = obj.data.vertex_colors.active.data
i = 0
for f in obj.data.polygons:
for v in f.vertices:
gr = obj.data.vertices[v].groups
- if(self.red): gr[min(len(gr)-sub_red, id_red)].weight = \
- self.invert + mult * v_colors[i].color.r
- if(self.green): gr[min(len(gr)-sub_green, id_green)].weight\
- = self.invert + mult * v_colors[i].color.g
- if(self.blue): gr[min(len(gr)-sub_blue, id_blue)].weight = \
- self.invert + mult * v_colors[i].color.b
- if(self.value): gr[min(len(gr)-sub_value, id_value)].weight\
- = self.invert + mult * v_colors[i].color.v
- i+=1
+ if self.red:
+ gr[min(len(gr) - sub_red, id_red)].weight = \
+ self.invert + mult * v_colors[i].color.r
+
+ if self.green:
+ gr[min(len(gr) - sub_green, id_green)].weight = \
+ self.invert + mult * v_colors[i].color.g
+
+ if self.blue:
+ gr[min(len(gr) - sub_blue, id_blue)].weight = \
+ self.invert + mult * v_colors[i].color.b
+
+ if self.value:
+ gr[min(len(gr) - sub_value, id_value)].weight = \
+ self.invert + mult * v_colors[i].color.v
+ i += 1
bpy.ops.paint.weight_paint_toggle()
+
return {'FINISHED'}
-class vertex_group_to_vertex_colors(bpy.types.Operator):
+class vertex_group_to_vertex_colors(Operator):
bl_idname = "object.vertex_group_to_vertex_colors"
bl_label = "Vertex Group"
+ bl_description = ("Convert the active Vertex Group into a Vertex Color")
bl_options = {'REGISTER', 'UNDO'}
- bl_description = ("Convert the active Vertex Group into a Vertex Color.")
-
- channel = bpy.props.EnumProperty(
- items=[('Blue', 'Blue Channel', 'Convert to Blue Channel'),
- ('Green', 'Green Channel', 'Convert to Green Channel'),
- ('Red', 'Red Channel', 'Convert to Red Channel'),
- ('Value', 'Value Channel', 'Convert to Grayscale'),
- ('False Colors', 'False Colors', 'Convert to False Colors')],
- name="Convert to", description="Choose how to convert vertex group",
- default="Value", options={'LIBRARY_EDITABLE'})
- invert = bpy.props.BoolProperty(
- name="invert", default=False, description="invert color channel")
+ channel = EnumProperty(
+ items=[('Blue', 'Blue Channel', 'Convert to Blue Channel'),
+ ('Green', 'Green Channel', 'Convert to Green Channel'),
+ ('Red', 'Red Channel', 'Convert to Red Channel'),
+ ('Value', 'Value Channel', 'Convert to Grayscale'),
+ ('False Colors', 'False Colors', 'Convert to False Colors')],
+ name="Convert to",
+ description="Choose how to convert vertex group",
+ default="Value",
+ options={'LIBRARY_EDITABLE'}
+ )
+
+ invert = BoolProperty(
+ name="Invert",
+ default=False,
+ description="Invert Color Channel"
+ )
def execute(self, context):
obj = bpy.context.active_object
group_id = obj.vertex_groups.active_index
+
if (group_id == -1):
return {'FINISHED'}
@@ -165,37 +206,45 @@ class vertex_group_to_vertex_colors(bpy.types.Operator):
colors_id = obj.data.vertex_colors.active_index
colors_name = group_name
- if(self.channel == 'False Colors'): colors_name += "_false_colors"
- elif(self.channel == 'Value'): colors_name += "_value"
- elif(self.channel == 'Red'): colors_name += "_red"
- elif(self.channel == 'Green'): colors_name += "_green"
- elif(self.channel == 'Blue'): colors_name += "_blue"
+ if(self.channel == 'False Colors'):
+ colors_name += "_false_colors"
+ elif(self.channel == 'Value'):
+ colors_name += "_value"
+ elif(self.channel == 'Red'):
+ colors_name += "_red"
+ elif(self.channel == 'Green'):
+ colors_name += "_green"
+ elif(self.channel == 'Blue'):
+ colors_name += "_blue"
bpy.context.object.data.vertex_colors[colors_id].name = colors_name
v_colors = obj.data.vertex_colors.active.data
mult = 1
- if(self.invert): mult = -1
+ if self.invert:
+ mult = -1
i = 0
for f in obj.data.polygons:
for v in f.vertices:
gr = obj.data.vertices[v].groups
- if(self.channel == 'False Colors'): v_colors[i].color = (0,0,1)
- else: v_colors[i].color = (0,0,0)
+ if(self.channel == 'False Colors'):
+ v_colors[i].color = (0, 0, 1)
+ else:
+ v_colors[i].color = (0, 0, 0)
for g in gr:
if g.group == group_id:
if(self.channel == 'False Colors'):
if g.weight < 0.25:
- v_colors[i].color = (0, g.weight*4, 1)
+ v_colors[i].color = (0, g.weight * 4, 1)
elif g.weight < 0.5:
- v_colors[i].color = (0, 1, 1-(g.weight-0.25)*4)
+ v_colors[i].color = (0, 1, 1 - (g.weight - 0.25) * 4)
elif g.weight < 0.75:
- v_colors[i].color = ((g.weight-0.5)*4,1,0)
+ v_colors[i].color = ((g.weight - 0.5) * 4, 1, 0)
else:
- v_colors[i].color = (1,1-(g.weight-0.75)*4,0)
+ v_colors[i].color = (1, 1 - (g.weight - 0.75) * 4, 0)
elif(self.channel == 'Value'):
v_colors[i].color = (
self.invert + mult * g.weight,
@@ -203,46 +252,66 @@ class vertex_group_to_vertex_colors(bpy.types.Operator):
self.invert + mult * g.weight)
elif(self.channel == 'Red'):
v_colors[i].color = (
- self.invert + mult * g.weight,0,0)
+ self.invert + mult * g.weight, 0, 0)
elif(self.channel == 'Green'):
v_colors[i].color = (
- 0, self.invert + mult * g.weight,0)
+ 0, self.invert + mult * g.weight, 0)
elif(self.channel == 'Blue'):
v_colors[i].color = (
- 0,0, self.invert + mult * g.weight)
- i+=1
+ 0, 0, self.invert + mult * g.weight)
+ i += 1
bpy.ops.paint.vertex_paint_toggle()
bpy.context.object.data.vertex_colors[colors_id].active_render = True
return {'FINISHED'}
-class curvature_to_vertex_groups(bpy.types.Operator):
+
+class curvature_to_vertex_groups(Operator):
bl_idname = "object.curvature_to_vertex_groups"
bl_label = "Curvature"
- bl_options = {'REGISTER', 'UNDO'}
- invert = bpy.props.BoolProperty(
- name="invert", default=False, description="invert values")
bl_description = ("Generate a Vertex Group based on the curvature of the"
- "mesh. Is based on Dirty Vertex Color.")
-
- blur_strength = bpy.props.FloatProperty(
- name="Blur Strength", default=1, min=0.001,
- max=1, description="Blur strength per iteration")
-
- blur_iterations = bpy.props.IntProperty(
- name="Blur Iterations", default=1, min=0,
- max=40, description="Number of times to blur the values")
-
- min_angle = bpy.props.FloatProperty(
- name="Min Angle", default=0, min=0,
- max=pi/2, subtype='ANGLE', description="Minimum angle")
-
- max_angle = bpy.props.FloatProperty(
- name="Max Angle", default=pi, min=pi/2,
- max=pi, subtype='ANGLE', description="Maximum angle")
+ "mesh. Is based on Dirty Vertex Color")
+ bl_options = {'REGISTER', 'UNDO'}
- invert = bpy.props.BoolProperty(
- name="Invert", default=False,
- description="Invert the curvature map")
+ invert = BoolProperty(
+ name="Invert",
+ default=False,
+ description="Invert Values"
+ )
+ blur_strength = FloatProperty(
+ name="Blur Strength",
+ default=1,
+ min=0.001,
+ max=1,
+ description="Blur strength per iteration"
+ )
+ blur_iterations = IntProperty(
+ name="Blur Iterations",
+ default=1,
+ min=0,
+ max=40,
+ description="Number of times to blur the values"
+ )
+ min_angle = FloatProperty(
+ name="Min Angle",
+ default=0,
+ min=0,
+ max=pi / 2,
+ subtype='ANGLE',
+ description="Minimum angle"
+ )
+ max_angle = FloatProperty(
+ name="Max Angle",
+ default=pi,
+ min=pi / 2,
+ max=pi,
+ subtype='ANGLE',
+ description="Maximum angle"
+ )
+ invert = BoolProperty(
+ name="Invert",
+ default=False,
+ description="Invert the curvature map"
+ )
def execute(self, context):
bpy.ops.object.mode_set(mode='OBJECT')
@@ -251,22 +320,35 @@ class curvature_to_vertex_groups(bpy.types.Operator):
vertex_colors[-1].active = True
vertex_colors[-1].active_render = True
vertex_colors[-1].name = "Curvature"
- for c in vertex_colors[-1].data: c.color.r, c.color.g, c.color.b = 1,1,1
+
+ for c in vertex_colors[-1].data:
+ c.color.r, c.color.g, c.color.b = 1, 1, 1
+
bpy.ops.object.mode_set(mode='VERTEX_PAINT')
- bpy.ops.paint.vertex_color_dirt(blur_strength=self.blur_strength, blur_iterations=self.blur_iterations, clean_angle=self.max_angle, dirt_angle=self.min_angle)
+ bpy.ops.paint.vertex_color_dirt(
+ blur_strength=self.blur_strength,
+ blur_iterations=self.blur_iterations,
+ clean_angle=self.max_angle,
+ dirt_angle=self.min_angle
+ )
bpy.ops.object.vertex_colors_to_vertex_groups(invert=self.invert)
bpy.ops.mesh.vertex_color_remove()
+
return {'FINISHED'}
-class face_area_to_vertex_groups(bpy.types.Operator):
+class face_area_to_vertex_groups(Operator):
bl_idname = "object.face_area_to_vertex_groups"
bl_label = "Area"
- bl_options = {'REGISTER', 'UNDO'}
- invert = bpy.props.BoolProperty(
- name="invert", default=False, description="invert values")
bl_description = ("Generate a Vertex Group based on the area of individual"
- "faces.")
+ "faces")
+ bl_options = {'REGISTER', 'UNDO'}
+
+ invert = BoolProperty(
+ name="Invert",
+ default=False,
+ description="Invert Values"
+ )
def execute(self, context):
obj = bpy.context.active_object
@@ -278,65 +360,88 @@ class face_area_to_vertex_groups(bpy.types.Operator):
obj.vertex_groups[id_value].name = 'faces_area'
mult = 1
- if self.invert: mult = -1
+ if self.invert:
+ mult = -1
bpy.ops.object.mode_set(mode='OBJECT')
min_area = False
max_area = False
- n_values = [0]*len(obj.data.vertices)
- values = [0]*len(obj.data.vertices)
+ n_values = [0] * len(obj.data.vertices)
+ values = [0] * len(obj.data.vertices)
for p in obj.data.polygons:
for v in p.vertices:
n_values[v] += 1
values[v] += p.area
if min_area:
- if min_area > p.area: min_area = p.area
- else: min_area = p.area
+ if min_area > p.area:
+ min_area = p.area
+ else:
+ min_area = p.area
if max_area:
- if max_area < p.area: max_area = p.area
- else: max_area = p.area
+ if max_area < p.area:
+ max_area = p.area
+ else:
+ max_area = p.area
- id = len(obj.vertex_groups)
for v in obj.data.vertices:
gr = v.groups
index = v.index
try:
- gr[min(len(gr)-1, id_value)].weight = self.invert + mult * \
- ((values[index] / n_values[index] - min_area)/(max_area - \
- min_area))
+ gr[min(len(gr) - 1, id_value)].weight = \
+ self.invert + mult * \
+ ((values[index] / n_values[index] - min_area) /
+ (max_area - min_area))
except:
- gr[min(len(gr)-1, id_value)].weight = 0.5
+ gr[min(len(gr) - 1, id_value)].weight = 0.5
+
bpy.ops.paint.weight_paint_toggle()
+
return {'FINISHED'}
-class harmonic_weight(bpy.types.Operator):
+class harmonic_weight(Operator):
bl_idname = "object.harmonic_weight"
bl_label = "Harmonic"
+ bl_description = "Create an harmonic variation of the active Vertex Group"
bl_options = {'REGISTER', 'UNDO'}
- bl_description = ("Create an harmonic variation of the active Vertex Group")
- freq = bpy.props.FloatProperty(
- name="Frequency", default=20, soft_min=0,
- soft_max=100, description="Wave frequency")
-
- amp = bpy.props.FloatProperty(
- name="Amplitude", default=1, soft_min=0,
- soft_max=10, description="Wave amplitude")
-
- midlevel = bpy.props.FloatProperty(
- name="Midlevel", default=0, min=-1,
- max=1, description="Midlevel")
-
- add = bpy.props.FloatProperty(
- name="Add", default=0, min=-1,
- max=1, description="Add to the Weight")
-
- mult = bpy.props.FloatProperty(
- name="Multiply", default=0, min=0,
- max=1, description="Multiply for he Weight")
+ freq = FloatProperty(
+ name="Frequency",
+ default=20,
+ soft_min=0,
+ soft_max=100,
+ description="Wave frequency"
+ )
+ amp = FloatProperty(
+ name="Amplitude",
+ default=1,
+ soft_min=0,
+ soft_max=10,
+ description="Wave amplitude"
+ )
+ midlevel = FloatProperty(
+ name="Midlevel",
+ default=0,
+ min=-1,
+ max=1,
+ description="Midlevel"
+ )
+ add = FloatProperty(
+ name="Add",
+ default=0,
+ min=-1,
+ max=1,
+ description="Add to the Weight"
+ )
+ mult = FloatProperty(
+ name="Multiply",
+ default=0,
+ min=0,
+ max=1,
+ description="Multiply for he Weight"
+ )
def execute(self, context):
obj = bpy.context.active_object
@@ -344,13 +449,17 @@ class harmonic_weight(bpy.types.Operator):
group_id = obj.vertex_groups.active_index
for v in obj.data.vertices:
val = v.groups[group_id].weight
- v.groups[group_id].weight = (self.amp*(sin(val*self.freq) - self.midlevel)/2 + 0.5 + self.add*val)*(1-(1-val)*self.mult)
+ v.groups[group_id].weight = (self.amp * (sin(val * self.freq) -
+ self.midlevel) / 2 + 0.5 + self.add * val) * \
+ (1 - (1 - val) * self.mult)
except:
self.report({'ERROR'}, "Active object doesn't have vertex groups")
+
return {'CANCELLED'}
+
bpy.ops.object.mode_set(mode='WEIGHT_PAINT')
- return {'FINISHED'}
+ return {'FINISHED'}
class colors_groups_exchanger_panel(bpy.types.Panel):
@@ -359,7 +468,6 @@ class colors_groups_exchanger_panel(bpy.types.Panel):
bl_space_type = "VIEW_3D"
bl_region_type = "TOOLS"
bl_options = {'DEFAULT_CLOSED'}
- #bl_context = "objectmode"
def draw(self, context):
try:
diff --git a/mesh_tissue/dual_mesh.py b/mesh_tissue/dual_mesh.py
index 29926250..3b20e138 100644
--- a/mesh_tissue/dual_mesh.py
+++ b/mesh_tissue/dual_mesh.py
@@ -16,8 +16,8 @@
#
# ##### END GPL LICENSE BLOCK #####
-#---------------------------------- DUAL MESH ---------------------------------#
-#--------------------------------- version 0.3 --------------------------------#
+# --------------------------------- DUAL MESH -------------------------------- #
+# -------------------------------- version 0.3 ------------------------------- #
# #
# Convert a generic mesh to its dual. With open meshes it can get some wired #
# effect on the borders. #
@@ -27,10 +27,7 @@
# #
# http://www.co-de-it.com/ #
# #
-################################################################################
-
-import bpy
-import bmesh
+# ############################################################################ #
bl_info = {
"name": "Dual Mesh",
@@ -41,53 +38,71 @@ bl_info = {
"description": "Convert a generic mesh to its dual",
"warning": "",
"wiki_url": "",
- "tracker_url": "",
"category": "Mesh"}
-class dual_mesh(bpy.types.Operator):
+import bpy
+from bpy.types import Operator
+from bpy.props import (
+ BoolProperty,
+ EnumProperty,
+ )
+import bmesh
+
+
+class dual_mesh(Operator):
bl_idname = "object.dual_mesh"
bl_label = "Dual Mesh"
+ bl_description = ("Convert a generic mesh into a polygonal mesh")
bl_options = {'REGISTER', 'UNDO'}
- bl_description = ("Convert a generic mesh into a polygonal mesh.")
-
- quad_method = bpy.props.EnumProperty(
- items=[('BEAUTY', 'Beauty',
- 'Split the quads in nice triangles, slower method'),
- ('FIXED', 'Fixed', 'Split the quads on the 1st and 3rd vertices'),
- ('FIXED_ALTERNATE', 'Fixed Alternate', ('Split the quads on the 2nd and'
- ' 4th vertices')),
- ('SHORTEST_DIAGONAL', 'Shortest Diagonal', ('Split the quads based on '
- 'the distance between the vertices'))],
- name="Quad Method",
- description="Method for splitting the quads into triangles",
- default="FIXED", options={'LIBRARY_EDITABLE'})
-
- polygon_method = bpy.props.EnumProperty(
- items=[
- ('BEAUTY', 'Beauty', 'Arrange the new triangles evenly'),
- ('CLIP', 'Clip',
- 'Split the polygons with an ear clipping algorithm')],
- name="Polygon Method",
- description="Method for splitting the polygons into triangles",
- default="BEAUTY", options={'LIBRARY_EDITABLE'})
-
- preserve_borders = bpy.props.BoolProperty(
- name="Preserve Borders", default=True,
- description="Preserve original borders")
-
- apply_modifiers = bpy.props.BoolProperty(
- name="Apply Modifiers", default=True,
- description="Apply object's modifiers")
+
+ quad_method = EnumProperty(
+ items=[('BEAUTY', 'Beauty',
+ 'Split the quads in nice triangles, slower method'),
+ ('FIXED', 'Fixed',
+ 'Split the quads on the 1st and 3rd vertices'),
+ ('FIXED_ALTERNATE', 'Fixed Alternate',
+ 'Split the quads on the 2nd and 4th vertices'),
+ ('SHORTEST_DIAGONAL', 'Shortest Diagonal',
+ 'Split the quads based on the distance between the vertices')
+ ],
+ name="Quad Method",
+ description="Method for splitting the quads into triangles",
+ default="FIXED",
+ options={'LIBRARY_EDITABLE'}
+ )
+ polygon_method = EnumProperty(
+ items=[
+ ('BEAUTY', 'Beauty', 'Arrange the new triangles evenly'),
+ ('CLIP', 'Clip',
+ 'Split the polygons with an ear clipping algorithm')],
+ name="Polygon Method",
+ description="Method for splitting the polygons into triangles",
+ default="BEAUTY",
+ options={'LIBRARY_EDITABLE'}
+ )
+ preserve_borders = BoolProperty(
+ name="Preserve Borders",
+ default=True,
+ description="Preserve original borders"
+ )
+ apply_modifiers = BoolProperty(
+ name="Apply Modifiers",
+ default=True,
+ description="Apply object's modifiers"
+ )
def execute(self, context):
mode = context.mode
- if mode == 'EDIT_MESH': mode = 'EDIT'
+ if mode == 'EDIT_MESH':
+ mode = 'EDIT'
act = bpy.context.active_object
if mode != 'OBJECT':
sel = [act]
bpy.ops.object.mode_set(mode='OBJECT')
- else: sel = bpy.context.selected_objects
+ else:
+ sel = bpy.context.selected_objects
doneMeshes = []
+
'''
if self.new_object:
bpy.ops.object.duplicate_move()
@@ -97,9 +112,12 @@ class dual_mesh(bpy.types.Operator):
bpy.context.scene.objects.active = bpy.context.selected_objects[i]
sel = bpy.context.selected_objects
'''
+
for ob0 in sel:
- if ob0.type != 'MESH': continue
- if ob0.data.name in doneMeshes: continue
+ if ob0.type != 'MESH':
+ continue
+ if ob0.data.name in doneMeshes:
+ continue
ob = ob0
mesh_name = ob0.data.name
@@ -108,70 +126,80 @@ class dual_mesh(bpy.types.Operator):
n_users = ob0.data.users
count = 0
for o in bpy.data.objects:
- if o.type != 'MESH': continue
+ if o.type != 'MESH':
+ continue
if o.data.name == mesh_name:
- count+=1
+ count += 1
clones.append(o)
- if count == n_users: break
- if self.apply_modifiers: bpy.ops.object.convert(target='MESH')
+ if count == n_users:
+ break
+
+ if self.apply_modifiers:
+ bpy.ops.object.convert(target='MESH')
ob.data = ob.data.copy()
bpy.ops.object.select_all(action='DESELECT')
ob.select = True
bpy.context.scene.objects.active = ob0
- bpy.ops.object.mode_set(mode = 'EDIT')
+ bpy.ops.object.mode_set(mode='EDIT')
# prevent borders erosion
bpy.ops.mesh.select_mode(
- use_extend=False, use_expand=False, type='EDGE')
+ use_extend=False, use_expand=False, type='EDGE'
+ )
bpy.ops.mesh.select_non_manifold(
- extend=False, use_wire=False, use_boundary=True,
- use_multi_face=False, use_non_contiguous=False,
- use_verts=False)
+ extend=False, use_wire=False, use_boundary=True,
+ use_multi_face=False, use_non_contiguous=False,
+ use_verts=False
+ )
bpy.ops.mesh.extrude_region_move(
- MESH_OT_extrude_region={"mirror":False},
- TRANSFORM_OT_translate={"value":(0, 0, 0),
- "constraint_axis":(False, False, False),
- "constraint_orientation":'GLOBAL', "mirror":False,
- "proportional":'DISABLED',
- "proportional_edit_falloff":'SMOOTH', "proportional_size":1,
- "snap":False, "snap_target":'CLOSEST',
- "snap_point":(0, 0, 0), "snap_align":False,
- "snap_normal":(0, 0, 0), "gpencil_strokes":False,
- "texture_space":False, "remove_on_cancel":False,
- "release_confirm":False})
-
+ MESH_OT_extrude_region={"mirror": False},
+ TRANSFORM_OT_translate={"value": (0, 0, 0),
+ "constraint_axis": (False, False, False),
+ "constraint_orientation": 'GLOBAL', "mirror": False,
+ "proportional": 'DISABLED',
+ "proportional_edit_falloff": 'SMOOTH', "proportional_size": 1,
+ "snap": False, "snap_target": 'CLOSEST',
+ "snap_point": (0, 0, 0), "snap_align": False,
+ "snap_normal": (0, 0, 0), "gpencil_strokes": False,
+ "texture_space": False, "remove_on_cancel": False,
+ "release_confirm": False}
+ )
bpy.ops.mesh.select_mode(
- use_extend=False, use_expand=False, type='VERT',
- action='TOGGLE')
- bpy.ops.mesh.select_all(action = 'SELECT')
+ use_extend=False, use_expand=False, type='VERT',
+ action='TOGGLE'
+ )
+ bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.mesh.quads_convert_to_tris(
- quad_method=self.quad_method, ngon_method=self.polygon_method)
- bpy.ops.mesh.select_all(action = 'DESELECT')
- bpy.ops.object.mode_set(mode = 'OBJECT')
+ quad_method=self.quad_method, ngon_method=self.polygon_method
+ )
+ bpy.ops.mesh.select_all(action='DESELECT')
+ bpy.ops.object.mode_set(mode='OBJECT')
bpy.ops.object.modifier_add(type='SUBSURF')
ob.modifiers[-1].name = "dual_mesh_subsurf"
while True:
bpy.ops.object.modifier_move_up(modifier="dual_mesh_subsurf")
- if ob.modifiers[0].name == "dual_mesh_subsurf": break
- bpy.ops.object.modifier_apply(
- apply_as='DATA', modifier='dual_mesh_subsurf')
+ if ob.modifiers[0].name == "dual_mesh_subsurf":
+ break
- bpy.ops.object.mode_set(mode = 'EDIT')
- bpy.ops.mesh.select_all(action = 'DESELECT')
+ bpy.ops.object.modifier_apply(
+ apply_as='DATA', modifier='dual_mesh_subsurf'
+ )
+ bpy.ops.object.mode_set(mode='EDIT')
+ bpy.ops.mesh.select_all(action='DESELECT')
verts = ob.data.vertices
- bpy.ops.object.mode_set(mode = 'OBJECT')
+ bpy.ops.object.mode_set(mode='OBJECT')
verts[0].select = True
- bpy.ops.object.mode_set(mode = 'EDIT')
+ bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.select_more(use_face_step=False)
bpy.ops.mesh.select_similar(
type='EDGE', compare='EQUAL', threshold=0.01)
bpy.ops.mesh.select_all(action='INVERT')
bpy.ops.mesh.dissolve_verts()
- bpy.ops.mesh.select_all(action = 'DESELECT')
+ bpy.ops.mesh.select_all(action='DESELECT')
bpy.ops.mesh.select_non_manifold(
extend=False, use_wire=False, use_boundary=True,
@@ -179,18 +207,18 @@ class dual_mesh(bpy.types.Operator):
bpy.ops.mesh.select_more()
# find boundaries
- bpy.ops.object.mode_set(mode = 'OBJECT')
+ bpy.ops.object.mode_set(mode='OBJECT')
bound_v = [v.index for v in ob.data.vertices if v.select]
bound_e = [e.index for e in ob.data.edges if e.select]
bound_p = [p.index for p in ob.data.polygons if p.select]
- bpy.ops.object.mode_set(mode = 'EDIT')
+ bpy.ops.object.mode_set(mode='EDIT')
# select quad faces
bpy.context.tool_settings.mesh_select_mode = (False, False, True)
bpy.ops.mesh.select_face_by_sides(number=4, extend=False)
# deselect boundaries
- bpy.ops.object.mode_set(mode = 'OBJECT')
+ bpy.ops.object.mode_set(mode='OBJECT')
for i in bound_v:
bpy.context.active_object.data.vertices[i].select = False
for i in bound_e:
@@ -198,17 +226,18 @@ class dual_mesh(bpy.types.Operator):
for i in bound_p:
bpy.context.active_object.data.polygons[i].select = False
- bpy.ops.object.mode_set(mode = 'EDIT')
+ bpy.ops.object.mode_set(mode='EDIT')
bpy.context.tool_settings.mesh_select_mode = (False, False, True)
bpy.ops.mesh.edge_face_add()
bpy.context.tool_settings.mesh_select_mode = (True, False, False)
- bpy.ops.mesh.select_all(action = 'DESELECT')
+ bpy.ops.mesh.select_all(action='DESELECT')
# delete boundaries
bpy.ops.mesh.select_non_manifold(
- extend=False, use_wire=True, use_boundary=True,
- use_multi_face=False, use_non_contiguous=False, use_verts=True)
+ extend=False, use_wire=True, use_boundary=True,
+ use_multi_face=False, use_non_contiguous=False, use_verts=True
+ )
bpy.ops.mesh.delete(type='VERT')
# remove middle vertices
@@ -219,38 +248,47 @@ class dual_mesh(bpy.types.Operator):
# dissolve
bpy.ops.mesh.dissolve_verts()
- bpy.ops.mesh.select_all(action = 'DESELECT')
+ bpy.ops.mesh.select_all(action='DESELECT')
# remove border faces
if not self.preserve_borders:
bpy.ops.mesh.select_non_manifold(
extend=False, use_wire=False, use_boundary=True,
- use_multi_face=False, use_non_contiguous=False, use_verts=False)
+ use_multi_face=False, use_non_contiguous=False, use_verts=False
+ )
bpy.ops.mesh.select_more()
bpy.ops.mesh.delete(type='FACE')
# clean wires
bpy.ops.mesh.select_non_manifold(
- extend=False, use_wire=True, use_boundary=False,
- use_multi_face=False, use_non_contiguous=False, use_verts=False)
+ extend=False, use_wire=True, use_boundary=False,
+ use_multi_face=False, use_non_contiguous=False, use_verts=False
+ )
bpy.ops.mesh.delete(type='EDGE')
- bpy.ops.object.mode_set(mode = 'OBJECT')
+ bpy.ops.object.mode_set(mode='OBJECT')
ob0.data.name = mesh_name
doneMeshes.append(mesh_name)
- for o in clones: o.data = ob.data
- for o in sel: o.select = True
+
+ for o in clones:
+ o.data = ob.data
+
+ for o in sel:
+ o.select = True
+
bpy.context.scene.objects.active = act
bpy.ops.object.mode_set(mode=mode)
+
return {'FINISHED'}
-'''
+
+"""
class dual_mesh_panel(bpy.types.Panel):
bl_label = "Dual Mesh"
bl_category = "Tools"
bl_space_type = "VIEW_3D"
bl_region_type = "TOOLS"
- bl_context = (("objectmode"))
+ bl_context = "objectmode"
def draw(self, context):
layout = self.layout
@@ -260,17 +298,17 @@ class dual_mesh_panel(bpy.types.Panel):
col.operator("object.dual_mesh")
except:
pass
-'''
+"""
def register():
bpy.utils.register_class(dual_mesh)
- #bpy.utils.register_class(dual_mesh_panel)
+ # bpy.utils.register_class(dual_mesh_panel)
def unregister():
bpy.utils.unregister_class(dual_mesh)
- #bpy.utils.unregister_class(dual_mesh_panel)
+ # bpy.utils.unregister_class(dual_mesh_panel)
if __name__ == "__main__":
diff --git a/mesh_tissue/lattice.py b/mesh_tissue/lattice.py
index 685d5664..737b4c87 100644
--- a/mesh_tissue/lattice.py
+++ b/mesh_tissue/lattice.py
@@ -15,8 +15,8 @@
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
-#---------------------------- LATTICE ALONG SURFACE ---------------------------#
-#--------------------------------- version 0.3 --------------------------------#
+# --------------------------- LATTICE ALONG SURFACE -------------------------- #
+# -------------------------------- version 0.3 ------------------------------- #
# #
# Automatically generate and assign a lattice that follows the active surface. #
# #
@@ -25,10 +25,7 @@
# #
# http://www.co-de-it.com/ #
# #
-################################################################################
-
-import bpy, bmesh
-from mathutils import Vector, Matrix
+# ############################################################################ #
bl_info = {
"name": "Lattice",
@@ -39,10 +36,19 @@ bl_info = {
"description": "Generate a Lattice based on a grid mesh",
"warning": "",
"wiki_url": "",
- "tracker_url": "",
"category": "Mesh"}
+import bpy
+import bmesh
+from bpy.types import Operator
+from bpy.props import (
+ BoolProperty,
+ FloatProperty,
+ )
+from mathutils import Vector
+
+
def not_in(element, grid):
output = True
for loop in grid:
@@ -51,6 +57,7 @@ def not_in(element, grid):
break
return output
+
def grid_from_mesh(mesh, swap_uv):
bm = bmesh.new()
bm.from_mesh(mesh)
@@ -66,21 +73,27 @@ def grid_from_mesh(mesh, swap_uv):
# storing first point
verts_candidates = []
- if len(faces_grid) == 0: verts_candidates = bm.verts # for first loop check all vertices
- else: verts_candidates = [v for v in bm.faces[faces_grid[-1][0]].verts if not_in(v.index, verts_grid)] # for other loops start form the vertices of the first face the last loop, skipping already used vertices
+ if len(faces_grid) == 0:
+ # for first loop check all vertices
+ verts_candidates = bm.verts
+ else:
+ # for other loops start form the vertices of the first face
+ # the last loop, skipping already used vertices
+ verts_candidates = [v for v in bm.faces[faces_grid[-1][0]].verts if not_in(v.index, verts_grid)]
# check for last loop
is_last = False
for vert in verts_candidates:
- if len(vert.link_faces) == 1: # check if corner vertex
+ if len(vert.link_faces) == 1: # check if corner vertex
vert.select = True
verts_loop.append(vert.index)
is_last = True
break
+
if not is_last:
for vert in verts_candidates:
new_link_faces = [f for f in vert.link_faces if not_in(f.index, faces_grid)]
- if len(new_link_faces) < 2: # check if corner vertex
+ if len(new_link_faces) < 2: # check if corner vertex
vert.select = True
verts_loop.append(vert.index)
break
@@ -92,26 +105,30 @@ def grid_from_mesh(mesh, swap_uv):
id = verts_loop[-1]
link_edges = bm.verts[id].link_edges
# storing second point
- if len(verts_loop) == 1: # only one vertex stored in the loop
- if len(faces_grid) == 0: ### first loop ###
- edge = link_edges[swap_uv] # chose direction
+ if len(verts_loop) == 1: # only one vertex stored in the loop
+ if len(faces_grid) == 0: # first loop #
+ edge = link_edges[swap_uv] # chose direction
for vert in edge.verts:
if vert.index != id:
vert.select = True
- verts_loop.append(vert.index) # new vertex
- edges_loop.append(edge.index) # chosen edge
- faces_loop.append(edge.link_faces[0].index) # only one face
- #edge.link_faces[0].select = True
- else: ### other loops ###
- for edge in bm.faces[faces_grid[-1][0]].edges: # start from the edges of the first face of the last loop
- if bm.verts[verts_loop[0]] in edge.verts and bm.verts[verts_grid[-1][0]] not in edge.verts: # chose an edge starting from the first vertex that is not returning back
+ verts_loop.append(vert.index) # new vertex
+ edges_loop.append(edge.index) # chosen edge
+ faces_loop.append(edge.link_faces[0].index) # only one face
+ # edge.link_faces[0].select = True
+ else: # other loops #
+ # start from the edges of the first face of the last loop
+ for edge in bm.faces[faces_grid[-1][0]].edges:
+ # chose an edge starting from the first vertex that is not returning back
+ if bm.verts[verts_loop[0]] in edge.verts and \
+ bm.verts[verts_grid[-1][0]] not in edge.verts:
for vert in edge.verts:
if vert.index != id:
vert.select = True
verts_loop.append(vert.index)
edges_loop.append(edge.index)
+
for face in edge.link_faces:
- if not_in(face.index,faces_grid):
+ if not_in(face.index, faces_grid):
faces_loop.append(face.index)
# continuing the loop
else:
@@ -121,7 +138,8 @@ def grid_from_mesh(mesh, swap_uv):
if not_in(vert.index, verts_grid) and vert.index not in verts_loop:
if len(faces_loop) > 0:
bm.faces.ensure_lookup_table()
- if vert not in bm.faces[faces_loop[-1]].verts: store_data = True
+ if vert not in bm.faces[faces_loop[-1]].verts:
+ store_data = True
else:
store_data = True
if store_data:
@@ -133,79 +151,108 @@ def grid_from_mesh(mesh, swap_uv):
faces_loop.append(face.index)
break
# ending condition
- if verts_loop[-1] == id or verts_loop[-1] == verts_loop[0]: running_loop = False
+ if verts_loop[-1] == id or verts_loop[-1] == verts_loop[0]:
+ running_loop = False
verts_grid.append(verts_loop)
edges_grid.append(edges_loop)
faces_grid.append(faces_loop)
- if len(faces_loop) == 0: running_grid = False
+
+ if len(faces_loop) == 0:
+ running_grid = False
+
return verts_grid, edges_grid, faces_grid
-class lattice_along_surface(bpy.types.Operator):
+
+class lattice_along_surface(Operator):
bl_idname = "object.lattice_along_surface"
bl_label = "Lattice along Surface"
bl_description = ("Automatically add a Lattice modifier to the selected "
"object, adapting it to the active one.\nThe active "
"object must be a rectangular grid compatible with the "
- "Lattice's topology.")
+ "Lattice's topology")
bl_options = {'REGISTER', 'UNDO'}
- set_parent = bpy.props.BoolProperty(
- name="Set Parent", default=True,
- description="Automatically set the Lattice as parent")
-
- flipNormals = bpy.props.BoolProperty(
- name="Flip Normals", default=False,
- description="Flip normals direction")
-
- swapUV = bpy.props.BoolProperty(
- name="Swap UV", default=False,
- description="Flip grid's U and V")
-
- flipU = bpy.props.BoolProperty(
- name="Flip U", default=False,
- description="Flip grid's U")
-
- flipV = bpy.props.BoolProperty(
- name="Flip V", default=False,
- description="Flip grid's V")
-
- flipW = bpy.props.BoolProperty(
- name="Flip W", default=False,
- description="Flip grid's W")
-
- use_groups = bpy.props.BoolProperty(
- name="Vertex Group", default=False,
- description="Use active Vertex Group for lattice's thickness")
-
- high_quality_lattice = bpy.props.BoolProperty(
- name="High quality", default=True,
- description="Increase the the subdivisions in normal direction for a "
- "more correct result")
-
- hide_lattice = bpy.props.BoolProperty(
- name="Hide Lattice", default=True,
- description="Automatically hide the Lattice object")
-
- scale_x = bpy.props.FloatProperty(
- name="Scale X", default=1, min=0.001,
- max=1, description="Object scale")
-
- scale_y = bpy.props.FloatProperty(
- name="Scale Y", default=1, min=0.001,
- max=1, description="Object scale")
-
- scale_z = bpy.props.FloatProperty(
- name="Scale Z", default=1, min=0.001,
- max=1, description="Object scale")
-
- thickness = bpy.props.FloatProperty(
- name="Thickness", default=1, soft_min=0,
- soft_max=5, description="Lattice thickness")
-
- displace = bpy.props.FloatProperty(
- name="Displace", default=0, soft_min=-1,
- soft_max=1, description="Lattice displace")
+ set_parent = BoolProperty(
+ name="Set Parent",
+ default=True,
+ description="Automatically set the Lattice as parent"
+ )
+ flipNormals = BoolProperty(
+ name="Flip Normals",
+ default=False,
+ description="Flip normals direction"
+ )
+ swapUV = BoolProperty(
+ name="Swap UV",
+ default=False,
+ description="Flip grid's U and V"
+ )
+ flipU = BoolProperty(
+ name="Flip U",
+ default=False,
+ description="Flip grid's U")
+
+ flipV = BoolProperty(
+ name="Flip V",
+ default=False,
+ description="Flip grid's V"
+ )
+ flipW = BoolProperty(
+ name="Flip W",
+ default=False,
+ description="Flip grid's W"
+ )
+ use_groups = BoolProperty(
+ name="Vertex Group",
+ default=False,
+ description="Use active Vertex Group for lattice's thickness"
+ )
+ high_quality_lattice = BoolProperty(
+ name="High quality",
+ default=True,
+ description="Increase the the subdivisions in normal direction for a "
+ "more correct result"
+ )
+ hide_lattice = BoolProperty(
+ name="Hide Lattice",
+ default=True,
+ description="Automatically hide the Lattice object"
+ )
+ scale_x = FloatProperty(
+ name="Scale X",
+ default=1,
+ min=0.001,
+ max=1,
+ description="Object scale"
+ )
+ scale_y = FloatProperty(
+ name="Scale Y", default=1,
+ min=0.001,
+ max=1,
+ description="Object scale"
+ )
+ scale_z = FloatProperty(
+ name="Scale Z",
+ default=1,
+ min=0.001,
+ max=1,
+ description="Object scale"
+ )
+ thickness = FloatProperty(
+ name="Thickness",
+ default=1,
+ soft_min=0,
+ soft_max=5,
+ description="Lattice thickness"
+ )
+ displace = FloatProperty(
+ name="Displace",
+ default=0,
+ soft_min=-1,
+ soft_max=1,
+ description="Lattice displace"
+ )
def draw(self, context):
layout = self.layout
@@ -214,11 +261,13 @@ class lattice_along_surface(bpy.types.Operator):
col.prop(
self, "thickness", text="Thickness", icon='NONE', expand=False,
slider=True, toggle=False, icon_only=False, event=False,
- full_event=False, emboss=True, index=-1)
+ full_event=False, emboss=True, index=-1
+ )
col.prop(
self, "displace", text="Offset", icon='NONE', expand=False,
slider=True, toggle=False, icon_only=False, event=False,
- full_event=False, emboss=True, index=-1)
+ full_event=False, emboss=True, index=-1
+ )
row = col.row()
row.prop(self, "use_groups")
col.separator()
@@ -226,17 +275,19 @@ class lattice_along_surface(bpy.types.Operator):
col.prop(
self, "scale_x", text="U", icon='NONE', expand=False,
slider=True, toggle=False, icon_only=False, event=False,
- full_event=False, emboss=True, index=-1)
+ full_event=False, emboss=True, index=-1
+ )
col.prop(
self, "scale_y", text="V", icon='NONE', expand=False,
slider=True, toggle=False, icon_only=False, event=False,
- full_event=False, emboss=True, index=-1)
- '''
+ full_event=False, emboss=True, index=-1
+ )
+ """
col.prop(
self, "scale_z", text="W", icon='NONE', expand=False,
slider=True, toggle=False, icon_only=False, event=False,
full_event=False, emboss=True, index=-1)
- '''
+ """
col.separator()
col.label(text="Flip:")
row = col.row()
@@ -262,15 +313,17 @@ class lattice_along_surface(bpy.types.Operator):
return {'CANCELLED'}
obj = None
for o in bpy.context.selected_objects:
- if o.name != grid_obj.name and o.type in ('MESH', 'CURVE', \
- 'SURFACE', 'FONT'):
+ if o.name != grid_obj.name and o.type in \
+ ('MESH', 'CURVE', 'SURFACE', 'FONT'):
obj = o
o.select = False
break
try:
obj_dim = obj.dimensions
- obj_me = obj.to_mesh(bpy.context.scene, apply_modifiers=True,
- settings = 'PREVIEW')
+ obj_me = obj.to_mesh(
+ bpy.context.scene, apply_modifiers=True,
+ settings='PREVIEW'
+ )
except:
self.report({'ERROR'}, "The object to deform is not valid. Only "
"Mesh, Curve, Surface and Font objects are allowed.")
@@ -281,16 +334,18 @@ class lattice_along_surface(bpy.types.Operator):
bpy.ops.object.convert(target='MESH')
bpy.ops.object.transform_apply(location=True, rotation=True, scale=True)
grid_mesh = grid_obj.to_mesh(bpy.context.scene, apply_modifiers=True,
- settings = 'PREVIEW')
- if len(grid_mesh.polygons) > 64*64:
+ settings='PREVIEW')
+
+ if len(grid_mesh.polygons) > 64 * 64:
bpy.ops.object.delete(use_global=False)
bpy.context.scene.objects.active = obj
obj.select = True
self.report({'ERROR'}, "Maximum resolution allowed for Lattice is 64")
return {'CANCELLED'}
+
# CREATING LATTICE
- min = Vector((0,0,0))
- max = Vector((0,0,0))
+ min = Vector((0, 0, 0))
+ max = Vector((0, 0, 0))
first = True
for v in obj_me.vertices:
vert = obj.matrix_world * v.co
@@ -307,17 +362,23 @@ class lattice_along_surface(bpy.types.Operator):
if vert[2] > max[2] or first:
max[2] = vert[2]
first = False
- bb = max-min
- lattice_loc = (max+min)/2
+
+ bb = max - min
+ lattice_loc = (max + min) / 2
bpy.ops.object.add(type='LATTICE', view_align=False,
enter_editmode=False)
lattice = bpy.context.active_object
lattice.location = lattice_loc
- lattice.scale = Vector((bb.x/self.scale_x, bb.y/self.scale_y,
- bb.z/self.scale_z))
- if bb.x == 0: lattice.scale.x = 1
- if bb.y == 0: lattice.scale.y = 1
- if bb.z == 0: lattice.scale.z = 1
+ lattice.scale = Vector((bb.x / self.scale_x, bb.y / self.scale_y,
+ bb.z / self.scale_z))
+
+ if bb.x == 0:
+ lattice.scale.x = 1
+ if bb.y == 0:
+ lattice.scale.y = 1
+ if bb.z == 0:
+ lattice.scale.z = 1
+
bpy.context.scene.objects.active = obj
bpy.ops.object.modifier_add(type='LATTICE')
obj.modifiers[-1].object = lattice
@@ -330,8 +391,10 @@ class lattice_along_surface(bpy.types.Operator):
bpy.ops.object.parent_set(type='LATTICE')
# reading grid structure
- verts_grid, edges_grid, faces_grid = grid_from_mesh(grid_mesh,
- swap_uv=self.swapUV)
+ verts_grid, edges_grid, faces_grid = grid_from_mesh(
+ grid_mesh,
+ swap_uv=self.swapUV
+ )
nu = len(verts_grid)
nv = len(verts_grid[0])
nw = 2
@@ -346,17 +409,27 @@ class lattice_along_surface(bpy.types.Operator):
for w in range(nw):
if self.use_groups:
try:
- displace = grid_obj.vertex_groups.active.weight(verts_grid[i][j])*scale_normal*bb.z
+ displace = grid_obj.vertex_groups.active.weight(
+ verts_grid[i][j]) * scale_normal * bb.z
except:
- displace = scale_normal*bb.z
- else: displace = scale_normal*bb.z
- target_point = (grid_mesh.vertices[verts_grid[i][j]].co + grid_mesh.vertices[verts_grid[i][j]].normal*(w + self.displace/2 - 0.5)*displace) - lattice.location
- if self.flipW: w = 1-w
- if self.flipU: i = nu-i-1
- if self.flipV: j = nv-j-1
- lattice.data.points[i + j*nu + w*nu*nv].co_deform.x = target_point.x / bpy.data.objects[lattice.name].scale.x
- lattice.data.points[i + j*nu + w*nu*nv].co_deform.y = target_point.y / bpy.data.objects[lattice.name].scale.y
- lattice.data.points[i + j*nu + w*nu*nv].co_deform.z = target_point.z / bpy.data.objects[lattice.name].scale.z
+ displace = scale_normal * bb.z
+ else:
+ displace = scale_normal * bb.z
+ target_point = (grid_mesh.vertices[verts_grid[i][j]].co +
+ grid_mesh.vertices[verts_grid[i][j]].normal *
+ (w + self.displace / 2 - 0.5) * displace) - lattice.location
+ if self.flipW:
+ w = 1 - w
+ if self.flipU:
+ i = nu - i - 1
+ if self.flipV:
+ j = nv - j - 1
+ lattice.data.points[i + j * nu + w * nu * nv].co_deform.x = \
+ target_point.x / bpy.data.objects[lattice.name].scale.x
+ lattice.data.points[i + j * nu + w * nu * nv].co_deform.y = \
+ target_point.y / bpy.data.objects[lattice.name].scale.y
+ lattice.data.points[i + j * nu + w * nu * nv].co_deform.z = \
+ target_point.z / bpy.data.objects[lattice.name].scale.z
except:
bpy.ops.object.mode_set(mode='OBJECT')
grid_obj.select = True
@@ -373,9 +446,9 @@ class lattice_along_surface(bpy.types.Operator):
self.report({'ERROR'}, "The grid mesh is not correct")
return {'CANCELLED'}
- #grid_obj.data = old_grid_data
- #print(old_grid_matrix)
- #grid_obj.matrix_world = old_grid_matrix
+ # grid_obj.data = old_grid_data
+ # print(old_grid_matrix)
+ # grid_obj.matrix_world = old_grid_matrix
bpy.ops.object.mode_set(mode='OBJECT')
grid_obj.select = True
@@ -384,13 +457,19 @@ class lattice_along_surface(bpy.types.Operator):
bpy.ops.object.delete(use_global=False)
bpy.context.scene.objects.active = lattice
lattice.select = True
- if self.high_quality_lattice: bpy.context.object.data.points_w = 8
- else: bpy.context.object.data.use_outside = True
+
+ if self.high_quality_lattice:
+ bpy.context.object.data.points_w = 8
+ else:
+ bpy.context.object.data.use_outside = True
+
if self.hide_lattice:
bpy.ops.object.hide_view_set(unselected=False)
+
bpy.context.scene.objects.active = obj
obj.select = True
lattice.select = False
+
if self.flipNormals:
try:
bpy.ops.object.mode_set(mode='EDIT')
@@ -399,34 +478,37 @@ class lattice_along_surface(bpy.types.Operator):
bpy.ops.object.mode_set(mode='OBJECT')
except:
pass
+
return {'FINISHED'}
-'''
+
+"""
class lattice_along_surface_panel(bpy.types.Panel):
bl_label = "Modifiers Tools"
bl_category = "Tools"
bl_space_type = "VIEW_3D"
bl_region_type = "TOOLS"
- bl_context = (("objectmode"))
+ bl_context = "objectmode"
def draw(self, context):
layout = self.layout
col = layout.column(align=True)
+
try:
col.operator("object.lattice_along_surface", icon="MOD_LATTICE")
except:
pass
-'''
+"""
def register():
bpy.utils.register_class(lattice_along_surface)
- #bpy.utils.register_class(lattice_along_surface_panel)
+ # bpy.utils.register_class(lattice_along_surface_panel)
def unregister():
bpy.utils.unregister_class(lattice_along_surface)
- #bpy.utils.unregister_class(lattice_along_surface_panel)
+ # bpy.utils.unregister_class(lattice_along_surface_panel)
if __name__ == "__main__":
diff --git a/mesh_tissue/tessellate_numpy.py b/mesh_tissue/tessellate_numpy.py
index 367b44f5..e80cd39b 100644
--- a/mesh_tissue/tessellate_numpy.py
+++ b/mesh_tissue/tessellate_numpy.py
@@ -16,8 +16,8 @@
#
# ##### END GPL LICENSE BLOCK #####
-# ---------------------------- ADAPTIVE DUPLIFACES ----------------------------#
-#-------------------------------- version 0.83 --------------------------------#
+# ---------------------------- ADAPTIVE DUPLIFACES --------------------------- #
+# ------------------------------- version 0.84 ------------------------------- #
# #
# Creates duplicates of selected mesh to active morphing the shape according #
# to target faces. #
@@ -27,31 +27,43 @@
# #
# http://www.co-de-it.com/ #
# #
-################################################################################
+# ############################################################################ #
import bpy
+from bpy.types import (
+ Operator,
+ Panel,
+ PropertyGroup,
+ )
+from bpy.props import (
+ BoolProperty,
+ EnumProperty,
+ FloatProperty,
+ IntProperty,
+ StringProperty,
+ )
from mathutils import Vector
import numpy as np
from math import sqrt
import random
-def lerp(a,b,t):
- return a + (b-a)*t
+def lerp(a, b, t):
+ return a + (b - a) * t
def lerp2(v1, v2, v3, v4, v):
- v12 = v1 + (v2-v1)*v.x
- v43 = v4 + (v3-v4)*v.x
- return v12 + (v43-v12)*v.y
+ v12 = v1 + (v2 - v1) * v.x
+ v43 = v4 + (v3 - v4) * v.x
+ return v12 + (v43 - v12) * v.y
def lerp3(v1, v2, v3, v4, v):
loc = lerp2(v1.co, v2.co, v3.co, v4.co, v)
nor = lerp2(v1.normal, v2.normal, v3.normal, v4.normal, v)
nor.normalize()
- return loc + nor*v.z
+ return loc + nor * v.z
def tassellate(ob0, ob1, offset, zscale, gen_modifiers, com_modifiers, mode,
@@ -59,38 +71,43 @@ def tassellate(ob0, ob1, offset, zscale, gen_modifiers, com_modifiers, mode,
bool_vertex_group, bool_selection, bool_shapekeys):
random.seed(rand_seed)
old_me0 = ob0.data # Store generator mesh
+
if gen_modifiers: # Apply generator modifiers
me0 = ob0.to_mesh(bpy.context.scene, apply_modifiers=True,
- settings = 'PREVIEW')
- else: me0 = ob0.data
+ settings='PREVIEW')
+ else:
+ me0 = ob0.data
ob0.data = me0
base_polygons = []
# Check if zero faces are selected
if bool_selection:
for p in ob0.data.polygons:
- if p.select: base_polygons.append(p)
+ if p.select:
+ base_polygons.append(p)
else:
base_polygons = ob0.data.polygons
- if len(base_polygons) == 0: return 0
+ if len(base_polygons) == 0:
+ return 0
# Apply component modifiers
if com_modifiers:
me1 = ob1.to_mesh(bpy.context.scene, apply_modifiers=True,
- settings = 'PREVIEW')
- else: me1 = ob1.data
+ settings='PREVIEW')
+ else:
+ me1 = ob1.data
verts0 = me0.vertices # Collect generator vertices
# Component statistics
n_verts = len(me1.vertices)
- n_edges = len(me1.edges)
- n_faces = len(me1.polygons)
+ # n_edges = len(me1.edges)
+ # n_faces = len(me1.polygons)
# Component transformations
- loc = ob1.location
- dim = ob1.dimensions
- scale = ob1.scale
+ # loc = ob1.location
+ # dim = ob1.dimensions
+ # scale = ob1.scale
# Create empty lists
new_verts = []
@@ -99,44 +116,44 @@ def tassellate(ob0, ob1, offset, zscale, gen_modifiers, com_modifiers, mode,
new_verts_np = np.array(())
# Component bounding box
- min = Vector((0,0,0))
- max = Vector((0,0,0))
+ min_c = Vector((0, 0, 0))
+ max_c = Vector((0, 0, 0))
first = True
for v in me1.vertices:
vert = v.co
- if vert[0] < min[0] or first:
- min[0] = vert[0]
- if vert[1] < min[1] or first:
- min[1] = vert[1]
- if vert[2] < min[2] or first:
- min[2] = vert[2]
- if vert[0] > max[0] or first:
- max[0] = vert[0]
- if vert[1] > max[1] or first:
- max[1] = vert[1]
- if vert[2] > max[2] or first:
- max[2] = vert[2]
+ if vert[0] < min_c[0] or first:
+ min_c[0] = vert[0]
+ if vert[1] < min_c[1] or first:
+ min_c[1] = vert[1]
+ if vert[2] < min_c[2] or first:
+ min_c[2] = vert[2]
+ if vert[0] > max_c[0] or first:
+ max_c[0] = vert[0]
+ if vert[1] > max_c[1] or first:
+ max_c[1] = vert[1]
+ if vert[2] > max_c[2] or first:
+ max_c[2] = vert[2]
first = False
- bb = max-min
+ bb = max_c - min_c
# adaptive XY
verts1 = []
for v in me1.vertices:
- if mode=="ADAPTIVE":
- vert = v.co - min#( ob1.matrix_world * v.co ) - min
+ if mode == "ADAPTIVE":
+ vert = v.co - min_c # (ob1.matrix_world * v.co) - min_c
vert[0] = (vert[0] / bb[0] if bb[0] != 0 else 0.5)
vert[1] = (vert[1] / bb[1] if bb[1] != 0 else 0.5)
- vert[2] = (vert[2] + (-0.5 + offset*0.5)*bb[2])*zscale
+ vert[2] = (vert[2] + (-0.5 + offset * 0.5) * bb[2]) * zscale
else:
vert = v.co.xyz
- vert[2] = (vert[2] - min[2] + (-0.5 + offset*0.5)*bb[2])*zscale
+ vert[2] = (vert[2] - min_c[2] + (-0.5 + offset * 0.5) * bb[2]) * zscale
verts1.append(vert)
# component vertices
- vs1 = np.array([v for v in verts1]).reshape(len(verts1),3,1)
- vx = vs1[:,0]
- vy = vs1[:,1]
- vz = vs1[:,2]
+ vs1 = np.array([v for v in verts1]).reshape(len(verts1), 3, 1)
+ vx = vs1[:, 0]
+ vy = vs1[:, 1]
+ vz = vs1[:, 2]
# Component polygons
fs1 = [[i for i in p.vertices] for p in me1.polygons]
@@ -155,26 +172,26 @@ def tassellate(ob0, ob1, offset, zscale, gen_modifiers, com_modifiers, mode,
# Read active key
active_key = ob1.active_shape_key_index
- if active_key == 0: active_key = 1
+ if active_key == 0:
+ active_key = 1
for v in me1.shape_keys.key_blocks[active_key].data:
- if mode=="ADAPTIVE":
- vert = v.co - min
- #vert = ( ob1.matrix_world * v.co ) - min
+ if mode == "ADAPTIVE":
+ vert = v.co - min_c
vert[0] = vert[0] / bb[0]
vert[1] = vert[1] / bb[1]
- vert[2] = (vert[2] + (-0.5 + offset*0.5)*bb[2]) * zscale
+ vert[2] = (vert[2] + (-0.5 + offset * 0.5) * bb[2]) * zscale
else:
vert = v.co.xyz
- vert[2] = (vert[2] - min[2] + (-0.5 + offset*0.5)*bb[2]) * \
+ vert[2] = (vert[2] - min_c[2] + (-0.5 + offset * 0.5) * bb[2]) * \
zscale
shapekeys.append(vert)
# Component vertices
- key1 = np.array([v for v in shapekeys]).reshape(len(shapekeys),3,1)
- vx_key = key1[:,0]
- vy_key = key1[:,1]
- vz_key = key1[:,2]
+ key1 = np.array([v for v in shapekeys]).reshape(len(shapekeys), 3, 1)
+ vx_key = key1[:, 0]
+ vy_key = key1[:, 1]
+ vz_key = key1[:, 2]
# Active vertex group
if bool_vertex_group:
@@ -194,10 +211,10 @@ def tassellate(ob0, ob1, offset, zscale, gen_modifiers, com_modifiers, mode,
if fill_mode == 'FAN':
fan_verts = [v.co.to_tuple() for v in me0.vertices]
fan_polygons = []
- selected_faces = []
+ # selected_faces = []
for p in base_polygons:
- #if bool_selection and not p.select: continue
- fan_center = Vector((0,0,0))
+ # if bool_selection and not p.select: continue
+ fan_center = Vector((0, 0, 0))
for v in p.vertices:
fan_center += me0.vertices[v].co
fan_center /= len(p.vertices)
@@ -206,22 +223,23 @@ def tassellate(ob0, ob1, offset, zscale, gen_modifiers, com_modifiers, mode,
# Vertex Group
if bool_vertex_group:
- center_weight = sum([weight[i] for i in p.vertices])/ \
- len(p.vertices)
+ center_weight = sum([weight[i] for i in p.vertices]) / len(p.vertices)
weight.append(center_weight)
for i in range(len(p.vertices)):
fan_polygons.append((p.vertices[i],
- p.vertices[(i+1)%len(p.vertices)],
+ p.vertices[(i + 1) % len(p.vertices)],
last_vert, last_vert))
- #if bool_selection: selected_faces.append(p.select)
+ # if bool_selection: selected_faces.append(p.select)
fan_me = bpy.data.meshes.new('Fan.Mesh')
fan_me.from_pydata(tuple(fan_verts), [], tuple(fan_polygons))
me0 = fan_me
verts0 = me0.vertices
base_polygons = me0.polygons
- #for i in range(len(selected_faces)):
- # fan_me.polygons[i].select = selected_faces[i]
+ """
+ for i in range(len(selected_faces)):
+ fan_me.polygons[i].select = selected_faces[i]
+ """
count = 0 # necessary for UV calculation
# TESSELLATION
@@ -231,41 +249,44 @@ def tassellate(ob0, ob1, offset, zscale, gen_modifiers, com_modifiers, mode,
if rotation_mode == 'RANDOM':
shifted_vertices = []
n_poly_verts = len(p.vertices)
- rand = random.randint(0,n_poly_verts)
+ rand = random.randint(0, n_poly_verts)
for i in range(n_poly_verts):
- shifted_vertices.append(p.vertices[(i+rand)%n_poly_verts])
+ shifted_vertices.append(p.vertices[(i + rand) % n_poly_verts])
vs0 = np.array([verts0[i].co for i in shifted_vertices])
nvs0 = np.array([verts0[i].normal for i in shifted_vertices])
# vertex weight
if bool_vertex_group:
ws0 = []
for i in shifted_vertices:
- try: ws0.append(weight[i])
- except: ws0.append(0)
+ try:
+ ws0.append(weight[i])
+ except:
+ ws0.append(0)
+
ws0 = np.array(ws0)
# UV rotation
- elif rotation_mode == 'UV' and len(ob0.data.uv_layers) > 0 \
- and fill_mode != 'FAN':
+ elif rotation_mode == 'UV' and len(ob0.data.uv_layers) > 0 and \
+ fill_mode != 'FAN':
i = p.index
- v01 = (me0.uv_layers.active.data[count].uv + \
- me0.uv_layers.active.data[count+1].uv)
+ v01 = (me0.uv_layers.active.data[count].uv +
+ me0.uv_layers.active.data[count + 1].uv)
if len(p.vertices) > 3:
- v32 = (me0.uv_layers.active.data[count+3].uv + \
- me0.uv_layers.active.data[count+2].uv)
+ v32 = (me0.uv_layers.active.data[count + 3].uv +
+ me0.uv_layers.active.data[count + 2].uv)
else:
- v32 = (me0.uv_layers.active.data[count].uv + \
- me0.uv_layers.active.data[count+2].uv)
- v0132 = v32-v01
+ v32 = (me0.uv_layers.active.data[count].uv +
+ me0.uv_layers.active.data[count + 2].uv)
+ v0132 = v32 - v01
v0132.normalize()
- v12 = (me0.uv_layers.active.data[count+1].uv + \
- me0.uv_layers.active.data[count+2].uv)
+ v12 = (me0.uv_layers.active.data[count + 1].uv +
+ me0.uv_layers.active.data[count + 2].uv)
if len(p.vertices) > 3:
- v03 = (me0.uv_layers.active.data[count].uv + \
- me0.uv_layers.active.data[count+3].uv)
+ v03 = (me0.uv_layers.active.data[count].uv +
+ me0.uv_layers.active.data[count + 3].uv)
else:
- v03 = (me0.uv_layers.active.data[count].uv + \
+ v03 = (me0.uv_layers.active.data[count].uv +
me0.uv_layers.active.data[count].uv)
v1203 = v03 - v12
v1203.normalize()
@@ -274,11 +295,15 @@ def tassellate(ob0, ob1, offset, zscale, gen_modifiers, com_modifiers, mode,
dot1203 = v1203.x
dot0132 = v0132.x
if(abs(dot1203) < abs(dot0132)):
- if(dot0132 > 0): vertUV = p.vertices[1:] + p.vertices[:1]
- else: vertUV = p.vertices[3:] + p.vertices[:3]
+ if (dot0132 > 0):
+ vertUV = p.vertices[1:] + p.vertices[:1]
+ else:
+ vertUV = p.vertices[3:] + p.vertices[:3]
else:
- if(dot1203 < 0): vertUV = p.vertices[:]
- else: vertUV = p.vertices[2:] + p.vertices[:2]
+ if(dot1203 < 0):
+ vertUV = p.vertices[:]
+ else:
+ vertUV = p.vertices[2:] + p.vertices[:2]
vs0 = np.array([verts0[i].co for i in vertUV])
nvs0 = np.array([verts0[i].normal for i in vertUV])
@@ -286,8 +311,10 @@ def tassellate(ob0, ob1, offset, zscale, gen_modifiers, com_modifiers, mode,
if bool_vertex_group:
ws0 = []
for i in vertUV:
- try: ws0.append(weight[i])
- except: ws0.append(0)
+ try:
+ ws0.append(weight[i])
+ except:
+ ws0.append(0)
ws0 = np.array(ws0)
count += len(p.vertices)
@@ -300,8 +327,10 @@ def tassellate(ob0, ob1, offset, zscale, gen_modifiers, com_modifiers, mode,
if bool_vertex_group:
ws0 = []
for i in p.vertices:
- try: ws0.append(weight[i])
- except: ws0.append(0)
+ try:
+ ws0.append(weight[i])
+ except:
+ ws0.append(0)
ws0 = np.array(ws0)
# considering only 4 vertices
@@ -309,43 +338,44 @@ def tassellate(ob0, ob1, offset, zscale, gen_modifiers, com_modifiers, mode,
nvs0 = np.array((nvs0[0], nvs0[1], nvs0[2], nvs0[-1]))
# remapped vertex coordinates
- v0 = vs0[0] + (vs0[1] -vs0[0])*vx
- v1 = vs0[3] + (vs0[2] -vs0[3])*vx
- v2 = v0 + (v1 - v0)*vy
+ v0 = vs0[0] + (vs0[1] - vs0[0]) * vx
+ v1 = vs0[3] + (vs0[2] - vs0[3]) * vx
+ v2 = v0 + (v1 - v0) * vy
# remapped vertex normal
- nv0 = nvs0[0] + (nvs0[1] -nvs0[0])*vx
- nv1 = nvs0[3] + (nvs0[2] -nvs0[3])*vx
- nv2 = nv0 + (nv1 - nv0)*vy
+ nv0 = nvs0[0] + (nvs0[1] - nvs0[0]) * vx
+ nv1 = nvs0[3] + (nvs0[2] - nvs0[3]) * vx
+ nv2 = nv0 + (nv1 - nv0) * vy
# vertex z to normal
- v3 = v2 + nv2*vz*(sqrt(p.area) if scale_mode == "ADAPTIVE" else 1)
+ v3 = v2 + nv2 * vz * (sqrt(p.area) if scale_mode == "ADAPTIVE" else 1)
if bool_vertex_group:
ws0 = np.array((ws0[0], ws0[1], ws0[2], ws0[-1]))
# Interpolate vertex weight
- w0 = ws0[0] + (ws0[1] -ws0[0])*vx
- w1 = ws0[3] + (ws0[2] -ws0[3])*vx
- w2 = w0 + (w1 - w0)*vy
+ w0 = ws0[0] + (ws0[1] - ws0[0]) * vx
+ w1 = ws0[3] + (ws0[2] - ws0[3]) * vx
+ w2 = w0 + (w1 - w0) * vy
# Shapekeys
if do_shapekeys:
# remapped vertex coordinates
- v0 = vs0[0] + (vs0[1] -vs0[0])*vx_key
- v1 = vs0[3] + (vs0[2] -vs0[3])*vx_key
- v2 = v0 + (v1 - v0)*vy_key
+ v0 = vs0[0] + (vs0[1] - vs0[0]) * vx_key
+ v1 = vs0[3] + (vs0[2] - vs0[3]) * vx_key
+ v2 = v0 + (v1 - v0) * vy_key
# remapped vertex normal
- nv0 = nvs0[0] + (nvs0[1] -nvs0[0])*vx_key
- nv1 = nvs0[3] + (nvs0[2] -nvs0[3])*vx_key
- nv2 = nv0 + (nv1 - nv0)*vy_key
+ nv0 = nvs0[0] + (nvs0[1] - nvs0[0]) * vx_key
+ nv1 = nvs0[3] + (nvs0[2] - nvs0[3]) * vx_key
+ nv2 = nv0 + (nv1 - nv0) * vy_key
# vertex z to normal
- v3_key = v2 + nv2*vz_key*(sqrt(p.area) \
- if scale_mode == "ADAPTIVE" else 1)
+ v3_key = v2 + nv2 * vz_key * (sqrt(p.area) if
+ scale_mode == "ADAPTIVE" else 1)
v3 = v3 + (v3_key - v3) * w2
if j == 0:
new_verts_np = v3
- if bool_vertex_group: new_vertex_group_np = w2
+ if bool_vertex_group:
+ new_vertex_group_np = w2
else:
# Appending vertices
new_verts_np = np.concatenate((new_verts_np, v3), axis=0)
@@ -354,9 +384,11 @@ def tassellate(ob0, ob1, offset, zscale, gen_modifiers, com_modifiers, mode,
new_vertex_group_np = np.concatenate((new_vertex_group_np, w2),
axis=0)
# Appending faces
- for p in fs1: new_faces.append([i+n_verts*j for i in p])
+ for p in fs1:
+ new_faces.append([i + n_verts * j for i in p])
# Appending edges
- for e in es1: new_edges.append([i+n_verts*j for i in e])
+ for e in es1:
+ new_edges.append([i + n_verts * j for i in e])
j += 1
@@ -364,7 +396,6 @@ def tassellate(ob0, ob1, offset, zscale, gen_modifiers, com_modifiers, mode,
new_name = ob0.name + "_" + ob1.name
new_me = bpy.data.meshes.new(new_name)
new_me.from_pydata(new_verts, new_edges, new_faces)
- #new_me.from_pydata(new_verts, new_edges, [])
new_me.update(calc_edges=True)
new_ob = bpy.data.objects.new("tessellate_temp", new_me)
@@ -400,88 +431,141 @@ def store_parameters(operator, ob):
return ob
-class tissue_tessellate_prop(bpy.types.PropertyGroup):
- generator = bpy.props.StringProperty()
- component = bpy.props.StringProperty()
- offset = bpy.props.FloatProperty()
- zscale = bpy.props.FloatProperty(default=1)
- merge = bpy.props.BoolProperty()
- merge_thres = bpy.props.FloatProperty()
- gen_modifiers = bpy.props.BoolProperty()
- com_modifiers = bpy.props.BoolProperty()
- mode = bpy.props.StringProperty()
- rotation_mode = bpy.props.StringProperty()
- scale_mode = bpy.props.StringProperty()
- fill_mode = bpy.props.StringProperty()
- bool_random = bpy.props.BoolProperty()
- random_seed = bpy.props.IntProperty()
- vertexgroup = bpy.props.StringProperty()
- bool_vertex_group = bpy.props.BoolProperty()
- bool_selection = bpy.props.BoolProperty()
- bool_shapekeys = bpy.props.BoolProperty()
-
-
-class tessellate(bpy.types.Operator):
+class tissue_tessellate_prop(PropertyGroup):
+ generator = StringProperty()
+ component = StringProperty()
+ offset = FloatProperty()
+ zscale = FloatProperty(default=1)
+ merge = BoolProperty()
+ merge_thres = FloatProperty()
+ gen_modifiers = BoolProperty()
+ com_modifiers = BoolProperty()
+ mode = StringProperty()
+ rotation_mode = StringProperty()
+ scale_mode = StringProperty()
+ fill_mode = StringProperty()
+ bool_random = BoolProperty()
+ random_seed = IntProperty()
+ vertexgroup = StringProperty()
+ bool_vertex_group = BoolProperty()
+ bool_selection = BoolProperty()
+ bool_shapekeys = BoolProperty()
+
+
+class tessellate(Operator):
bl_idname = "object.tessellate"
bl_label = "Tessellate"
bl_description = ("Create a copy of selected object on the active object's "
- "faces, adapting the shape to the different faces.")
+ "faces, adapting the shape to the different faces")
bl_options = {'REGISTER', 'UNDO'}
- object_name = bpy.props.StringProperty(
- name="", description="Name of the generated object")
- zscale = bpy.props.FloatProperty(
- name="Scale", default=1, soft_min=0, soft_max=10,
- description="Scale factor for the component thickness")
- scale_mode = bpy.props.EnumProperty(
- items=(('CONSTANT', "Constant", ""), ('ADAPTIVE', "Proportional", "")),
- default='CONSTANT', name="Z-Scale according to faces size")
- offset = bpy.props.FloatProperty(
- name="Surface Offset", default=0, min=-1, max=1, soft_min=-1,
- soft_max=1, description="Surface offset")
- mode = bpy.props.EnumProperty(
- items=(('CONSTANT', "Constant", ""), ('ADAPTIVE', "Adaptive", "")),
- default='ADAPTIVE', name="Component Mode")
- rotation_mode = bpy.props.EnumProperty(
- items=(('RANDOM', "Random", ""), ('UV', "Active UV", ""),
- ('DEFAULT', "Default", "")), default='DEFAULT',
- name="Component Rotation")
- fill_mode = bpy.props.EnumProperty(
- items=(('QUAD', "Quad", ""), ('FAN', "Fan", "")), default='QUAD',
- name="Fill Mode")
- gen_modifiers = bpy.props.BoolProperty(
- name="Generator Modifiers", default=False,
- description="Apply modifiers to base object")
- com_modifiers = bpy.props.BoolProperty(
- name="Component Modifiers", default=False,
- description="Apply modifiers to component object")
- merge = bpy.props.BoolProperty(
- name="Merge", default=False,
- description="Merge vertices in adjacent duplicates")
- merge_thres = bpy.props.FloatProperty(
- name="Distance", default=0.001, soft_min=0, soft_max=10,
- description="Limit below which to merge vertices")
- generator = bpy.props.StringProperty(
- name="", description="Base object for the tessellation")
- component = bpy.props.StringProperty(
- name="", description="Component object for the tessellation")
- bool_random = bpy.props.BoolProperty(
- name="Randomize", default=False,
- description="Randomize component rotation")
- random_seed = bpy.props.IntProperty(
- name="Seed", default=0, soft_min=0, soft_max=10,
- description="Random seed")
- bool_vertex_group = bpy.props.BoolProperty(
- name="Map Vertex Group", default=False, description=("Map the active "
- "Vertex Group from the Base object to generated geometry"))
- bool_selection = bpy.props.BoolProperty(
- name="On selected Faces", default=False,
- description="Create Tessellation only on selected faces")
- bool_shapekeys = bpy.props.BoolProperty(
- name="Use Shape Keys", default=False, description=("Use component's "
- "active Shape Key according to active Vertex Group of the base object"))
+ object_name = StringProperty(
+ name="",
+ description="Name of the generated object"
+ )
+ zscale = FloatProperty(
+ name="Scale",
+ default=1,
+ soft_min=0,
+ soft_max=10,
+ description="Scale factor for the component thickness"
+ )
+ scale_mode = EnumProperty(
+ items=(('CONSTANT', "Constant", ""), ('ADAPTIVE', "Proportional", "")),
+ default='CONSTANT',
+ name="Z-Scale according to faces size"
+ )
+ offset = FloatProperty(
+ name="Surface Offset",
+ default=0,
+ min=-1, max=1,
+ soft_min=-1,
+ soft_max=1,
+ description="Surface offset"
+ )
+ mode = EnumProperty(
+ items=(('CONSTANT', "Constant", ""), ('ADAPTIVE', "Adaptive", "")),
+ default='ADAPTIVE',
+ name="Component Mode"
+ )
+ rotation_mode = EnumProperty(
+ items=(('RANDOM', "Random", ""),
+ ('UV', "Active UV", ""),
+ ('DEFAULT', "Default", "")),
+ default='DEFAULT',
+ name="Component Rotation"
+ )
+ fill_mode = EnumProperty(
+ items=(('QUAD', "Quad", ""), ('FAN', "Fan", "")),
+ default='QUAD',
+ name="Fill Mode"
+ )
+ gen_modifiers = BoolProperty(
+ name="Generator Modifiers",
+ default=False,
+ description="Apply modifiers to base object"
+ )
+ com_modifiers = BoolProperty(
+ name="Component Modifiers",
+ default=False,
+ description="Apply modifiers to component object"
+ )
+ merge = BoolProperty(
+ name="Merge",
+ default=False,
+ description="Merge vertices in adjacent duplicates"
+ )
+ merge_thres = FloatProperty(
+ name="Distance",
+ default=0.001,
+ soft_min=0,
+ soft_max=10,
+ description="Limit below which to merge vertices"
+ )
+ generator = StringProperty(
+ name="",
+ description="Base object for the tessellation"
+ )
+ component = StringProperty(
+ name="",
+ description="Component object for the tessellation"
+ )
+ bool_random = BoolProperty(
+ name="Randomize",
+ default=False,
+ description="Randomize component rotation"
+ )
+ random_seed = IntProperty(
+ name="Seed",
+ default=0,
+ soft_min=0,
+ soft_max=10,
+ description="Random seed"
+ )
+ bool_vertex_group = BoolProperty(
+ name="Map Vertex Group",
+ default=False,
+ description="Map the active "
+ "Vertex Group from the Base object to generated geometry"
+ )
+ bool_selection = BoolProperty(
+ name="On selected Faces",
+ default=False,
+ description="Create Tessellation only on selected faces"
+ )
+ bool_shapekeys = BoolProperty(
+ name="Use Shape Keys",
+ default=False,
+ description="Use component's active Shape Key according to "
+ "active Vertex Group of the base object"
+ )
working_on = ""
+ @staticmethod
+ def check_gen_comp(checking):
+ # note pass the stored name key in here to check it out
+ return checking in bpy.data.objects.keys()
+
def draw(self, context):
try:
bool_working = self.working_on == self.object_name and \
@@ -495,7 +579,8 @@ class tessellate(bpy.types.Operator):
if len(sel) == 2:
bool_meshes = True
for o in sel:
- if o.type != 'MESH': bool_meshes = False
+ if o.type != 'MESH':
+ bool_meshes = False
if len(sel) != 2 and not bool_working:
layout = self.layout
@@ -515,27 +600,38 @@ class tessellate(bpy.types.Operator):
self.generator = ob0.name
for o in sel:
- if(o.name == ob0.name or o.type != 'MESH'): continue
+ if (o.name == ob0.name or o.type != 'MESH'):
+ continue
else:
ob1 = o
self.component = o.name
- no_component = False
+ self.no_component = False
break
- # Checks for Tool Shelf panel, it loose the original Selection
+ # Checks for Tool Shelf panel, it lost the original Selection
if bpy.context.active_object.name == self.object_name:
- ob1 = bpy.data.objects[
- bpy.context.active_object.tissue_tessellate.component]
- self.component = ob1.name
- ob0 = bpy.data.objects[
- bpy.context.active_object.tissue_tessellate.generator]
- self.generator = ob0.name
- no_component = False
+ # checks if the objects were deleted
+ if self.check_gen_comp(
+ bpy.context.active_object.tissue_tessellate.component):
+ ob1 = bpy.data.objects[
+ bpy.context.active_object.tissue_tessellate.component
+ ]
+ self.component = ob1.name
+
+ if self.check_gen_comp(
+ bpy.context.active_object.tissue_tessellate.generator):
+ ob0 = bpy.data.objects[
+ bpy.context.active_object.tissue_tessellate.generator
+ ]
+ self.generator = ob0.name
+ self.no_component = False
# new object name
if self.object_name == "":
- if self.generator == "": self.object_name = "Tessellation"
- else: self.object_name = self.generator + "_Tessellation"
+ if self.generator == "":
+ self.object_name = "Tessellation"
+ else:
+ self.object_name = self.generator + "_Tessellation"
layout = self.layout
# Base and Component
@@ -546,12 +642,16 @@ class tessellate(bpy.types.Operator):
row = col.row(align=True)
col2 = row.column(align=True)
col2.prop(self, "gen_modifiers", text="Use Modifiers")
- if len(bpy.data.objects[self.generator].modifiers) == 0:
+
+ if not self.check_gen_comp(self.generator) or \
+ len(bpy.data.objects[self.generator].modifiers) == 0:
col2.enabled = False
self.gen_modifiers = False
col2 = row.column(align=True)
col2.prop(self, "com_modifiers", text="Use Modifiers")
- if len(bpy.data.objects[self.component].modifiers) == 0:
+
+ if not self.check_gen_comp(self.component) or \
+ len(bpy.data.objects[self.component].modifiers) == 0:
col2.enabled = False
self.com_modifiers = False
@@ -568,18 +668,29 @@ class tessellate(bpy.types.Operator):
# Count number of faces
try:
polygons = 0
- if self.gen_modifiers: me_temp = ob0.to_mesh(bpy.context.scene,
- apply_modifiers=True, settings = 'PREVIEW')
- else: me_temp = ob0.data
+ if self.gen_modifiers:
+ me_temp = ob0.to_mesh(
+ bpy.context.scene,
+ apply_modifiers=True, settings='PREVIEW'
+ )
+ else:
+ me_temp = ob0.data
+
for p in me_temp.polygons:
if not self.bool_selection or p.select:
- if self.fill_mode == "FAN": polygons += len(p.vertices)
- else: polygons += 1
-
- if self.com_modifiers: me_temp = bpy.data.objects[
- self.component].to_mesh(bpy.context.scene,
- apply_modifiers=True, settings = 'PREVIEW')
- else: me_temp = bpy.data.objects[self.component].data
+ if self.fill_mode == "FAN":
+ polygons += len(p.vertices)
+ else:
+ polygons += 1
+
+ if self.com_modifiers:
+ me_temp = bpy.data.objects[self.component].to_mesh(
+ bpy.context.scene,
+ apply_modifiers=True,
+ settings='PREVIEW'
+ )
+ else:
+ me_temp = bpy.data.objects[self.component].data
polygons *= len(me_temp.polygons)
str_polygons = '{:0,.0f}'.format(polygons)
@@ -622,10 +733,14 @@ class tessellate(bpy.types.Operator):
row.label(text="UV rotation doesn't work in FAN mode",
icon='ERROR')
uv_error = True
- if len(bpy.data.objects[self.generator].data.uv_layers) == 0:
+
+ if not self.check_gen_comp(self.generator) or \
+ len(bpy.data.objects[self.generator].data.uv_layers) == 0:
row = col.row(align=True)
- row.label(text="'" + bpy.data.objects[self.generator].name \
- + "' doesn't have UV Maps", icon='ERROR')
+ check_name = bpy.data.objects[self.generator].name if \
+ self.check_gen_comp(self.generator) else "None"
+ row.label(text="'" + check_name +
+ "' doesn't have UV Maps", icon='ERROR')
uv_error = True
if uv_error:
row = col.row(align=True)
@@ -661,7 +776,9 @@ class tessellate(bpy.types.Operator):
col = layout.column(align=True)
row = col.row(align=True)
row.prop(self, "merge")
- if self.merge: row.prop(self, "merge_thres")
+
+ if self.merge:
+ row.prop(self, "merge_thres")
row = col.row(align=True)
# ADVANCED
@@ -671,21 +788,30 @@ class tessellate(bpy.types.Operator):
row = col.row(align=True)
col2 = row.column(align=True)
col2.prop(self, "bool_vertex_group")
- if len(bpy.data.objects[self.generator].vertex_groups) == 0:
+
+ if self.check_gen_comp(self.generator) and \
+ len(bpy.data.objects[self.generator].vertex_groups) == 0:
col2.enabled = False
- bool_vertex_group = False
+ self.bool_vertex_group = False
+
col2 = row.column(align=True)
+
+ if not self.check_gen_comp(self.generator) or \
+ not self.check_gen_comp(self.component):
+ return
+
col2.prop(self, "bool_shapekeys", text="Use Shape Keys")
+
if len(bpy.data.objects[self.generator].vertex_groups) == 0 or \
- bpy.data.objects[self.component].data.shape_keys == None:
+ bpy.data.objects[self.component].data.shape_keys is None:
col2.enabled = False
- bool_shapekeys = False
+ self.bool_shapekeys = False
elif len(bpy.data.objects[self.generator].vertex_groups) == 0 or \
- bpy.data.objects[self.component].data.shape_keys != None:
+ bpy.data.objects[self.component].data.shape_keys is not None:
if len(bpy.data.objects[
self.component].data.shape_keys.key_blocks) < 2:
col2.enabled = False
- bool_shapekeys = False
+ self.bool_shapekeys = False
def execute(self, context):
try:
@@ -698,14 +824,15 @@ class tessellate(bpy.types.Operator):
sel = bpy.context.selected_objects
no_component = True
for o in sel:
- if(o.name == ob0.name or o.type != 'MESH'): continue
+ if (o.name == ob0.name or o.type != 'MESH'):
+ continue
else:
ob1 = o
self.component = o.name
no_component = False
break
- # Checks for Tool Shelf panel, it loose the original Selection
+ # Checks for Tool Shelf panel, it lost the original Selection
if bpy.context.active_object == self.object_name:
ob1 = bpy.data.objects[
bpy.context.active_object.tissue_tessellate.component]
@@ -715,32 +842,38 @@ class tessellate(bpy.types.Operator):
self.generator = ob0.name
no_component = False
- if(no_component):
- #self.report({'ERROR'}, "A component mesh object must be selected")
+ if no_component:
+ # self.report({'ERROR'}, "A component mesh object must be selected")
return {'CANCELLED'}
# new object name
if self.object_name == "":
- if self.generator == "": self.object_name = "Tessellation"
- else: self.object_name = self.generator + "_Tessellation"
+ if self.generator == "":
+ self.object_name = "Tessellation"
+ else:
+ self.object_name = self.generator + "_Tessellation"
if bpy.data.objects[self.component].type != 'MESH':
message = "Component must be Mesh Objects!"
self.report({'ERROR'}, message)
self.component = ""
+
if bpy.data.objects[self.generator].type != 'MESH':
message = "Generator must be Mesh Objects!"
self.report({'ERROR'}, message)
self.generator = ""
+
if self.component != "" and self.generator != "":
- bpy.ops.object.select_all(action='TOGGLE')
+ if bpy.ops.object.select_all.poll():
+ bpy.ops.object.select_all(action='TOGGLE')
new_ob = tassellate(
- ob0, ob1, self.offset, self.zscale, self.gen_modifiers,
- self.com_modifiers, self.mode, self.scale_mode,
- self.rotation_mode, self.random_seed, self.fill_mode,
- self.bool_vertex_group, self.bool_selection,
- self.bool_shapekeys)
+ ob0, ob1, self.offset, self.zscale, self.gen_modifiers,
+ self.com_modifiers, self.mode, self.scale_mode,
+ self.rotation_mode, self.random_seed, self.fill_mode,
+ self.bool_vertex_group, self.bool_selection,
+ self.bool_shapekeys
+ )
if new_ob == 0:
message = "Zero faces selected in the Base mesh!"
@@ -748,7 +881,7 @@ class tessellate(bpy.types.Operator):
return {'CANCELLED'}
new_ob.name = self.object_name
- #new_ob = bpy.data.objects.new(self.object_name, new_me)
+ # new_ob = bpy.data.objects.new(self.object_name, new_me)
new_ob.location = ob0.location
new_ob.matrix_world = ob0.matrix_world
@@ -758,7 +891,7 @@ class tessellate(bpy.types.Operator):
new_ob.select = True
bpy.context.scene.objects.active = new_ob
if self.merge:
- bpy.ops.object.mode_set(mode = 'EDIT')
+ bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.select_mode(
use_extend=False, use_expand=False, type='VERT')
bpy.ops.mesh.select_non_manifold(
@@ -767,7 +900,7 @@ class tessellate(bpy.types.Operator):
use_verts=False)
bpy.ops.mesh.remove_doubles(
threshold=self.merge_thres, use_unselected=False)
- bpy.ops.object.mode_set(mode = 'OBJECT')
+ bpy.ops.object.mode_set(mode='OBJECT')
new_ob = store_parameters(self, new_ob)
self.object_name = new_ob.name
self.working_on = self.object_name
@@ -778,8 +911,8 @@ class tessellate(bpy.types.Operator):
# MATERIALS
try:
# create materials list
- polygon_materials = [p.material_index for p in ob1.data.polygons]*int(
- len(new_ob.data.polygons) / len(ob1.data.polygons))
+ polygon_materials = [p.material_index for p in ob1.data.polygons] * int(
+ len(new_ob.data.polygons) / len(ob1.data.polygons))
# assign old material
component_materials = [slot.material for slot in ob1.material_slots]
for i in range(len(component_materials)):
@@ -800,22 +933,27 @@ class tessellate(bpy.types.Operator):
return context.window_manager.invoke_props_dialog(self)
-class update_tessellate(bpy.types.Operator):
-#class adaptive_duplifaces(bpy.types.Panel):
+class update_tessellate(Operator):
bl_idname = "object.update_tessellate"
bl_label = "Refresh"
bl_description = ("Fast update the tessellated mesh according to base and "
"component changes")
bl_options = {'REGISTER', 'UNDO'}
+
go = False
- ob = bpy.types.Object
@classmethod
def poll(cls, context):
try:
return context.active_object.tissue_tessellate.generator != "" and \
context.active_object.tissue_tessellate.component != ""
- except: return False
+ except:
+ return False
+
+ @staticmethod
+ def check_gen_comp(checking):
+ # note pass the stored name key in here to check it out
+ return checking in bpy.data.objects.keys()
def execute(self, context):
ob = bpy.context.active_object
@@ -838,20 +976,26 @@ class update_tessellate(bpy.types.Operator):
bool_shapekeys = ob.tissue_tessellate.bool_shapekeys
mode = ob.tissue_tessellate.mode
- if(generator == "" or component == ""):
+ if not self.check_gen_comp(generator) or \
+ not self.check_gen_comp(component):
+ self.report({'ERROR'},
+ "Base or Component Objects are missing from the data "
+ "(Most likely deleted or renamed)")
+ return {'CANCELLED'}
+
+ if (generator == "" or component == ""):
self.report({'ERROR'},
"Active object must be Tessellate before Update")
return {'CANCELLED'}
ob0 = bpy.data.objects[generator]
ob1 = bpy.data.objects[component]
- me0 = ob0.data
- verts = me0.vertices
temp_ob = tassellate(
- ob0, ob1, offset, zscale, gen_modifiers, com_modifiers,
- mode, scale_mode, rotation_mode, random_seed, fill_mode,
- bool_vertex_group, bool_selection, bool_shapekeys)
+ ob0, ob1, offset, zscale, gen_modifiers, com_modifiers,
+ mode, scale_mode, rotation_mode, random_seed, fill_mode,
+ bool_vertex_group, bool_selection, bool_shapekeys
+ )
if temp_ob == 0:
message = "Zero faces selected in the Base mesh!"
@@ -861,7 +1005,7 @@ class update_tessellate(bpy.types.Operator):
ob.data = temp_ob.data
bpy.data.objects.remove(temp_ob)
if merge:
- bpy.ops.object.mode_set(mode = 'EDIT')
+ bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.select_mode(
use_extend=False, use_expand=False, type='VERT')
bpy.ops.mesh.select_non_manifold(
@@ -869,15 +1013,15 @@ class update_tessellate(bpy.types.Operator):
use_multi_face=False, use_non_contiguous=False, use_verts=False)
bpy.ops.mesh.remove_doubles(
threshold=merge_thres, use_unselected=False)
- bpy.ops.object.mode_set(mode = 'OBJECT')
+ bpy.ops.object.mode_set(mode='OBJECT')
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.object.mode_set(mode='OBJECT')
# MATERIALS
try:
# create materials list
- polygon_materials = [p.material_index for p in ob1.data.polygons]*int(
- len(ob.data.polygons) / len(ob1.data.polygons))
+ polygon_materials = [p.material_index for p in ob1.data.polygons] * int(
+ len(ob.data.polygons) / len(ob1.data.polygons))
# assign old material
component_materials = [slot.material for slot in ob1.material_slots]
for i in range(len(component_materials)):
@@ -895,75 +1039,126 @@ class update_tessellate(bpy.types.Operator):
return True
-class settings_tessellate(bpy.types.Operator):
-#class adaptive_duplifaces(bpy.types.Panel):
+class settings_tessellate(Operator):
bl_idname = "object.settings_tessellate"
bl_label = "Settings"
- bl_description = ("Update the tessellated mesh according to base and "
- "component changes. Allow also to change tessellation's parameters")
+ bl_description = ("Update the tessellated mesh according to base and component changes\n"
+ "Allow also to change tessellation's parameters")
bl_options = {'REGISTER', 'UNDO'}
- object_name = bpy.props.StringProperty(
- name="", description="Name of the generated object")
- zscale = bpy.props.FloatProperty(
- name="Scale", default=1, soft_min=0, soft_max=10,
- description="Scale factor for the component thickness")
- scale_mode = bpy.props.EnumProperty(
- items=(('CONSTANT', "Constant", ""), ('ADAPTIVE', "Proportional", "")),
- default='ADAPTIVE', name="Scale variation")
- offset = bpy.props.FloatProperty(
- name="Surface Offset", default=0, min=-1, max=1, soft_min=-1,
- soft_max=1, description="Surface offset")
- mode = bpy.props.EnumProperty(
- items=(('CONSTANT', "Constant", ""), ('ADAPTIVE', "Adaptive", "")),
- default='ADAPTIVE', name="Component Mode")
- rotation_mode = bpy.props.EnumProperty(
- items=(('RANDOM', "Random", ""), ('UV', "Active UV", ""),
- ('DEFAULT', "Default", "")), default='DEFAULT',
- name="Component Rotation")
- fill_mode = bpy.props.EnumProperty(
- items=(('QUAD', "Quad", ""), ('FAN', "Fan", "")), default='QUAD',
- name="Fill Mode")
- gen_modifiers = bpy.props.BoolProperty(
- name="Generator Modifiers", default=False,
- description="Apply modifiers to base object")
- com_modifiers = bpy.props.BoolProperty(
- name="Component Modifiers", default=False,
- description="Apply modifiers to component object")
- merge = bpy.props.BoolProperty(
- name="Merge", default=False,
- description="Merge vertices in adjacent duplicates")
- merge_thres = bpy.props.FloatProperty(
- name="Distance", default=0.001, soft_min=0, soft_max=10,
- description="Limit below which to merge vertices")
- generator = bpy.props.StringProperty(
- name="", description="Base object for the tessellation")
- component = bpy.props.StringProperty(
- name="", description="Component object for the tessellation")
- bool_random = bpy.props.BoolProperty(
- name="Randomize", default=False,
- description="Randomize component rotation")
- random_seed = bpy.props.IntProperty(
- name="Seed", default=0, soft_min=0, soft_max=10,
- description="Random seed")
- bool_vertex_group = bpy.props.BoolProperty(
- name="Map Vertex Group", default=False, description=("Map on generated "
- "geometry the active Vertex Group from the base object"))
- bool_selection = bpy.props.BoolProperty(
- name="On selected Faces", default=False,
- description="Create Tessellation only on select faces")
- bool_shapekeys = bpy.props.BoolProperty(
- name="Use Shape Keys", default=False, description=("Use component's "
- "active Shape Key according to active Vertex Group of the base object"))
+ object_name = StringProperty(
+ name="",
+ description="Name of the generated object"
+ )
+ zscale = FloatProperty(
+ name="Scale",
+ default=1,
+ soft_min=0,
+ soft_max=10,
+ description="Scale factor for the component thickness"
+ )
+ scale_mode = EnumProperty(
+ items=(('CONSTANT', "Constant", ""), ('ADAPTIVE', "Proportional", "")),
+ default='ADAPTIVE',
+ name="Scale variation"
+ )
+ offset = FloatProperty(
+ name="Surface Offset",
+ default=0,
+ min=-1, max=1,
+ soft_min=-1,
+ soft_max=1,
+ description="Surface offset"
+ )
+ mode = EnumProperty(
+ items=(('CONSTANT', "Constant", ""), ('ADAPTIVE', "Adaptive", "")),
+ default='ADAPTIVE',
+ name="Component Mode"
+ )
+ rotation_mode = EnumProperty(
+ items=(('RANDOM', "Random", ""), ('UV', "Active UV", ""),
+ ('DEFAULT', "Default", "")),
+ default='DEFAULT',
+ name="Component Rotation"
+ )
+ fill_mode = EnumProperty(
+ items=(('QUAD', "Quad", ""), ('FAN', "Fan", "")),
+ default='QUAD',
+ name="Fill Mode"
+ )
+ gen_modifiers = BoolProperty(
+ name="Generator Modifiers",
+ default=False,
+ description="Apply modifiers to base object"
+ )
+ com_modifiers = BoolProperty(
+ name="Component Modifiers",
+ default=False,
+ description="Apply modifiers to component object"
+ )
+ merge = BoolProperty(
+ name="Merge",
+ default=False,
+ description="Merge vertices in adjacent duplicates"
+ )
+ merge_thres = FloatProperty(
+ name="Distance",
+ default=0.001,
+ soft_min=0,
+ soft_max=10,
+ description="Limit below which to merge vertices"
+ )
+ generator = StringProperty(
+ name="",
+ description="Base object for the tessellation"
+ )
+ component = StringProperty(
+ name="",
+ description="Component object for the tessellation"
+ )
+ bool_random = BoolProperty(
+ name="Randomize",
+ default=False,
+ description="Randomize component rotation"
+ )
+ random_seed = IntProperty(
+ name="Seed",
+ default=0,
+ soft_min=0,
+ soft_max=10,
+ description="Random seed"
+ )
+ bool_vertex_group = BoolProperty(
+ name="Map Vertex Group",
+ default=False,
+ description="Map on generated "
+ "geometry the active Vertex Group from the base object"
+ )
+ bool_selection = BoolProperty(
+ name="On selected Faces",
+ default=False,
+ description="Create Tessellation only on select faces"
+ )
+ bool_shapekeys = BoolProperty(
+ name="Use Shape Keys",
+ default=False,
+ description="Use component's active Shape Key according to active "
+ "Vertex Group of the base object"
+ )
go = False
- ob = bpy.types.Object
@classmethod
def poll(cls, context):
try:
return context.active_object.tissue_tessellate.generator != "" and \
context.active_object.tissue_tessellate.component != ""
- except: return False
+ except:
+ return False
+
+ @staticmethod
+ def check_gen_comp(checking):
+ # note pass the stored name key in here to check it out
+ return checking in bpy.data.objects.keys()
def draw(self, context):
layout = self.layout
@@ -990,7 +1185,22 @@ class settings_tessellate(bpy.types.Operator):
# start drawing
layout = self.layout
- #ob0 = bpy.context.active_object
+
+ # check for keys in data - as the objects can be deleted or renamed
+ if not self.check_gen_comp(self.generator) or \
+ not self.check_gen_comp(self.component):
+
+ layout.label(text="Base or Component Objects are missing from the data",
+ icon="INFO")
+ layout.label(text="(Most likely deleted or renamed)",
+ icon="BLANK1")
+ layout.label(text="Settings could not be altered anymore",
+ icon="BLANK1")
+ layout.label(text="Please re-run Tesselate with two new selected objects",
+ icon="BLANK1")
+ return
+
+ # ob0 = bpy.context.active_object
# Base and Component
col = layout.column(align=True)
row = col.row(align=True)
@@ -1007,11 +1217,14 @@ class settings_tessellate(bpy.types.Operator):
row = col.row(align=True)
col2 = row.column(align=True)
col2.prop(self, "gen_modifiers", text="Use Modifiers")
+
if len(bpy.data.objects[self.generator].modifiers) == 0:
col2.enabled = False
self.gen_modifiers = False
+
col2 = row.column(align=True)
col2.prop(self, "com_modifiers", text="Use Modifiers")
+
if len(bpy.data.objects[self.component].modifiers) == 0:
col2.enabled = False
self.com_modifiers = False
@@ -1026,19 +1239,28 @@ class settings_tessellate(bpy.types.Operator):
polygons = 0
if self.gen_modifiers:
me_temp = bpy.data.objects[self.generator].to_mesh(
- bpy.context.scene, apply_modifiers=True,
- settings = 'PREVIEW')
- else: me_temp = bpy.data.objects[self.generator].data
+ bpy.context.scene,
+ apply_modifiers=True,
+ settings='PREVIEW'
+ )
+ else:
+ me_temp = bpy.data.objects[self.generator].data
+
for p in me_temp.polygons:
if not self.bool_selection or p.select:
- if self.fill_mode == "FAN": polygons += len(p.vertices)
- else: polygons += 1
+ if self.fill_mode == "FAN":
+ polygons += len(p.vertices)
+ else:
+ polygons += 1
if self.com_modifiers:
me_temp = bpy.data.objects[self.component].to_mesh(
- bpy.context.scene, apply_modifiers=True,
- settings = 'PREVIEW')
- else: me_temp = bpy.data.objects[self.component].data
+ bpy.context.scene,
+ apply_modifiers=True,
+ settings='PREVIEW'
+ )
+ else:
+ me_temp = bpy.data.objects[self.component].data
polygons *= len(me_temp.polygons)
str_polygons = '{:0,.0f}'.format(polygons)
@@ -1069,9 +1291,11 @@ class settings_tessellate(bpy.types.Operator):
row.prop(self, "rotation_mode", text="", icon='NONE', expand=False,
slider=True, toggle=False, icon_only=False, event=False,
full_event=False, emboss=True, index=-1)
+
if self.rotation_mode == 'RANDOM':
row = col.row(align=True)
row.prop(self, "random_seed")
+
if self.rotation_mode == 'UV':
uv_error = False
if self.fill_mode == 'FAN':
@@ -1079,9 +1303,10 @@ class settings_tessellate(bpy.types.Operator):
row.label(text="UV rotation doesn't work in FAN mode",
icon='ERROR')
uv_error = True
+
if len(bpy.data.objects[self.generator].data.uv_layers) == 0:
row = col.row(align=True)
- row.label(text="'" + bpy.data.objects[self.generator].name + \
+ row.label(text="'" + bpy.data.objects[self.generator].name +
" doesn't have UV Maps", icon='ERROR')
uv_error = True
if uv_error:
@@ -1114,10 +1339,11 @@ class settings_tessellate(bpy.types.Operator):
col = layout.column(align=True)
row = col.row(align=True)
row.prop(self, "merge")
- if self.merge: row.prop(self, "merge_thres")
+ if self.merge:
+ row.prop(self, "merge_thres")
row = col.row(align=True)
- ### ADVANCED ###
+ # ADVANCED #
col = layout.column(align=True)
tessellate.rotation_mode
@@ -1126,27 +1352,27 @@ class settings_tessellate(bpy.types.Operator):
row = col.row(align=True)
col2 = row.column(align=True)
col2.prop(self, "bool_vertex_group")
+
if len(bpy.data.objects[self.generator].vertex_groups) == 0:
col2.enabled = False
- bool_vertex_group = False
+ self.bool_vertex_group = False
col2 = row.column(align=True)
col2.prop(self, "bool_shapekeys", text="Use Shape Keys")
+
if len(bpy.data.objects[self.generator].vertex_groups) == 0 or \
- bpy.data.objects[self.component].data.shape_keys == None:
+ bpy.data.objects[self.component].data.shape_keys is None:
col2.enabled = False
- bool_shapekeys = False
+ self.bool_shapekeys = False
elif len(bpy.data.objects[self.generator].vertex_groups) == 0 or \
- bpy.data.objects[self.component].data.shape_keys != None:
+ bpy.data.objects[self.component].data.shape_keys is not None:
if len(bpy.data.objects[self.component].data.shape_keys.key_blocks) < 2:
col2.enabled = False
- bool_shapekeys = False
+ self.bool_shapekeys = False
self.go = True
def execute(self, context):
self.ob = bpy.context.active_object
- old_material = None
- if(len(self.ob.material_slots) > 0):
- old_material = self.ob.material_slots[0].material
+
if not self.go:
self.generator = self.ob.tissue_tessellate.generator
self.component = self.ob.tissue_tessellate.component
@@ -1165,31 +1391,38 @@ class settings_tessellate(bpy.types.Operator):
self.bool_selection = self.ob.tissue_tessellate.bool_selection
self.bool_shapekeys = self.ob.tissue_tessellate.bool_shapekeys
- if(self.generator == "" or self.component == ""):
+ if not self.check_gen_comp(self.generator) or \
+ not self.check_gen_comp(self.component):
+ # do nothing as the Warning was already done in it UI
+ return {'CANCELLED'}
+
+ if (self.generator == "" or self.component == ""):
self.report({'ERROR'},
- "Active object must be Tessellate before Update")
+ "Active object must be Tessellated before Update")
return {'CANCELLED'}
- if(bpy.data.objects[self.generator].type != 'MESH'):
+
+ if (bpy.data.objects[self.generator].type != 'MESH'):
self.report({'ERROR'}, "Base object must be a Mesh")
return {'CANCELLED'}
- if(bpy.data.objects[self.component].type != 'MESH'):
+
+ if (bpy.data.objects[self.component].type != 'MESH'):
self.report({'ERROR'}, "Component object must be a Mesh")
return {'CANCELLED'}
ob0 = bpy.data.objects[self.generator]
ob1 = bpy.data.objects[self.component]
- me0 = ob0.data
- verts = me0.vertices
temp_ob = tassellate(
- ob0, ob1, self.offset, self.zscale, self.gen_modifiers,
- self.com_modifiers, self.mode, self.scale_mode, self.rotation_mode,
- self.random_seed, self.fill_mode, self.bool_vertex_group,
- self.bool_selection, self.bool_shapekeys)
+ ob0, ob1, self.offset, self.zscale, self.gen_modifiers,
+ self.com_modifiers, self.mode, self.scale_mode, self.rotation_mode,
+ self.random_seed, self.fill_mode, self.bool_vertex_group,
+ self.bool_selection, self.bool_shapekeys
+ )
if temp_ob == 0:
- message = "Zero faces selected in the Base mesh!"
+ message = "Zero faces selected in the Base mesh"
self.report({'ERROR'}, message)
+
return {'CANCELLED'}
# Transfer mesh data
@@ -1200,16 +1433,18 @@ class settings_tessellate(bpy.types.Operator):
scene.objects.link(temp_ob)
temp_ob.select = True
bpy.context.scene.objects.active = temp_ob
+
try:
bpy.ops.object.vertex_group_copy_to_linked()
except:
pass
+
scene.objects.unlink(temp_ob)
bpy.data.objects.remove(temp_ob)
bpy.context.scene.objects.active = self.ob
if self.merge:
- bpy.ops.object.mode_set(mode = 'EDIT')
+ bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.select_mode(
use_extend=False, use_expand=False, type='VERT')
bpy.ops.mesh.select_non_manifold(
@@ -1217,7 +1452,7 @@ class settings_tessellate(bpy.types.Operator):
use_multi_face=False, use_non_contiguous=False, use_verts=False)
bpy.ops.mesh.remove_doubles(
threshold=self.merge_thres, use_unselected=False)
- bpy.ops.object.mode_set(mode = 'OBJECT')
+ bpy.ops.object.mode_set(mode='OBJECT')
self.ob = store_parameters(self, self.ob)
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.object.mode_set(mode='OBJECT')
@@ -1226,7 +1461,7 @@ class settings_tessellate(bpy.types.Operator):
try:
# create materials list
polygon_materials = [p.material_index for p in ob1.data.polygons] * \
- int(len(self.ob.data.polygons) / len(ob1.data.polygons))
+ int(len(self.ob.data.polygons) / len(ob1.data.polygons))
# assign old material
component_materials = [slot.material for slot in ob1.material_slots]
for i in range(len(component_materials)):
@@ -1244,16 +1479,15 @@ class settings_tessellate(bpy.types.Operator):
return True
def invoke(self, context, event):
- return context.window_manager.invoke_props_dialog(self)
+ return context.window_manager.invoke_props_dialog(self, width=400)
-class tessellate_panel(bpy.types.Panel):
+class tessellate_panel(Panel):
bl_label = "Tissue"
bl_category = "Create"
bl_space_type = "VIEW_3D"
bl_region_type = "TOOLS"
bl_options = {'DEFAULT_CLOSED'}
- #bl_context = "objectmode"
@classmethod
def poll(cls, context):
@@ -1261,42 +1495,32 @@ class tessellate_panel(bpy.types.Panel):
def draw(self, context):
layout = self.layout
+
col = layout.column(align=True)
col.label(text="Tessellate Add:")
- col.operator("object.tessellate")#, icon="STRANDS")
- #col.enable = False
- #col.operator("object.adaptive_duplifaces", icon="MESH_CUBE")
+ col.operator("object.tessellate")
+
col = layout.column(align=True)
col.label(text="Tessellate Edit:")
col.operator("object.settings_tessellate")
col.operator("object.update_tessellate")
+
col = layout.column(align=True)
col.operator("mesh.rotate_face")
- act = context.active_object
- sel = act #context.selected_objects[0]
-
- for ob1 in context.selected_objects:
- if(ob1.name == act.name or ob1.type != 'MESH'): continue
- sel = ob1
col.separator()
col.label(text="Other:")
col.operator("object.lattice_along_surface", icon="OUTLINER_OB_LATTICE")
- #col.separator()
- #col.label(text="Add Modifier:")
- try:
- if bpy.context.object.type == 'MESH':
- col.operator("object.uv_to_mesh", icon="GROUP_UVS")
- except:
- pass
-
+ act = context.active_object
+ if act and act.type == 'MESH':
+ col.operator("object.uv_to_mesh", icon="GROUP_UVS")
-class rotate_face(bpy.types.Operator):
+class rotate_face(Operator):
bl_idname = "mesh.rotate_face"
bl_label = "Rotate Faces"
- bl_description = "Rotate selected faces and update tessellated meshes."
+ bl_description = "Rotate selected faces and update tessellated meshes"
bl_options = {'REGISTER', 'UNDO'}
@classmethod
@@ -1314,17 +1538,17 @@ class rotate_face(bpy.types.Operator):
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.flip_normals()
bpy.ops.mesh.flip_normals()
- #me.vertices[0].co[0] = 10
me.update(calc_edges=True)
- #update tessellated meshes
+ # update tessellated meshes
bpy.ops.object.mode_set(mode='OBJECT')
- for o in [object for object in bpy.data.objects if \
- object.tissue_tessellate.generator == ob.name]:
+ for o in [obj for obj in bpy.data.objects if
+ obj.tissue_tessellate.generator == ob.name]:
bpy.context.scene.objects.active = o
bpy.ops.object.update_tessellate()
bpy.context.scene.objects.active = ob
bpy.ops.object.mode_set(mode='EDIT')
+
return {'FINISHED'}
diff --git a/mesh_tissue/uv_to_mesh.py b/mesh_tissue/uv_to_mesh.py
index ad119f4a..7c64b5f5 100644
--- a/mesh_tissue/uv_to_mesh.py
+++ b/mesh_tissue/uv_to_mesh.py
@@ -16,8 +16,8 @@
#
# ##### END GPL LICENSE BLOCK #####
-#---------------------------------- UV to MESH --------------------------------#
-#--------------------------------- version 0.1 --------------------------------#
+# --------------------------------- UV to MESH ------------------------------- #
+# -------------------------------- version 0.1.1 ----------------------------- #
# #
# Create a new Mesh based on active UV #
# #
@@ -26,57 +26,67 @@
# #
# http://www.co-de-it.com/ #
# #
-################################################################################
-
-import bpy
-import bmesh, math
-from mathutils import Vector
+# ############################################################################ #
bl_info = {
"name": "UV to Mesh",
"author": "Alessandro Zomparelli (Co-de-iT)",
- "version": (0, 1),
+ "version": (0, 1, 1),
"blender": (2, 7, 9),
"location": "",
"description": "Create a new Mesh based on active UV",
"warning": "",
"wiki_url": "",
- "tracker_url": "",
"category": "Mesh"}
-class uv_to_mesh(bpy.types.Operator):
- bl_idname = "object.uv_to_mesh"
- bl_label = "UV to Mesh"
- bl_options = {'REGISTER', 'UNDO'}
- bl_description = ("Create a new Mesh based on active UV")
- apply_modifiers = bpy.props.BoolProperty(
- name="Apply Modifiers", default=False,
- description="Apply object's modifiers")
+import bpy
+import math
+from bpy.types import Operator
+from bpy.props import BoolProperty
+from mathutils import Vector
- vertex_groups = bpy.props.BoolProperty(
- name="Keep Vertex Groups", default=False,
- description="Transfer all the Vertex Groups")
- materials = bpy.props.BoolProperty(
- name="Keep Materials", default=True,
- description="Transfer all the Materials")
+class uv_to_mesh(Operator):
+ bl_idname = "object.uv_to_mesh"
+ bl_label = "UV to Mesh"
+ bl_description = ("Create a new Mesh based on active UV")
+ bl_options = {'REGISTER', 'UNDO'}
- auto_scale = bpy.props.BoolProperty(
- name="Resize", default=True,
- description="Scale the new object in order to preserve the average surface area")
+ apply_modifiers = BoolProperty(
+ name="Apply Modifiers",
+ default=False,
+ description="Apply object's modifiers"
+ )
+ vertex_groups = BoolProperty(
+ name="Keep Vertex Groups",
+ default=False,
+ description="Transfer all the Vertex Groups"
+ )
+ materials = BoolProperty(
+ name="Keep Materials",
+ default=True,
+ description="Transfer all the Materials"
+ )
+ auto_scale = BoolProperty(
+ name="Resize",
+ default=True,
+ description="Scale the new object in order to preserve the average surface area"
+ )
def execute(self, context):
bpy.ops.object.mode_set(mode='OBJECT')
- for o in bpy.data.objects: o.select = False
+ for o in bpy.data.objects:
+ o.select = False
bpy.context.object.select = True
+
if self.apply_modifiers:
bpy.ops.object.duplicate_move()
bpy.ops.object.convert(target='MESH')
ob0 = bpy.context.object
me0 = ob0.to_mesh(bpy.context.scene,
- apply_modifiers=self.apply_modifiers, settings = 'PREVIEW')
+ apply_modifiers=self.apply_modifiers, settings='PREVIEW')
area = 0
verts = []
@@ -89,8 +99,9 @@ class uv_to_mesh(bpy.types.Operator):
try:
for loop in face.loop_indices:
uv = me0.uv_layers.active.data[loop].uv
- if uv.x != 0 and uv.y != 0: store = True
- new_vert = Vector((uv.x,uv.y,0))
+ if uv.x != 0 and uv.y != 0:
+ store = True
+ new_vert = Vector((uv.x, uv.y, 0))
verts.append(new_vert)
uv_face.append(loop)
if store:
@@ -98,10 +109,12 @@ class uv_to_mesh(bpy.types.Operator):
face_materials.append(face.material_index)
except:
self.report({'ERROR'}, "Missing UV Map")
+
return {'CANCELLED'}
+
name = ob0.name + 'UV'
# Create mesh and object
- me = bpy.data.meshes.new(name+'Mesh')
+ me = bpy.data.meshes.new(name + 'Mesh')
ob = bpy.data.objects.new(name, me)
# Link object to scene and make active
@@ -120,6 +133,7 @@ class uv_to_mesh(bpy.types.Operator):
new_area += p.area
if new_area == 0:
self.report({'ERROR'}, "Impossible to generate mesh from UV")
+
return {'CANCELLED'}
# VERTEX GROUPS
@@ -136,8 +150,9 @@ class uv_to_mesh(bpy.types.Operator):
ob0.select = False
if self.auto_scale:
- scaleFactor = math.pow(area/new_area,1/2)
- ob.scale = Vector((scaleFactor,scaleFactor,scaleFactor))
+ scaleFactor = math.pow(area / new_area, 1 / 2)
+ ob.scale = Vector((scaleFactor, scaleFactor, scaleFactor))
+
bpy.ops.object.mode_set(mode='EDIT', toggle=False)
bpy.ops.mesh.remove_doubles(threshold=1e-06)
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)