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

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'mesh_tissue/curves_tools.py')
-rw-r--r--mesh_tissue/curves_tools.py803
1 files changed, 803 insertions, 0 deletions
diff --git a/mesh_tissue/curves_tools.py b/mesh_tissue/curves_tools.py
new file mode 100644
index 00000000..5f6e07a4
--- /dev/null
+++ b/mesh_tissue/curves_tools.py
@@ -0,0 +1,803 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# #
+# (c) Alessandro Zomparelli #
+# (2017) #
+# #
+# http://www.co-de-it.com/ #
+# #
+# ############################################################################ #
+
+
+import bpy, bmesh
+from bpy.types import Operator
+from bpy.props import (
+ IntProperty,
+ BoolProperty,
+ EnumProperty,
+ PointerProperty,
+ StringProperty,
+ FloatProperty
+ )
+from bpy.types import (
+ Operator,
+ Panel,
+ PropertyGroup,
+ )
+
+import numpy as np
+from mathutils import Vector
+from math import pi
+from .utils import (
+ find_curves,
+ update_curve_from_pydata,
+ simple_to_mesh,
+ convert_object_to_mesh,
+ get_weight_numpy,
+ loops_from_bmesh,
+ get_mesh_before_subs
+ )
+import time
+
+
+def anim_curve_active(self, context):
+ ob = context.object
+ props = ob.tissue_to_curve
+ try:
+ props.object.name
+ if not ob.tissue.bool_lock:
+ bpy.ops.object.tissue_convert_to_curve_update()
+ except: pass
+
+
+class tissue_to_curve_prop(PropertyGroup):
+ object : PointerProperty(
+ type=bpy.types.Object,
+ name="",
+ description="Source object",
+ update = anim_curve_active
+ )
+ bool_smooth : BoolProperty(
+ name="Smooth Shading",
+ default=True,
+ description="Output faces with smooth shading rather than flat shaded",
+ update = anim_curve_active
+ )
+ bool_lock : BoolProperty(
+ name="Lock",
+ description="Prevent automatic update on settings changes or if other objects have it in the hierarchy.",
+ default=False,
+ update = anim_curve_active
+ )
+ bool_dependencies : BoolProperty(
+ name="Update Dependencies",
+ description="Automatically updates source object as well, when possible",
+ default=False,
+ update = anim_curve_active
+ )
+ bool_run : BoolProperty(
+ name="Animatable Curve",
+ description="Automatically recompute the conversion when the frame is changed.",
+ default = False
+ )
+ use_modifiers : BoolProperty(
+ name="Use Modifiers",
+ default=True,
+ description="Automatically apply Modifiers and Shape Keys",
+ update = anim_curve_active
+ )
+ subdivision_mode : EnumProperty(
+ items=(
+ ('ALL', "All", ""),
+ ('CAGE', "Cage", ""),
+ ('INNER', "Inner", "")
+ ),
+ default='CAGE',
+ name="Subdivided Edges",
+ update = anim_curve_active
+ )
+ use_endpoint_u : BoolProperty(
+ name="Endpoint U",
+ default=True,
+ description="Make all open nurbs curve meet the endpoints",
+ update = anim_curve_active
+ )
+ clean_distance : FloatProperty(
+ name="Merge Distance", default=0, min=0, soft_max=10,
+ description="Merge Distance",
+ update = anim_curve_active
+ )
+ nurbs_order : IntProperty(
+ name="Order", default=4, min=2, max=6,
+ description="Nurbs order",
+ update = anim_curve_active
+ )
+ system : IntProperty(
+ name="System", default=0, min=0,
+ description="Particle system index",
+ update = anim_curve_active
+ )
+ bounds_selection : EnumProperty(
+ items=(
+ ('ALL', "All", ""),
+ ('BOUNDS', "Boundaries", ""),
+ ('INNER', "Inner", "")
+ ),
+ default='ALL',
+ name="Boundary Selection",
+ update = anim_curve_active
+ )
+ periodic_selection : EnumProperty(
+ items=(
+ ('ALL', "All", ""),
+ ('OPEN', "Open", ""),
+ ('CLOSED', "Closed", "")
+ ),
+ default='ALL',
+ name="Periodic Selection",
+ update = anim_curve_active
+ )
+ spline_type : EnumProperty(
+ items=(
+ ('POLY', "Poly", ""),
+ ('BEZIER', "Bezier", ""),
+ ('NURBS', "NURBS", "")
+ ),
+ default='POLY',
+ name="Spline Type",
+ update = anim_curve_active
+ )
+ mode : EnumProperty(
+ items=(
+ ('LOOPS', "Loops", ""),
+ ('EDGES', "Edges", ""),
+ ('PARTICLES', "Particles", "")
+ ),
+ default='LOOPS',
+ name="Conversion Mode",
+ update = anim_curve_active
+ )
+ vertex_group : StringProperty(
+ name="Radius", default='',
+ description="Vertex Group used for variable radius",
+ update = anim_curve_active
+ )
+ invert_vertex_group : BoolProperty(default=False,
+ description='Inverte the value of the Vertex Group',
+ update = anim_curve_active
+ )
+ vertex_group_factor : FloatProperty(
+ name="Factor",
+ default=0,
+ min=0,
+ max=1,
+ description="Depth bevel factor to use for zero vertex group influence",
+ update = anim_curve_active
+ )
+ only_sharp : BoolProperty(
+ default=False,
+ name="Only Sharp Edges",
+ description='Convert only Sharp edges',
+ update = anim_curve_active
+ )
+ pattern_depth : FloatProperty(
+ name="Depth",
+ default=0.02,
+ min=0,
+ soft_max=10,
+ description="Displacement pattern depth",
+ update = anim_curve_active
+ )
+ pattern_offset : FloatProperty(
+ name="Offset",
+ default=0,
+ soft_min=-1,
+ soft_max=1,
+ description="Displacement pattern offset",
+ update = anim_curve_active
+ )
+ pattern0 : IntProperty(
+ name="Step 0",
+ default=0,
+ min=0,
+ soft_max=10,
+ description="Pattern step 0",
+ update = anim_curve_active
+ )
+ pattern1 : IntProperty(
+ name="Step 1",
+ default=0,
+ min=0,
+ soft_max=10,
+ description="Pattern step 1",
+ update = anim_curve_active
+ )
+
+class tissue_convert_to_curve(Operator):
+ bl_idname = "object.tissue_convert_to_curve"
+ bl_label = "Tissue Convert to Curve"
+ bl_description = "Convert selected mesh to Curve object"
+ bl_options = {'REGISTER', 'UNDO'}
+
+ object : StringProperty(
+ name="",
+ description="Source object",
+ default = ""
+ )
+ bool_smooth : BoolProperty(
+ name="Smooth Shading",
+ default=True,
+ description="Output faces with smooth shading rather than flat shaded"
+ )
+ use_modifiers : BoolProperty(
+ name="Use Modifiers",
+ default=True,
+ description="Automatically apply Modifiers and Shape Keys"
+ )
+ subdivision_mode : EnumProperty(
+ items=(
+ ('ALL', "All", ""),
+ ('CAGE', "Cage", ""),
+ ('INNER', "Inner", "")
+ ),
+ default='CAGE',
+ name="Subdivided Edges"
+ )
+ use_endpoint_u : BoolProperty(
+ name="Endpoint U",
+ default=True,
+ description="Make all open nurbs curve meet the endpoints"
+ )
+ nurbs_order : IntProperty(
+ name="Order", default=4, min=2, max=6,
+ description="Nurbs order"
+ )
+ system : IntProperty(
+ name="System", default=0, min=0,
+ description="Particle system index"
+ )
+ clean_distance : FloatProperty(
+ name="Merge Distance", default=0, min=0, soft_max=10,
+ description="Merge Distance"
+ )
+ spline_type : EnumProperty(
+ items=(
+ ('POLY', "Poly", ""),
+ ('BEZIER', "Bezier", ""),
+ ('NURBS', "NURBS", "")
+ ),
+ default='POLY',
+ name="Spline Type"
+ )
+ bounds_selection : EnumProperty(
+ items=(
+ ('ALL', "All", ""),
+ ('BOUNDS', "Boundaries", ""),
+ ('INNER', "Inner", "")
+ ),
+ default='ALL',
+ name="Boundary Selection"
+ )
+ periodic_selection : EnumProperty(
+ items=(
+ ('ALL', "All", ""),
+ ('OPEN', "Open", ""),
+ ('CLOSED', "Closed", "")
+ ),
+ default='ALL',
+ name="Periodic Selection"
+ )
+ mode : EnumProperty(
+ items=(
+ ('LOOPS', "Loops", ""),
+ ('EDGES', "Edges", ""),
+ ('PARTICLES', "Particles", "")
+ ),
+ default='LOOPS',
+ name="Conversion Mode"
+ )
+ vertex_group : StringProperty(
+ name="Radius", default='',
+ description="Vertex Group used for variable radius"
+ )
+ invert_vertex_group : BoolProperty(default=False,
+ description='Inverte the value of the Vertex Group'
+ )
+ vertex_group_factor : FloatProperty(
+ name="Factor",
+ default=0,
+ min=0,
+ max=1,
+ description="Depth bevel factor to use for zero vertex group influence"
+ )
+ only_sharp : BoolProperty(
+ default=False,
+ name="Only Sharp Edges",
+ description='Convert only Sharp edges'
+ )
+ pattern_depth : FloatProperty(
+ name="Depth",
+ default=0.02,
+ min=0,
+ soft_max=10,
+ description="Displacement pattern depth"
+ )
+ pattern_offset : FloatProperty(
+ name="Offset",
+ default=0,
+ soft_min=-1,
+ soft_max=1,
+ description="Displacement pattern offset"
+ )
+ pattern0 : IntProperty(
+ name="Step 0",
+ default=0,
+ min=0,
+ soft_max=10,
+ description="Pattern step 0"
+ )
+ pattern1 : IntProperty(
+ name="Step 1",
+ default=0,
+ min=0,
+ soft_max=10,
+ description="Pattern step 1"
+ )
+
+ @classmethod
+ def poll(cls, context):
+ try:
+ #bool_tessellated = context.object.tissue_tessellate.generator != None
+ ob = context.object
+ return ob.type in ('MESH','CURVE','SURFACE','FONT') and ob.mode == 'OBJECT'# and bool_tessellated
+ except:
+ return False
+
+ def invoke(self, context, event):
+ self.object = context.object.name
+ return context.window_manager.invoke_props_dialog(self)
+
+ def draw(self, context):
+ ob = context.object
+ ob0 = bpy.data.objects[self.object]
+ #props = ob.tissue_to_curve
+ layout = self.layout
+ col = layout.column(align=True)
+ row = col.row(align=True)
+ #row.label(text='Object: ' + self.object)
+ #row.prop_search(self, "object", context.scene, "objects")
+ #row.prop(self, "use_modifiers")#, icon='MODIFIER', text='')
+ col.separator()
+ col.label(text='Conversion Mode:')
+ row = col.row(align=True)
+ row.prop(
+ self, "mode", text="Conversion Mode", icon='NONE', expand=True,
+ slider=False, toggle=False, icon_only=False, event=False,
+ full_event=False, emboss=True, index=-1)
+ if self.mode == 'PARTICLES':
+ col.separator()
+ col.prop(self, "system")
+ col.separator()
+ if self.mode in ('LOOPS', 'EDGES'):
+ row = col.row(align=True)
+ row.prop(self, "use_modifiers")
+ col2 = row.column(align=True)
+ if self.use_modifiers:
+ col2.prop(self, "subdivision_mode", text='', icon='NONE', expand=False,
+ slider=True, toggle=False, icon_only=False, event=False,
+ full_event=False, emboss=True, index=-1)
+ col2.enabled = False
+ for m in bpy.data.objects[self.object].modifiers:
+ if m.type in ('SUBSURF','MULTIRES'): col2.enabled = True
+ col.separator()
+ row = col.row(align=True)
+ row.label(text='Filter Edges:')
+ col2 = row.column(align=True)
+ col2.prop(self, "bounds_selection", text='', icon='NONE', expand=False,
+ slider=True, toggle=False, icon_only=False, event=False,
+ full_event=False, emboss=True, index=-1)
+ col2.prop(self, 'only_sharp')
+ col.separator()
+ if self.mode == 'LOOPS':
+ row = col.row(align=True)
+ row.label(text='Filter Loops:')
+ row.prop(self, "periodic_selection", text='', 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='Spline Type:')
+ row = col.row(align=True)
+ row.prop(
+ self, "spline_type", text="Spline Type", icon='NONE', expand=True,
+ slider=False, toggle=False, icon_only=False, event=False,
+ full_event=False, emboss=True, index=-1)
+ if self.spline_type == 'NURBS':
+ col.separator()
+ col.label(text='Nurbs splines:')
+ row = col.row(align=True)
+ row.prop(self, "use_endpoint_u")
+ row.prop(self, "nurbs_order")
+ col.separator()
+ col.prop(self, "bool_smooth")
+ if ob0.type == 'MESH' and self.mode != 'PARTICLES':
+ col.separator()
+ col.label(text='Variable Radius:')
+ row = col.row(align=True)
+ row.prop_search(self, 'vertex_group', ob0, "vertex_groups", text='')
+ row.prop(self, "invert_vertex_group", text="", toggle=True, icon='ARROW_LEFTRIGHT')
+ row.prop(self, "vertex_group_factor")
+ col.separator()
+ col.label(text='Clean curves:')
+ col.prop(self, "clean_distance")
+ col.separator()
+ col.label(text='Displacement Pattern:')
+ row = col.row(align=True)
+ row.prop(self, "pattern0")
+ row.prop(self, "pattern1")
+ row = col.row(align=True)
+ row.prop(self, "pattern_depth")
+ row.prop(self, "pattern_offset")
+
+ def execute(self, context):
+ ob = context.active_object
+
+ crv = bpy.data.curves.new(ob.name + '_Curve', type='CURVE')
+ crv.dimensions = '3D'
+ new_ob = bpy.data.objects.new(ob.name + '_Curve', crv)
+ bpy.context.collection.objects.link(new_ob)
+ context.view_layer.objects.active = new_ob
+
+ new_ob.select_set(True)
+ ob.select_set(False)
+ new_ob.matrix_world = ob.matrix_world
+
+ new_ob.tissue.tissue_type = 'TO_CURVE'
+ new_ob.tissue.bool_lock = True
+
+ props = new_ob.tissue_to_curve
+ props.object = ob
+ props.use_modifiers = self.use_modifiers
+ props.subdivision_mode = self.subdivision_mode
+ props.clean_distance = self.clean_distance
+ props.spline_type = self.spline_type
+ props.mode = self.mode
+ props.use_endpoint_u = self.use_endpoint_u
+ props.nurbs_order = self.nurbs_order
+ props.vertex_group = self.vertex_group
+ props.vertex_group_factor = self.vertex_group_factor
+ props.invert_vertex_group = self.invert_vertex_group
+ props.bool_smooth = self.bool_smooth
+ props.system = self.system
+ props.periodic_selection = self.periodic_selection
+ props.bounds_selection = self.bounds_selection
+ props.only_sharp = self.only_sharp
+ props.pattern0 = self.pattern0
+ props.pattern1 = self.pattern1
+ props.pattern_depth = self.pattern_depth
+ props.pattern_offset = self.pattern_offset
+
+ new_ob.tissue.bool_lock = False
+
+ bpy.ops.object.tissue_convert_to_curve_update()
+
+ return {'FINISHED'}
+
+class tissue_convert_to_curve_update(Operator):
+ bl_idname = "object.tissue_convert_to_curve_update"
+ bl_label = "Tissue Update Curve"
+ bl_description = "Update Curve object"
+ bl_options = {'REGISTER', 'UNDO'}
+
+ @classmethod
+ def poll(cls, context):
+ try:
+ ob = context.object
+ bool_curve = ob.tissue_to_curve.object != None
+ return ob.type == 'CURVE' and ob.mode == 'OBJECT' and bool_curve
+ except:
+ return False
+
+ def execute(self, context):
+ start_time = time.time()
+
+ ob = context.object
+ props = ob.tissue_to_curve
+ ob0 = props.object
+ if props.mode == 'PARTICLES':
+ eval_ob = ob0.evaluated_get(context.evaluated_depsgraph_get())
+ system_id = min(props.system, len(eval_ob.particle_systems))
+ psystem = eval_ob.particle_systems[system_id]
+ ob.data.splines.clear()
+ particles = psystem.particles
+ for id,p in enumerate(particles):
+ s = ob.data.splines.new('POLY')
+ if psystem.settings.type == 'HAIR':
+ n_pts = len(p.hair_keys)
+ pts = [0]*3*n_pts
+ p.hair_keys.foreach_get('co',pts)
+ co = np.array(pts).reshape((-1,3))
+ else:
+ n_pts = 2**psystem.settings.display_step + 1
+ pts = []
+ for i in range(n_pts):
+ vec = psystem.co_hair(eval_ob, particle_no=id,step=i)
+ vec = ob0.matrix_world.inverted() @ vec
+ pts.append(vec)
+ co = np.array(pts)
+ w = np.ones(n_pts).reshape((n_pts,1))
+ co = np.concatenate((co,w),axis=1).reshape((n_pts*4))
+ s.points.add(n_pts-1)
+ s.points.foreach_set('co',co)
+
+ else:
+ _ob0 = ob0
+ ob0 = convert_object_to_mesh(ob0, apply_modifiers=props.use_modifiers)
+ me = ob0.data
+ n_verts = len(me.vertices)
+ verts = [0]*n_verts*3
+ me.vertices.foreach_get('co',verts)
+ verts = np.array(verts).reshape((-1,3))
+
+ normals = [0]*n_verts*3
+ me.vertices.foreach_get('normal',normals)
+ normals = np.array(normals).reshape((-1,3))
+ #tilt = np.degrees(np.arcsin(normals[:,2]))
+ #tilt = np.arccos(normals[:,2])/2
+
+ verts = np.array(verts).reshape((-1,3))
+ if props.mode in ('LOOPS','EDGES'):
+ bm = bmesh.new()
+ bm.from_mesh(me)
+ bm.verts.ensure_lookup_table()
+ bm.edges.ensure_lookup_table()
+ bm.faces.ensure_lookup_table()
+ todo_edges = list(bm.edges)
+ if props.use_modifiers and props.subdivision_mode != 'ALL':
+ me0, subs = get_mesh_before_subs(_ob0)
+ n_edges0 = len(me0.edges)
+ bpy.data.meshes.remove(me0)
+ if props.subdivision_mode == 'CAGE':
+ todo_edges = todo_edges[:n_edges0*(2**subs)]
+ elif props.subdivision_mode == 'INNER':
+ todo_edges = todo_edges[n_edges0*(2**subs):]
+
+ if props.only_sharp:
+ _todo_edges = []
+ sharp_verts = []
+ for e in todo_edges:
+ edge = me.edges[e.index]
+ if edge.use_edge_sharp:
+ _todo_edges.append(e)
+ sharp_verts.append(edge.vertices[0])
+ sharp_verts.append(edge.vertices[1])
+ todo_edges = _todo_edges
+
+ if props.bounds_selection == 'BOUNDS': todo_edges = [e for e in todo_edges if len(e.link_faces)<2]
+ elif props.bounds_selection == 'INNER': todo_edges = [e for e in todo_edges if len(e.link_faces)>1]
+
+ if props.mode == 'EDGES':
+ ordered_points = [[e.verts[0].index, e.verts[1].index] for e in todo_edges]
+ elif props.mode == 'LOOPS':
+ vert_loops, edge_loops = loops_from_bmesh(todo_edges)
+ if props.only_sharp:
+ ordered_points = []
+ for loop in vert_loops:
+ loop_points = []
+ for v in loop:
+ if v.index in sharp_verts:
+ loop_points.append(v.index)
+ else:
+ if len(loop_points)>1:
+ ordered_points.append(loop_points)
+ loop_points = []
+ if len(loop_points)>1:
+ ordered_points.append(loop_points)
+ #ordered_points = [[v.index for v in loop if v.index in sharp_verts] for loop in vert_loops]
+ else:
+ ordered_points = [[v.index for v in loop] for loop in vert_loops]
+ if props.periodic_selection == 'CLOSED':
+ ordered_points = [points for points in ordered_points if points[0] == points[-1]]
+ elif props.periodic_selection == 'OPEN':
+ ordered_points = [points for points in ordered_points if points[0] != points[-1]]
+ else:
+ try:
+ ordered_points = find_curves(edges, n_verts)
+ except:
+ bpy.data.objects.remove(ob0)
+ return {'CANCELLED'}
+
+ try:
+ weight = get_weight_numpy(ob0.vertex_groups[props.vertex_group], n_verts)
+ if props.invert_vertex_group: weight = 1-weight
+ fact = props.vertex_group_factor
+ if fact > 0:
+ weight = weight*(1-fact) + fact
+ except:
+ weight = None
+
+ # Set curves Tilt
+ '''
+ tilt = []
+ for points in ordered_points:
+ if points[0] == points[-1]: # Closed curve
+ pts0 = [points[-1]] + points[:-1] # i-1
+ pts1 = points[:] # i
+ pts2 = points[1:] + [points[0]] # 1+1
+ else: # Open curve
+ pts0 = [points[0]] + points[:-1] # i-1
+ pts1 = points[:] # i
+ pts2 = points[1:] + [points[-1]] # i+1
+ curve_tilt = []
+ for i0, i1, i2 in zip(pts0, pts1, pts2):
+ pt0 = Vector(verts[i0])
+ pt1 = Vector(verts[i1])
+ pt2 = Vector(verts[i2])
+ tan1 = (pt1-pt0).normalized()
+ tan2 = (pt2-pt1).normalized()
+ vec_tan = -(tan1 + tan2).normalized()
+ vec2 = vec_tan.cross(Vector((0,0,1)))
+ vec_z = vec_tan.cross(vec2)
+ nor = normals[i1]
+ if vec_z.length == 0:
+ vec_z = Vector(nor)
+ ang = vec_z.angle(nor)
+ if nor[2] < 0: ang = 2*pi-ang
+ #if vec_tan[0] > vec_tan[1] and nor[0]>0: ang = -ang
+ #if vec_tan[0] > vec_tan[2] and nor[0]>0: ang = -ang
+ #if vec_tan[0] < vec_tan[1] and nor[1]>0: ang = -ang
+ #if nor[0]*nor[1]*nor[2] < 0: ang = -ang
+ if nor[2] == 0: ang = -5*pi/4
+ #ang = max(ang, np.arccos(nor[2]))
+ curve_tilt.append(ang)
+ #curve_tilt.append(np.arccos(nor[2]))
+ tilt.append(curve_tilt)
+ '''
+ depth = props.pattern_depth
+ offset = props.pattern_offset
+ pattern = [props.pattern0,props.pattern1]
+ update_curve_from_pydata(ob.data, verts, normals, weight, ordered_points, merge_distance=props.clean_distance, pattern=pattern, depth=depth, offset=offset)
+
+
+ bpy.data.objects.remove(ob0)
+ for s in ob.data.splines:
+ s.type = props.spline_type
+ if s.type == 'NURBS':
+ s.use_endpoint_u = props.use_endpoint_u
+ s.order_u = props.nurbs_order
+ ob.data.splines.update()
+ if not props.bool_smooth: bpy.ops.object.shade_flat()
+
+ end_time = time.time()
+ print('Tissue: object "{}" converted to Curve in {:.4f} sec'.format(ob.name, end_time-start_time))
+
+ return {'FINISHED'}
+
+
+class TISSUE_PT_convert_to_curve(Panel):
+ bl_space_type = 'PROPERTIES'
+ bl_region_type = 'WINDOW'
+ bl_context = "data"
+ bl_label = "Tissue Convert to Curve"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ @classmethod
+ def poll(cls, context):
+ try:
+ #bool_curve = context.object.tissue_to_curve.object != None
+ ob = context.object
+ return ob.type == 'CURVE' and ob.tissue.tissue_type == 'TO_CURVE'
+ except:
+ return False
+
+ def draw(self, context):
+ ob = context.object
+ props = ob.tissue_to_curve
+
+ layout = self.layout
+ #layout.use_property_split = True
+ #layout.use_property_decorate = False
+ col = layout.column(align=True)
+ row = col.row(align=True)
+ #col.operator("object.tissue_convert_to_curve_update", icon='FILE_REFRESH', text='Refresh')
+ row.operator("object.tissue_update_tessellate_deps", icon='FILE_REFRESH', text='Refresh') ####
+ lock_icon = 'LOCKED' if ob.tissue.bool_lock else 'UNLOCKED'
+ #lock_icon = 'PINNED' if props.bool_lock else 'UNPINNED'
+ deps_icon = 'LINKED' if ob.tissue.bool_dependencies else 'UNLINKED'
+ row.prop(ob.tissue, "bool_dependencies", text="", icon=deps_icon)
+ row.prop(ob.tissue, "bool_lock", text="", icon=lock_icon)
+ col2 = row.column(align=True)
+ col2.prop(ob.tissue, "bool_run", text="",icon='TIME')
+ col2.enabled = not ob.tissue.bool_lock
+
+ col.separator()
+ row = col.row(align=True)
+ row.prop_search(props, "object", context.scene, "objects")
+ row.prop(props, "use_modifiers", icon='MODIFIER', text='')
+ col.separator()
+ col.label(text='Conversion Mode:')
+ row = col.row(align=True)
+ row.prop(
+ props, "mode", icon='NONE', expand=True,
+ slider=False, toggle=False, icon_only=False, event=False,
+ full_event=False, emboss=True, index=-1)
+ if props.mode == 'PARTICLES':
+ col.separator()
+ col.prop(props, "system")
+ col.separator()
+
+ if props.mode in ('LOOPS', 'EDGES'):
+ row = col.row(align=True)
+ row.prop(props, "use_modifiers")
+ col2 = row.column(align=True)
+ if props.use_modifiers:
+ col2.prop(props, "subdivision_mode", text='', icon='NONE', expand=False,
+ slider=True, toggle=False, icon_only=False, event=False,
+ full_event=False, emboss=True, index=-1)
+ col2.enabled = False
+ for m in props.object.modifiers:
+ if m.type in ('SUBSURF','MULTIRES'): col2.enabled = True
+ col.separator()
+ row = col.row(align=True)
+ row.label(text='Filter Edges:')
+ col2 = row.column(align=True)
+ col2.prop(props, "bounds_selection", text='', icon='NONE', expand=False,
+ slider=True, toggle=False, icon_only=False, event=False,
+ full_event=False, emboss=True, index=-1)
+ col2.prop(props, 'only_sharp')
+ col.separator()
+ if props.mode == 'LOOPS':
+ row = col.row(align=True)
+ row.label(text='Filter Loops:')
+ row.prop(props, "periodic_selection", text='', 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='Spline Type:')
+ row = col.row(align=True)
+ row.prop(
+ props, "spline_type", text="Spline Type", icon='NONE', expand=True,
+ slider=False, toggle=False, icon_only=False, event=False,
+ full_event=False, emboss=True, index=-1)
+ if props.spline_type == 'NURBS':
+ col.separator()
+ col.label(text='Nurbs Splines:')
+ row = col.row(align=True)
+ row.prop(props, "use_endpoint_u")
+ row.prop(props, "nurbs_order")
+ col.separator()
+ col.prop(props, "bool_smooth")
+ if props.object.type == 'MESH':
+ col.separator()
+ col.label(text='Variable Radius:')
+ row = col.row(align=True)
+ row.prop_search(props, 'vertex_group', props.object, "vertex_groups", text='')
+ row.prop(props, "invert_vertex_group", text="", toggle=True, icon='ARROW_LEFTRIGHT')
+ row.prop(props, "vertex_group_factor")
+ col.separator()
+ col.label(text='Clean Curves:')
+ col.prop(props, "clean_distance")
+ col.separator()
+ col.label(text='Displacement Pattern:')
+ row = col.row(align=True)
+ row.prop(props, "pattern0")
+ row.prop(props, "pattern1")
+ row = col.row(align=True)
+ row.prop(props, "pattern_depth")
+ row.prop(props, "pattern_offset")