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
path: root/btrace
diff options
context:
space:
mode:
authorlijenstina <lijenstina@gmail.com>2017-04-12 01:57:41 +0300
committerlijenstina <lijenstina@gmail.com>2017-04-12 01:57:41 +0300
commit5d5098af42dbaa631f6a90de5a327523f92bdc45 (patch)
treec7a703fef9fd9df2a282fcdb4cf907abd94da299 /btrace
parent1af1c0963a14fba18f642a87394df05f6c8d3128 (diff)
Btrace: Major cleanup, reorganization
Bumped version to 1.2.1 Remove star imports Split the bTrace file into two Move the Panel and props code into the new file Pep8 cleanup Change the complicated switcher UI code Bools replace them with one EnumProperty This makes the second PropertyGroup not needed Make optional layout configuration in the preferences Fix the crashes with the Drawing operator Fix several crashes with wrong contexts Some small UI fixes More graceful error handling
Diffstat (limited to 'btrace')
-rw-r--r--btrace/__init__.py123
-rw-r--r--btrace/bTrace.py2610
-rw-r--r--btrace/bTrace_props.py951
3 files changed, 2162 insertions, 1522 deletions
diff --git a/btrace/__init__.py b/btrace/__init__.py
index 40ff4df1..c1f62512 100644
--- a/btrace/__init__.py
+++ b/btrace/__init__.py
@@ -1,43 +1,96 @@
-#BEGIN GPL LICENSE BLOCK
+# ##### 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 #####
-#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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-#END GPL LICENCE BLOCK
bl_info = {
"name": "Btrace",
"author": "liero, crazycourier, Atom, Meta-Androcto, MacKracken",
- "version": (1, 1, ),
- "blender": (2, 68, 0),
+ "version": (1, 2, 1),
+ "blender": (2, 78, 0),
"location": "View3D > Tools",
"description": "Tools for converting/animating objects/particles into curves",
"warning": "",
"wiki_url": "https://wiki.blender.org/index.php/Extensions:2.6/Py/Scripts/Curve/Btrace",
- "tracker_url": "https://developer.blender.org/maniphest/task/edit/form/2/",
"category": "Add Curve"}
+if "bpy" in locals():
+ import importlib
+ importlib.reload(bTrace_props)
+ importlib.reload(bTrace)
+else:
+ from . import bTrace_props
+ from . import bTrace
import bpy
-from .bTrace import *
-import selection_utils
-from bpy.props import FloatProperty, EnumProperty, IntProperty, BoolProperty, FloatVectorProperty
+from bpy.types import AddonPreferences
+from .bTrace_props import (
+ TracerProperties,
+ addTracerObjectPanel,
+ )
+from .bTrace import (
+ OBJECT_OT_convertcurve,
+ OBJECT_OT_objecttrace,
+ OBJECT_OT_objectconnect,
+ OBJECT_OT_writing,
+ OBJECT_OT_particletrace,
+ OBJECT_OT_traceallparticles,
+ OBJECT_OT_curvegrow,
+ OBJECT_OT_reset,
+ OBJECT_OT_fcnoise,
+ OBJECT_OT_meshfollow,
+ OBJECT_OT_materialChango,
+ OBJECT_OT_clearColorblender,
+ )
+from bpy.props import (
+ EnumProperty,
+ PointerProperty,
+ )
+
+
+# Add-on Preferences
+class btrace_preferences(AddonPreferences):
+ bl_idname = __name__
+
+ expand_enum = EnumProperty(
+ name="UI Options",
+ items=[
+ ('list', "Drop down list",
+ "Show all the items as dropdown list in the Tools Region"),
+ ('col', "Enable Expanded UI Panel",
+ "Show all the items expanded in the Tools Region in a column"),
+ ('row', "Icons only in a row",
+ "Show all the items as icons expanded in a row in the Tools Region")
+ ],
+ description="",
+ default='list'
+ )
+
+ def draw(self, context):
+ layout = self.layout
+ layout.label("UI Options:")
-### Define Classes to register
-classes = [
+ row = layout.row(align=True)
+ row.prop(self, "expand_enum", text="UI Options", expand=True)
+
+
+# Define Classes to register
+classes = (
TracerProperties,
- TracerPropertiesMenu,
addTracerObjectPanel,
OBJECT_OT_convertcurve,
OBJECT_OT_objecttrace,
@@ -50,18 +103,22 @@ classes = [
OBJECT_OT_fcnoise,
OBJECT_OT_meshfollow,
OBJECT_OT_materialChango,
- OBJECT_OT_clearColorblender
- ]
+ OBJECT_OT_clearColorblender,
+ btrace_preferences,
+ )
+
def register():
- for c in classes:
- bpy.utils.register_class(c)
- bpy.types.WindowManager.curve_tracer = bpy.props.PointerProperty(type=TracerProperties)
- bpy.types.WindowManager.btrace_menu = bpy.props.PointerProperty(type=TracerPropertiesMenu, update=deselect_others)
+ for cls in classes:
+ bpy.utils.register_class(cls)
+ bpy.types.WindowManager.curve_tracer = PointerProperty(type=TracerProperties)
+
def unregister():
- for c in classes:
- bpy.utils.unregister_class(c)
+ for cls in classes:
+ bpy.utils.unregister_class(cls)
del bpy.types.WindowManager.curve_tracer
+
+
if __name__ == "__main__":
register()
diff --git a/btrace/bTrace.py b/btrace/bTrace.py
index 9ac2cfcd..82d93f9d 100644
--- a/btrace/bTrace.py
+++ b/btrace/bTrace.py
@@ -1,750 +1,206 @@
-#BEGIN GPL LICENSE BLOCK
+# ##### 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 #####
+
+# TO DO LIST #
+# Add more options to curve radius/modulation plus cyclic/connect curve option
-#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.
+import bpy
+import selection_utils
+from bpy.types import Operator
+from random import (
+ choice as rand_choice,
+ random as rand_random,
+ randint as rand_randint,
+ uniform as rand_uniform,
+ )
-#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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-#END GPL LICENCE BLOCK
+def error_handlers(self, op_name, error, reports="ERROR", func=False):
+ if self and reports:
+ self.report({'WARNING'}, reports + " (See Console for more info)")
-bl_info = {
- "name": "Btrace",
- "author": "liero, crazycourier, Atom, Meta-Androcto, MacKracken",
- "version": (1, 1, ),
- "blender": (2, 71, 0),
- "location": "View3D > Toolshelf > Addons Tab",
- "description": "Tools for converting/animating objects/particles into curves",
- "warning": "Still under development, bug reports appreciated",
- "wiki_url": "",
- "tracker_url": "https://developer.blender.org/T29563",
- "category": "Add Curve"}
+ is_func = "Function" if func else "Operator"
+ print("\n[Btrace]\n{}: {}\nError: {}\n".format(op_name, is_func, error))
-#### TO DO LIST ####
-### [ ] Add more options to curve radius/modulation plus cyclic/connect curve option
+# Object Trace
+# creates a curve with a modulated radius connecting points of a mesh
-import bpy
-import selection_utils
-from bpy.props import FloatProperty, EnumProperty, IntProperty, BoolProperty, FloatVectorProperty
-
-
-def deselect_others(ob, context):
- """For tool menu select, deselects others if one selected"""
- selected = addTracerObjectPanel.selected
- ob[selected] = False
- keys = [key for key in ob.keys() if ob[key]] # all the True keys
- if len(keys) <= 0:
- ob[selected] = True # reselect
- return None
- for key in keys:
- addTracerObjectPanel.selected = key
- ob[key] = True
-
-
-# Class for properties panel
-class TracerPropertiesMenu(bpy.types.PropertyGroup):
- """Toolbar show/hide booleans for tool options"""
- tool_objectTrace = BoolProperty(name="Object Trace", default=False, description="Trace selected mesh object with a curve", update=deselect_others)
- tool_objectsConnect = BoolProperty(name="Objects Connect", default=False, description="Connect objects with a curve controlled by hooks", update=deselect_others)
- tool_particleTrace = BoolProperty(name="Particle Trace", default=False, description="Trace particle path with a curve", update=deselect_others)
- tool_meshFollow = BoolProperty(name="Mesh Follow", default=False, description="Follow selection items on animated mesh object", update=deselect_others)
- tool_particleConnect = BoolProperty(name="Particle Connect", default=False, description="Connect particles with a curves and animated over particle lifetime", update=deselect_others)
- tool_growCurve = BoolProperty(name="Grow Curve", default=False, description="Animate curve bevel over time by keyframing points radius", update=deselect_others)
- tool_handwrite = BoolProperty(name="Handwriting", default=False, description="Create and Animate curve using the grease pencil", update=deselect_others)
- tool_fcurve = BoolProperty(name="F-Curve Noise", default=False, description="Add F-Curve noise to selected objects", update=deselect_others)
- tool_colorblender = BoolProperty(name="Color Blender", default=False, description="Add F-Curve noise to selected objects", update=deselect_others)
-
-
-# Class to define properties
-class TracerProperties(bpy.types.PropertyGroup):
- """Options for tools"""
- curve_spline = EnumProperty(name="Spline", items=(("POLY", "Poly", "Use Poly spline type"), ("NURBS", "Nurbs", "Use Nurbs spline type"), ("BEZIER", "Bezier", "Use Bezier spline type")), description="Choose which type of spline to use when curve is created", default="BEZIER")
- curve_handle = EnumProperty(name="Handle", items=(("ALIGNED", "Aligned", "Use Aligned Handle Type"), ("AUTOMATIC", "Automatic", "Use Auto Handle Type"), ("FREE_ALIGN", "Free Align", "Use Free Handle Type"), ("VECTOR", "Vector", "Use Vector Handle Type")), description="Choose which type of handle to use when curve is created", default="VECTOR")
- curve_resolution = IntProperty(name="Bevel Resolution", min=1, max=32, default=4, description="Adjust the Bevel resolution")
- curve_depth = FloatProperty(name="Bevel Depth", min=0.0, max=100.0, default=0.1, description="Adjust the Bevel depth")
- curve_u = IntProperty(name="Resolution U", min=0, max=64, default=12, description="Adjust the Surface resolution")
- curve_join = BoolProperty(name="Join Curves", default=False, description="Join all the curves after they have been created")
- curve_smooth = BoolProperty(name="Smooth", default=True, description="Render curve smooth")
- # Option to Duplicate Mesh
- object_duplicate = BoolProperty(name="Apply to Copy", default=False, description="Apply curve to a copy of object")
- # Distort Mesh options
- distort_modscale = IntProperty(name="Modulation Scale", min=0, max=50, default=2, description="Add a scale to modulate the curve at random points, set to 0 to disable")
- distort_noise = FloatProperty(name="Mesh Noise", min=0.0, max=50.0, default=0.00, description="Adjust noise added to mesh before adding curve")
- # Particle Options
- particle_step = IntProperty(name="Step Size", min=1, max=50, default=5, description="Sample one every this number of frames")
- particle_auto = BoolProperty(name='Auto Frame Range', default=True, description='Calculate Frame Range from particles life')
- particle_f_start = IntProperty(name='Start Frame', min=1, max=5000, default=1, description='Start frame')
- particle_f_end = IntProperty(name='End Frame', min=1, max=5000, default=250, description='End frame')
- # F-Curve Modifier Properties
- fcnoise_rot = BoolProperty(name="Rotation", default=False, description="Affect Rotation")
- fcnoise_loc = BoolProperty(name="Location", default=True, description="Affect Location")
- fcnoise_scale = BoolProperty(name="Scale", default=False, description="Affect Scale")
- fcnoise_amp = IntProperty(name="Amp", min=1, max=500, default=5, description="Adjust the amplitude")
- fcnoise_timescale = FloatProperty(name="Time Scale", min=1, max=500, default=50, description="Adjust the time scale")
- fcnoise_key = BoolProperty(name="Add Keyframe", default=True, description="Keyframe is needed for tool, this adds a LocRotScale keyframe")
- show_curve_settings = BoolProperty(name="Curve Settings", default=False, description="Change the curve settings for the created curve")
- material_settings = BoolProperty(name="Material Settings", default=False, description="Change the material settings for the created curve")
- particle_settings = BoolProperty(name="Particle Settings", default=False, description="Show the settings for the created curve")
- animation_settings = BoolProperty(name="Animation Settings", default=False, description="Show the settings for the Animations")
- distort_curve = BoolProperty(name="Add Distortion", default=False, description="Set options to distort the final curve")
- connect_noise = BoolProperty(name="F-Curve Noise", default=False, description="Adds F-Curve Noise Modifier to selected objects")
- settings_objectTrace = BoolProperty(name="Object Trace Settings", default=False, description="Trace selected mesh object with a curve")
- settings_objectsConnect = BoolProperty(name="Objects Connect Settings", default=False, description="Connect objects with a curve controlled by hooks")
- settings_objectTrace = BoolProperty(name="Object Trace Settings", default=False, description="Trace selected mesh object with a curve")
- respect_order = BoolProperty(name="Order", default=False, description="Remember order objects were selected")
- settings_particleTrace = BoolProperty(name="Particle Trace Settings", default=False, description="Trace particle path with a curve")
- settings_particleConnect = BoolProperty(name="Particle Connect Settings", default=False, description="Connect particles with a curves and animated over particle lifetime")
- settings_growCurve = BoolProperty(name="Grow Curve Settings", default=False, description="Animate curve bevel over time by keyframing points radius")
- settings_fcurve = BoolProperty(name="F-Curve Settings", default=False, description="F-Curve Settings")
- settings_toggle = BoolProperty(name="Settings", default=False, description="Toggle Settings")
- # Animation Options
- anim_auto = BoolProperty(name='Auto Frame Range', default=True, description='Automatically calculate Frame Range')
- anim_f_start = IntProperty(name='Start', min=1, max=2500, default=1, description='Start frame / Hidden object')
- anim_length = IntProperty(name='Duration', min=1, soft_max=1000, max=2500, default=100, description='Animation Length')
- anim_f_fade = IntProperty(name='Fade After', min=0, soft_max=250, max=2500, default=10, description='Fade after this frames / Zero means no fade')
- anim_delay = IntProperty(name='Grow', min=0, max=50, default=5, description='Frames it takes a point to grow')
- anim_tails = BoolProperty(name='Tails on endpoints', default=True, description='Set radius to zero for open splines endpoints')
- anim_keepr = BoolProperty(name='Keep Radius', default=True, description='Try to keep radius data from original curve')
- animate = BoolProperty(name="Animate Result", default=False, description='Animate the final curve objects')
- # Convert to Curve options
- convert_conti = BoolProperty(name='Continuous', default=True, description='Create a continuous curve using verts from mesh')
- convert_everyedge = BoolProperty(name='Every Edge', default=False, description='Create a curve from all verts in a mesh')
- convert_edgetype = EnumProperty(name="Edge Type for Curves",
- items=(("CONTI", "Continuous", "Create a continuous curve using verts from mesh"), ("EDGEALL", "All Edges", "Create a curve from every edge in a mesh")),
- description="Choose which type of spline to use when curve is created", default="CONTI")
- convert_joinbefore = BoolProperty(name="Join objects before convert", default=False, description='Join all selected mesh to one object before converting to mesh')
- # Mesh Follow Options
- fol_edge_select = BoolProperty(name='Edge', default=False, description='Grow from edges')
- fol_vert_select = BoolProperty(name='Vertex', default=False, description='Grow from verts')
- fol_face_select = BoolProperty(name='Face', default=True, description='Grow from faces')
- fol_mesh_type = EnumProperty(name='Mesh type', default='VERTS', description='Mesh feature to draw cruves from', items=(
- ("VERTS", "Verts", "Draw from Verts"), ("EDGES", "Edges", "Draw from Edges"), ("FACES", "Faces", "Draw from Faces"), ("OBJECT", "Object", "Draw from Object origin")))
- fol_start_frame = IntProperty(name="Start Frame", min=1, max=2500, default=1, description="Start frame for range to trace")
- fol_end_frame = IntProperty(name="End Frame", min=1, max=2500, default=250, description="End frame for range to trace")
- fol_perc_verts = FloatProperty(name="Reduce selection by", min=0.001, max=1.000, default=0.5, description="percentage of total verts to trace")
- fol_sel_option = EnumProperty(name="Selection type", description="Choose which objects to follow", default="RANDOM", items=(
- ("RANDOM", "Random", "Follow Random items"), ("CUSTOM", "Custom Select", "Follow selected items"), ("ALL", "All", "Follow all items")))
- trace_mat_color = FloatVectorProperty(name="Material Color", description="Choose material color", min=0, max=1, default=(0.0,0.3,0.6), subtype="COLOR")
- trace_mat_random = BoolProperty(name="Random Color", default=False, description='Make the material colors random')
-
- # Material custom Properties properties
- mat_simple_adv_toggle = EnumProperty(name="Material Options", items=(("SIMPLE", "Simple", "Show Simple Material Options"), ("ADVANCED", "Advanced", "Show Advanced Material Options")), description="Choose which Material Options to show", default="SIMPLE")
- mat_run_color_blender = BoolProperty(name="Run Color Blender", default=False, description="Generate colors from a color scheme")
- mmColors = bpy.props.EnumProperty(
- items=(("RANDOM", "Random", "Use random colors"),
- ("CUSTOM", "Custom", "Use custom colors"),
- ("BW", "Black/White", "Use Black and White"),
- ("BRIGHT", "Bright Colors", "Use Bright colors"),
- ("EARTH", "Earth", "Use Earth colors"),
- ("GREENBLUE", "Green to Blue", "Use Green to Blue colors")),
- description="Choose which type of colors the materials uses",
- default="BRIGHT",
- name="Define a color palette")
- # Custom property for how many keyframes to skip
- mmSkip = bpy.props.IntProperty(name="frames", min=1, max=500, default=20, description="Number of frames between each keyframes")
- # Custom property to enable/disable random order for the
- mmBoolRandom = bpy.props.BoolProperty(name="Random Order", default=False, description="Randomize the order of the colors")
- # Custom Color properties
- mmColor1 = bpy.props.FloatVectorProperty(min=0, max=1, default=(0.8, 0.8, 0.8), description="Custom Color 1", subtype="COLOR")
- mmColor2 = bpy.props.FloatVectorProperty(min=0, max=1, default=(0.8, 0.8, 0.3), description="Custom Color 2", subtype="COLOR")
- mmColor3 = bpy.props.FloatVectorProperty(min=0, max=1, default=(0.8, 0.5, 0.6), description="Custom Color 3", subtype="COLOR")
- mmColor4 = bpy.props.FloatVectorProperty(min=0, max=1, default=(0.2, 0.8, 0.289), description="Custom Color 4", subtype="COLOR")
- mmColor5 = bpy.props.FloatVectorProperty(min=0, max=1, default=(1.0, 0.348, 0.8), description="Custom Color 5", subtype="COLOR")
- mmColor6 = bpy.props.FloatVectorProperty(min=0, max=1, default=(0.4, 0.67, 0.8), description="Custom Color 6", subtype="COLOR")
- mmColor7 = bpy.props.FloatVectorProperty(min=0, max=1, default=(0.66, 0.88, 0.8), description="Custom Color 7", subtype="COLOR")
- mmColor8 = bpy.props.FloatVectorProperty(min=0, max=1, default=(0.8, 0.38, 0.22), description="Custom Color 8", subtype="COLOR")
- # BW Color properties
- bwColor1 = bpy.props.FloatVectorProperty(min=0, max=1, default=(0.0,0.0,0.0), description="Black/White Color 1", subtype="COLOR")
- bwColor2 = bpy.props.FloatVectorProperty(min=0, max=1, default=(1.0,1.0,1.0), description="Black/White Color 2", subtype="COLOR")
- # Bright Color properties
- brightColor1 = bpy.props.FloatVectorProperty(min=0, max=1, default=(1.0, 0.0, 0.75), description="Bright Color 1", subtype="COLOR")
- brightColor2 = bpy.props.FloatVectorProperty(min=0, max=1, default=(0.0,1.0,1.0), description="Bright Color 2", subtype="COLOR")
- brightColor3 = bpy.props.FloatVectorProperty(min=0, max=1, default=(0.0,1.0,0.0), description="Bright Color 3", subtype="COLOR")
- brightColor4 = bpy.props.FloatVectorProperty(min=0, max=1, default=(1.0,1.0,0.0), description="Bright Color 4", subtype="COLOR")
- # Earth Color Properties
- earthColor1 = bpy.props.FloatVectorProperty(min=0, max=1, default=(0.068, 0.019, 0.014), description="Earth Color 1", subtype="COLOR")
- earthColor2 = bpy.props.FloatVectorProperty(min=0, max=1, default=(0.089, 0.060, 0.047), description="Earth Color 2", subtype="COLOR")
- earthColor3 = bpy.props.FloatVectorProperty(min=0, max=1, default=(0.188, 0.168, 0.066), description="Earth Color 3", subtype="COLOR")
- earthColor4 = bpy.props.FloatVectorProperty(min=0, max=1, default=(0.445, 0.296, 0.065), description="Earth Color 4", subtype="COLOR")
- earthColor5 = bpy.props.FloatVectorProperty(min=0, max=1, default=(0.745, 0.332, 0.065), description="Earth Color 5", subtype="COLOR")
- # Green to Blue Color properties
- greenblueColor1 = bpy.props.FloatVectorProperty(min=0, max=1, default=(0.296, 0.445, 0.074), description="Green/Blue Color 1", subtype="COLOR")
- greenblueColor2 = bpy.props.FloatVectorProperty(min=0, max=1, default=(0.651, 1.0, 0.223), description="Green/Blue Color 2", subtype="COLOR")
- greenblueColor3 = bpy.props.FloatVectorProperty(min=0, max=1, default=(0.037, 0.047, 0.084), description="Green/Blue Color 3", subtype="COLOR")
-
-
-############################
-## Draw Brush panel in Toolbar
-############################
-class addTracerObjectPanel(bpy.types.Panel):
- bl_label = "Btrace: Panel"
- bl_space_type = 'VIEW_3D'
- bl_region_type = 'TOOLS'
- bl_context = 'objectmode'
- selected = "tool_objectTrace"
- bl_category = 'Create'
- bl_options = {'DEFAULT_CLOSED'}
-
-
- def draw(self, context):
- layout = self.layout
- Btrace = bpy.context.window_manager.curve_tracer
- btracemenu = props = bpy.context.window_manager.btrace_menu
- obj = bpy.context.object
-
-
- ############################
- ## Color Blender Panel options
- ############################
- def color_blender():
- """Buttons for Color Blender"""
- row = box.row()
- row.label("Color palette")
- row.prop(Btrace, 'mmColors', text="")
- # Show Custom Colors if selected
- if Btrace.mmColors == 'CUSTOM':
- row = box.row(align=True)
- row.prop(Btrace, 'mmColor1', text="")
- row.prop(Btrace, 'mmColor2', text="")
- row.prop(Btrace, 'mmColor3', text="")
- row.prop(Btrace, 'mmColor4', text="")
- row.prop(Btrace, 'mmColor5', text="")
- row.prop(Btrace, 'mmColor6', text="")
- row.prop(Btrace, 'mmColor7', text="")
- row.prop(Btrace, 'mmColor8', text="")
- # Show Earth Colors
- elif Btrace.mmColors == 'BW':
- row = box.row(align=True)
- row.prop(Btrace, 'bwColor1', text="")
- row.prop(Btrace, 'bwColor2', text="")
- # Show Earth Colors
- elif Btrace.mmColors == 'BRIGHT':
- row = box.row(align=True)
- row.prop(Btrace, 'brightColor1', text="")
- row.prop(Btrace, 'brightColor2', text="")
- row.prop(Btrace, 'brightColor3', text="")
- row.prop(Btrace, 'brightColor4', text="")
- # Show Earth Colors
- elif Btrace.mmColors == 'EARTH':
- row = box.row(align=True)
- row.prop(Btrace, 'earthColor1', text="")
- row.prop(Btrace, 'earthColor2', text="")
- row.prop(Btrace, 'earthColor3', text="")
- row.prop(Btrace, 'earthColor4', text="")
- row.prop(Btrace, 'earthColor5', text="")
- # Show Earth Colors
- elif Btrace.mmColors == 'GREENBLUE':
- row = box.row(align=True)
- row.prop(Btrace, 'greenblueColor1', text="")
- row.prop(Btrace, 'greenblueColor2', text="")
- row.prop(Btrace, 'greenblueColor3', text="")
- elif Btrace.mmColors == 'RANDOM':
- row = box.row()
-
- ############################
- ## Curve Panel options
- ############################
- def curve_settings():
- """Button for curve options"""
- row = self.layout.row()
- row = box.row(align=True)
-
- row.prop(Btrace, 'show_curve_settings', icon='CURVE_BEZCURVE', text="Curve Settings")
- row.prop(Btrace, 'material_settings', icon='MATERIAL_DATA', text="Material Settings")
- if Btrace.material_settings:
- row = box.row()
- row.label(text="Material Settings", icon='COLOR')
- row = box.row()
- row.prop(Btrace, "trace_mat_random")
- if not Btrace.trace_mat_random:
- row = box.row()
- row.prop(Btrace, "trace_mat_color", text="")
- else:
- row.prop(Btrace, "mat_run_color_blender")
- if Btrace.mat_run_color_blender:
- row = box.row()
- row.operator("object.colorblenderclear", text="Reset Material Keyframes", icon="KEY_DEHLT")
- row.prop(Btrace, 'mmSkip', text="Keyframe every")
-
- color_blender()
- row = box.row()
- if Btrace.show_curve_settings:
- #if or btracemenu.tool_handwrite:
- if len(bpy.context.selected_objects) > 0 and obj.type == 'CURVE': # selected curve options
- col = box.column(align=True)
- col.label(text="Edit Curves for", icon='CURVE_BEZCURVE')
- col.label(text="Selected Curve Bevel Options")
- row = col.row(align=True)
- row.prop(obj.data, 'bevel_depth', text="Depth")
- row.prop(obj.data, 'bevel_resolution', text="Resolution")
- row = col.row(align=True)
- row.prop(obj.data, 'resolution_u')
- else: # For new curve
- box.label(text="New Curve Settings", icon='CURVE_BEZCURVE')
- box.prop(Btrace, "curve_spline")
- box.prop(Btrace, "curve_handle")
- box.label(text="Bevel Options")
- col = box.column(align=True)
- row = col.row(align=True)
- row.prop(Btrace, "curve_depth", text="Depth")
- row.prop(Btrace, "curve_resolution", text="Resolution")
- row = col.row(align=True)
- row.prop(Btrace, "curve_u")
-
- ############################
- ## Grow Animation Panel options
- ############################
- def add_grow():
- """Button for grow animation option"""
- row = box.row()
- row.label(text="Animate Final Curve")
- row = box.row()
- row.prop(Btrace, "animate", text="Add Grow Curve Animation", icon="META_BALL")
- row.label("")
- if Btrace.animate:
- box.label(text='Frame Animation Settings:', icon="META_BALL")
- col = box.column(align=True)
- col.prop(Btrace, 'anim_auto')
- if not Btrace.anim_auto:
- row = col.row(align=True)
- row.prop(Btrace, 'anim_f_start')
- row.prop(Btrace, 'anim_length')
- row = col.row(align=True)
- row.prop(Btrace, 'anim_delay')
- row.prop(Btrace, 'anim_f_fade')
-
- box.label(text='Additional Settings')
- row = box.row()
- row.prop(Btrace, 'anim_tails')
- row.prop(Btrace, 'anim_keepr')
-
- ##################################################################
- ## Start Btrace Panel
- ##################################################################
- col = self.layout.column(align=True)
- #col.label(text="Trace Tools")
- row = col.row()
- row.prop(btracemenu, "tool_objectTrace", text="Ojbect Trace", icon="FORCE_MAGNETIC")
- row.prop(btracemenu, "tool_objectsConnect", text="Object Connect", icon="OUTLINER_OB_EMPTY")
- row = col.row()
- row.prop(btracemenu, "tool_meshFollow", text="Mesh Follow", icon="DRIVER")
- row.prop(btracemenu, "tool_handwrite", text="Handwriting", icon='BRUSH_DATA')
- row = col.row()
- row.prop(btracemenu, "tool_particleTrace", icon="PARTICLES", text="Particle Trace")
- row.prop(btracemenu, "tool_particleConnect", icon="MOD_PARTICLES", text="Particle Connect")
- row = layout.row()
- col = layout.column(align=True)
- row = col.row()
- row.prop(btracemenu, "tool_growCurve", icon="META_BALL", text="Grow Animation")
- row.prop(btracemenu, "tool_fcurve", text="Fcurve Noise", icon='RNDCURVE')
- row = col.row()
- row.prop(btracemenu, "tool_colorblender", text="Color Blender", icon="COLOR")
- row.label(text="")
- row = layout.row()
-
- ##########################
- ## Start Object Tools
- ##########################
- sel = bpy.context.selected_objects
- ############################
- ### Object Trace
- ############################
- if btracemenu.tool_objectTrace:
- row = layout.row()
- row.label(text=" Trace Tool:", icon="FORCE_CURVE")
- box = self.layout.box()
- row = box.row()
- row.label(text="Object Trace", icon="FORCE_MAGNETIC")
- row.operator("object.btobjecttrace", text="Run!", icon="PLAY")
- row = box.row()
- row.prop(Btrace, "settings_toggle", icon='MODIFIER', text='Settings')
- myselected = "Selected %d" % len(bpy.context.selected_objects)
- row.label(text=myselected)
- if Btrace.settings_toggle:
- row = box.row()
- row.label(text='Edge Draw Method')
- row = box.row(align=True)
- row.prop(Btrace, 'convert_edgetype')
- box.prop(Btrace, "object_duplicate")
- if len(sel) > 1:
- box.prop(Btrace, 'convert_joinbefore')
- else:
- Btrace.convert_joinbefore = False
- row = box.row()
- row.prop(Btrace, "distort_curve")
- if Btrace.distort_curve:
- col = box.column(align=True)
- col.prop(Btrace, "distort_modscale")
- col.prop(Btrace, "distort_noise")
- row = box.row()
- curve_settings() # Show Curve/material settings
- add_grow() # Grow settings here
-
- ############################
- ### Objects Connect
- ############################
- if btracemenu.tool_objectsConnect:
- row = layout.row()
- row.label(text=" Trace Tool:", icon="FORCE_CURVE")
- box = self.layout.box()
- row = box.row()
- row.label(text="Objects Connect", icon="OUTLINER_OB_EMPTY")
- row.operator("object.btobjectsconnect", text="Run!", icon="PLAY")
- row = box.row()
- row.prop(Btrace, "settings_toggle", icon='MODIFIER', text='Settings')
- row.label(text="")
- if Btrace.settings_toggle:
- row = box.row()
- row.prop(Btrace, "respect_order", text="Selection Options")
- if Btrace.respect_order:
- box.operator("object.select_order", text="Click to start order selection", icon='UV_SYNC_SELECT')
- row = box.row()
- row.prop(Btrace, "connect_noise", text="Add F-Curve Noise")
- if Btrace.connect_noise:
- row = box.row()
- row.label(text="F-Curve Noise", icon='RNDCURVE')
- row = box.row(align=True)
- row.prop(Btrace, "fcnoise_rot")
- row.prop(Btrace, "fcnoise_loc")
- row.prop(Btrace, "fcnoise_scale")
- col = box.column(align=True)
- col.prop(Btrace, "fcnoise_amp")
- col.prop(Btrace, "fcnoise_timescale")
- box.prop(Btrace, "fcnoise_key")
- curve_settings() # Show Curve/material settings
- add_grow() # Grow settings here
-
- ############################
- ### Mesh Follow
- ############################
- if btracemenu.tool_meshFollow:
- row = layout.row()
- row.label(text=" Trace Tool:", icon="FORCE_CURVE")
- box = self.layout.box()
- row = box.row()
- row.label(text="Mesh Follow", icon="DRIVER")
- row.operator("object.btmeshfollow", text="Run!", icon="PLAY")
- row = box.row()
- if Btrace.fol_mesh_type == 'OBJECT':
- a, b = "Trace Object", "SNAP_VOLUME"
- if Btrace.fol_mesh_type == 'VERTS':
- a, b = "Trace Verts", "SNAP_VERTEX"
- if Btrace.fol_mesh_type == 'EDGES':
- a, b = "Trace Edges", "SNAP_EDGE"
- if Btrace.fol_mesh_type == 'FACES':
- a, b = "Trace Faces", "SNAP_FACE"
- row.prop(Btrace, "settings_toggle", icon='MODIFIER', text='Settings')
- row.label(text=a, icon=b)
- if Btrace.settings_toggle:
- col = box.column(align=True)
- row = col.row(align=True)
- row.prop(Btrace, "fol_mesh_type", expand=True)
- row = col.row(align=True)
- if Btrace.fol_mesh_type != 'OBJECT':
- row.prop(Btrace, "fol_sel_option", expand=True)
- row = box.row()
- if Btrace.fol_sel_option == 'RANDOM':
- row.label("Random Select of Total")
- row.prop(Btrace, "fol_perc_verts", text="%")
- if Btrace.fol_sel_option == 'CUSTOM':
- row.label("Choose selection in Edit Mode")
- if Btrace.fol_sel_option == 'ALL':
- row.label("Select All items")
- col = box.column(align=True)
- col.label("Time Options", icon="TIME")
- col.prop(Btrace, "particle_step")
- row = col.row(align=True)
- row.prop(Btrace, "fol_start_frame")
- row.prop(Btrace, "fol_end_frame")
- curve_settings() # Show Curve/material settings
- add_grow() # Grow settings here
-
- ############################
- ### Handwriting Tools
- ############################
- if btracemenu.tool_handwrite:
- row = layout.row()
- row.label(text=" Trace Tool:", icon="FORCE_CURVE")
- box = self.layout.box()
- row = box.row()
- row.label(text='Handwriting', icon='BRUSH_DATA')
- row.operator("curve.btwriting", text="Run!", icon='PLAY')
- row = box.row()
- row = box.row()
- row.label(text='Grease Pencil Writing Tools')
- col = box.column(align=True)
- row = col.row(align=True)
- row.operator("gpencil.draw", text="Draw", icon='BRUSH_DATA').mode = 'DRAW'
- row.operator("gpencil.draw", text="Poly", icon='VPAINT_HLT').mode = 'DRAW_POLY'
- row = col.row(align=True)
- row.operator("gpencil.draw", text="Line", icon='ZOOMOUT').mode = 'DRAW_STRAIGHT'
- row.operator("gpencil.draw", text="Erase", icon='TPAINT_HLT').mode = 'ERASER'
- row = box.row()
- row.operator("gpencil.data_unlink", text="Delete Grease Pencil Layer", icon="CANCEL")
- row = box.row()
- curve_settings() # Show Curve/material settings
- add_grow() # Grow settings here
-
- ############################
- ### Particle Trace
- ############################
- if btracemenu.tool_particleTrace:
- row = layout.row()
- row.label(text=" Trace Tool:", icon="FORCE_CURVE")
- box = self.layout.box()
- row = box.row()
- row.label(text="Particle Trace", icon="PARTICLES")
- row.operator("particles.particletrace", text="Run!", icon="PLAY")
- row = box.row()
- row.prop(Btrace, "settings_toggle", icon='MODIFIER', text='Settings')
- row.label(text="")
- if Btrace.settings_toggle:
- box.prop(Btrace, "particle_step")
- row = box.row()
- row.prop(Btrace, "curve_join")
- curve_settings() # Show Curve/material settings
- add_grow() # Grow settings here
-
- ############################
- ### Connect Particles
- ############################
- if btracemenu.tool_particleConnect:
- row = layout.row()
- row.label(text=" Trace Tool:", icon="FORCE_CURVE")
- box = self.layout.box()
- row = box.row()
- row.label(text='Particle Connect', icon='MOD_PARTICLES')
- row.operator("particles.connect", icon="PLAY", text='Run!')
- row = box.row()
- row.prop(Btrace, "settings_toggle", icon='MODIFIER', text='Settings')
- row.label(text="")
- if Btrace.settings_toggle:
- box.prop(Btrace, "particle_step")
- row = box.row()
- row.prop(Btrace, 'particle_auto')
- if not Btrace.particle_auto:
- row = box.row(align=True)
- row.prop(Btrace, 'particle_f_start')
- row.prop(Btrace, 'particle_f_end')
- curve_settings() # Show Curve/material settings
- add_grow() # Grow settings here
-
- #######################
- #### Grow Animation ####
- #######################
- if btracemenu.tool_growCurve:
- row = layout.row()
- row.label(text=" Curve Tool:", icon="OUTLINER_OB_CURVE")
- box = self.layout.box()
- row = box.row()
- row.label(text="Grow Curve", icon="META_BALL")
- row.operator('curve.btgrow', text='Run!', icon='PLAY')
- row = box.row()
- row.prop(Btrace, "settings_toggle", icon='MODIFIER', text='Settings')
- row.operator('object.btreset', icon='KEY_DEHLT')
- if Btrace.settings_toggle:
- box.label(text='Frame Animation Settings:')
- col = box.column(align=True)
- col.prop(Btrace, 'anim_auto')
- if not Btrace.anim_auto:
- row = col.row(align=True)
- row.prop(Btrace, 'anim_f_start')
- row.prop(Btrace, 'anim_length')
- row = col.row(align=True)
- row.prop(Btrace, 'anim_delay')
- row.prop(Btrace, 'anim_f_fade')
-
- box.label(text='Additional Settings')
- row = box.row()
- row.prop(Btrace, 'anim_tails')
- row.prop(Btrace, 'anim_keepr')
-
- #######################
- #### F-Curve Noise Curve ####
- #######################
- if btracemenu.tool_fcurve:
- row = layout.row()
- row.label(text=" Curve Tool:", icon="OUTLINER_OB_CURVE")
- box = self.layout.box()
- row = box.row()
- row.label(text="F-Curve Noise", icon='RNDCURVE')
- row.operator("object.btfcnoise", icon='PLAY', text="Run!")
- row = box.row()
- row.prop(Btrace, "settings_toggle", icon='MODIFIER', text='Settings')
- row.operator('object.btreset', icon='KEY_DEHLT')
- if Btrace.settings_toggle:
- row = box.row(align=True)
- row.prop(Btrace, "fcnoise_rot")
- row.prop(Btrace, "fcnoise_loc")
- row.prop(Btrace, "fcnoise_scale")
- col = box.column(align=True)
- col.prop(Btrace, "fcnoise_amp")
- col.prop(Btrace, "fcnoise_timescale")
- box.prop(Btrace, "fcnoise_key")
-
- #######################
- #### Color Blender ####
- #######################
- if btracemenu.tool_colorblender:
- row = layout.row()
- row.label(text=" Curve/Object Tool:", icon="OUTLINER_OB_CURVE")
- box = self.layout.box()
- row = box.row()
- row.label(text="Color Blender", icon="COLOR")
- row.operator("object.colorblender", icon='PLAY', text="Run!")
- row = box.row()
- row.operator("object.colorblenderclear", text="Reset Keyframes", icon="KEY_DEHLT")
- row.prop(Btrace, 'mmSkip', text="Keyframe every")
- color_blender()
-
-###### END PANEL ##############
-###############################
-
-
-################## ################## ################## ############
-## Object Trace
-## creates a curve with a modulated radius connecting points of a mesh
-################## ################## ################## ############
-
-class OBJECT_OT_objecttrace(bpy.types.Operator):
+class OBJECT_OT_objecttrace(Operator):
bl_idname = "object.btobjecttrace"
bl_label = "Btrace: Object Trace"
- bl_description = "Trace selected mesh object with a curve with the option to animate"
+ bl_description = ("Trace selected mesh object with a curve with the option to animate\n"
+ "The Active Object has to be of a Mesh or Font type")
bl_options = {'REGISTER', 'UNDO'}
-
@classmethod
def poll(cls, context):
- return (context.object and context.object.type in {'MESH', 'FONT'})
+ return (context.object and
+ context.object.type in {'MESH', 'FONT'})
def invoke(self, context, event):
- import bpy
-
- # Run through each selected object and convert to to a curved object
- brushObj = bpy.context.selected_objects
- Btrace = bpy.context.window_manager.curve_tracer
- # Duplicate Mesh
- if Btrace.object_duplicate:
- bpy.ops.object.duplicate_move()
- brushObj = bpy.context.selected_objects
- # Join Mesh
- if Btrace.convert_joinbefore:
- if len(brushObj) > 1: # Only run if multiple objects selected
- bpy.ops.object.join()
- brushObj = bpy.context.selected_objects
-
- for i in brushObj:
- bpy.context.scene.objects.active = i
- if i and i.type != 'CURVE':
- bpy.ops.object.btconvertcurve()
- addtracemat(bpy.context.object.data)
- if Btrace.animate:
- bpy.ops.curve.btgrow()
- return {'FINISHED'}
-
-
-################## ################## ################## ############
-## Objects Connect
-## connect selected objects with a curve + hooks to each node
-## possible handle types: 'FREE' 'AUTO' 'VECTOR' 'ALIGNED'
-################## ################## ################## ############
-
-class OBJECT_OT_objectconnect(bpy.types.Operator):
+ try:
+ # Run through each selected object and convert to to a curved object
+ brushObj = context.selected_objects
+ Btrace = context.window_manager.curve_tracer
+ check_materials = True
+ # Duplicate Mesh
+ if Btrace.object_duplicate:
+ bpy.ops.object.duplicate_move()
+ brushObj = context.selected_objects
+ # Join Mesh
+ if Btrace.convert_joinbefore:
+ if len(brushObj) > 1: # Only run if multiple objects selected
+ bpy.ops.object.join()
+ brushObj = context.selected_objects
+
+ for i in brushObj:
+ context.scene.objects.active = i
+ if i and i.type != 'CURVE':
+ bpy.ops.object.btconvertcurve()
+ # Materials
+ trace_mats = addtracemat(bpy.context.object.data)
+ if not trace_mats and check_materials is True:
+ check_materials = False
+ if Btrace.animate:
+ bpy.ops.curve.btgrow()
+
+ if check_materials is False:
+ self.report({'WARNING'}, "Some Materials could not be added")
+
+ return {'FINISHED'}
+
+ except Exception as e:
+ error_handlers(self, "object.btobjecttrace", e,
+ "Object Trace could not be completed")
+
+ return {'CANCELLED'}
+
+
+# Objects Connect
+# connect selected objects with a curve + hooks to each node
+# possible handle types: 'FREE' 'AUTO' 'VECTOR' 'ALIGNED'
+
+class OBJECT_OT_objectconnect(Operator):
bl_idname = "object.btobjectsconnect"
bl_label = "Btrace: Objects Connect"
- bl_description = "Connect selected objects with a curve and add hooks to each node"
+ bl_description = ("Connect selected objects with a curve and add hooks to each node\n"
+ "Needs at least two objects selected")
bl_options = {'REGISTER', 'UNDO'}
@classmethod
def poll(cls, context):
- return len(bpy.context.selected_objects) > 1
+ return len(context.selected_objects) > 1
def invoke(self, context, event):
- import bpy, selection_utils
- list = []
- Btrace = bpy.context.window_manager.curve_tracer
- curve_handle = Btrace.curve_handle
- if curve_handle == 'AUTOMATIC': # hackish because of naming conflict in api
- curve_handle = 'AUTO'
- # Check if Btrace group exists, if not create
- bgroup = bpy.data.groups.keys()
- if 'Btrace' not in bgroup:
- bpy.ops.group.create(name="Btrace")
- # check if noise
- if Btrace.connect_noise:
- bpy.ops.object.btfcnoise()
- # check if respect order is checked, create list of objects
- if Btrace.respect_order == True:
- selobnames = selection_utils.selected
- obnames = []
- for ob in selobnames:
- obnames.append(bpy.data.objects[ob])
- else:
- obnames = bpy.context.selected_objects # No selection order
-
- for a in obnames:
- list.append(a)
- a.select = False
-
- # trace the origins
- tracer = bpy.data.curves.new('tracer', 'CURVE')
- tracer.dimensions = '3D'
- spline = tracer.splines.new('BEZIER')
- spline.bezier_points.add(len(list) - 1)
- curve = bpy.data.objects.new('curve', tracer)
- bpy.context.scene.objects.link(curve)
-
- # render ready curve
- tracer.resolution_u = Btrace.curve_u
- tracer.bevel_resolution = Btrace.curve_resolution # Set bevel resolution from Panel options
- tracer.fill_mode = 'FULL'
- tracer.bevel_depth = Btrace.curve_depth # Set bevel depth from Panel options
-
- # move nodes to objects
- for i in range(len(list)):
- p = spline.bezier_points[i]
- p.co = list[i].location
- p.handle_right_type = curve_handle
- p.handle_left_type = curve_handle
-
- bpy.context.scene.objects.active = curve
- bpy.ops.object.mode_set(mode='OBJECT')
-
- # place hooks
- for i in range(len(list)):
- list[i].select = True
- curve.data.splines[0].bezier_points[i].select_control_point = True
- bpy.ops.object.mode_set(mode='EDIT')
- bpy.ops.object.hook_add_selob()
+ try:
+ lists = []
+ Btrace = context.window_manager.curve_tracer
+ curve_handle = Btrace.curve_handle
+ if curve_handle == 'AUTOMATIC': # hackish because of naming conflict in api
+ curve_handle = 'AUTO'
+ # Check if Btrace group exists, if not create
+ bgroup = bpy.data.groups.keys()
+ if 'Btrace' not in bgroup:
+ bpy.ops.group.create(name="Btrace")
+ # check if noise
+ if Btrace.connect_noise:
+ bpy.ops.object.btfcnoise()
+ # check if respect order is checked, create list of objects
+ if Btrace.respect_order is True:
+ selobnames = selection_utils.selected
+ obnames = []
+ for ob in selobnames:
+ obnames.append(bpy.data.objects[ob])
+ else:
+ obnames = bpy.context.selected_objects # No selection order
+
+ for a in obnames:
+ lists.append(a)
+ a.select = False
+
+ # trace the origins
+ tracer = bpy.data.curves.new('tracer', 'CURVE')
+ tracer.dimensions = '3D'
+ spline = tracer.splines.new('BEZIER')
+ spline.bezier_points.add(len(lists) - 1)
+ curve = bpy.data.objects.new('curve', tracer)
+ bpy.context.scene.objects.link(curve)
+
+ # render ready curve
+ tracer.resolution_u = Btrace.curve_u
+ # Set bevel resolution from Panel options
+ tracer.bevel_resolution = Btrace.curve_resolution
+ tracer.fill_mode = 'FULL'
+ # Set bevel depth from Panel options
+ tracer.bevel_depth = Btrace.curve_depth
+
+ # move nodes to objects
+ for i in range(len(lists)):
+ p = spline.bezier_points[i]
+ p.co = lists[i].location
+ p.handle_right_type = curve_handle
+ p.handle_left_type = curve_handle
+
+ bpy.context.scene.objects.active = curve
bpy.ops.object.mode_set(mode='OBJECT')
- curve.data.splines[0].bezier_points[i].select_control_point = False
- list[i].select = False
-
- bpy.ops.object.select_all(action='DESELECT')
- curve.select = True # selected curve after it's created
- addtracemat(bpy.context.object.data) # Add material
- if Btrace.animate: # Add Curve Grow it?
- bpy.ops.curve.btgrow()
- bpy.ops.object.group_link(group="Btrace") # add to Btrace group
- if Btrace.animate:
- bpy.ops.curve.btgrow() # Add grow curve
- return {'FINISHED'}
-
-
-################## ################## ################## ############
-## Particle Trace
-## creates a curve from each particle of a system
-################## ################## ################## ############
-def curvetracer(curvename, splinename):
+
+ # place hooks
+ for i in range(len(lists)):
+ lists[i].select = True
+ curve.data.splines[0].bezier_points[i].select_control_point = True
+ bpy.ops.object.mode_set(mode='EDIT')
+ bpy.ops.object.hook_add_selob()
+ bpy.ops.object.mode_set(mode='OBJECT')
+ curve.data.splines[0].bezier_points[i].select_control_point = False
+ lists[i].select = False
+
+ bpy.ops.object.select_all(action='DESELECT')
+ curve.select = True # selected curve after it's created
+ # Materials
+ check_materials = True
+ trace_mats = addtracemat(bpy.context.object.data)
+ if not trace_mats and check_materials is True:
+ check_materials = False
+
+ if Btrace.animate: # Add Curve Grow it?
+ bpy.ops.curve.btgrow()
+
+ bpy.ops.object.group_link(group="Btrace") # add to Btrace group
+ if Btrace.animate:
+ bpy.ops.curve.btgrow() # Add grow curve
+
+ if check_materials is False:
+ self.report({'WARNING'}, "Some Materials could not be added")
+
+ return {'FINISHED'}
+
+ except Exception as e:
+ error_handlers(self, "object.btobjectsconnect", e,
+ "Objects Connect could not be completed")
+
+ return {'CANCELLED'}
+
+
+# Particle Trace
+# creates a curve from each particle of a system
+
+def curvetracer(curvename, splinename):
Btrace = bpy.context.window_manager.curve_tracer
tracer = bpy.data.curves.new(splinename, 'CURVE')
tracer.dimensions = '3D'
@@ -757,762 +213,940 @@ def curvetracer(curvename, splinename):
tracer.bevel_resolution = Btrace.curve_resolution
tracer.bevel_depth = Btrace.curve_depth
tracer.resolution_u = Btrace.curve_u
+
return tracer, curve
-class OBJECT_OT_particletrace(bpy.types.Operator):
+class OBJECT_OT_particletrace(Operator):
bl_idname = "particles.particletrace"
bl_label = "Btrace: Particle Trace"
- bl_description = "Creates a curve from each particle of a system. Keeping particle amount under 250 will make this run faster"
+ bl_description = ("Creates a curve from each particle of a system.\n"
+ "Keeping particle amount under 250 will make this run faster")
bl_options = {'REGISTER', 'UNDO'}
@classmethod
def poll(cls, context):
- return (bpy.context.object and bpy.context.object.particle_systems)
+ return (context.object is not None and
+ context.object.particle_systems)
def execute(self, context):
- Btrace = bpy.context.window_manager.curve_tracer
- particle_step = Btrace.particle_step # step size in frames
- obj = bpy.context.object
- ps = obj.particle_systems.active
- curvelist = []
- curve_handle = Btrace.curve_handle
- if curve_handle == 'AUTOMATIC': # hackish naming conflict
- curve_handle = 'AUTO'
- if curve_handle == 'FREE_ALIGN': # hackish naming conflict
- curve_handle = 'FREE'
-
- # Check if Btrace group exists, if not create
- bgroup = bpy.data.groups.keys()
- if 'Btrace' not in bgroup:
- bpy.ops.group.create(name="Btrace")
-
- if Btrace.curve_join:
- tracer = curvetracer('Tracer', 'Splines')
- for x in ps.particles:
- if not Btrace.curve_join:
- tracer = curvetracer('Tracer.000', 'Spline.000')
- spline = tracer[0].splines.new('BEZIER')
- spline.bezier_points.add((x.lifetime - 1) // particle_step) # add point to spline based on step size
- for t in list(range(int(x.lifetime))):
- bpy.context.scene.frame_set(t + x.birth_time)
- if not t % particle_step:
- p = spline.bezier_points[t // particle_step]
- p.co = x.location
- p.handle_right_type = curve_handle
- p.handle_left_type = curve_handle
- particlecurve = tracer[1]
- curvelist.append(particlecurve)
- # add to group
- bpy.ops.object.select_all(action='DESELECT')
- for curveobject in curvelist:
- curveobject.select = True
- bpy.context.scene.objects.active = curveobject
- bpy.ops.object.group_link(group="Btrace")
- addtracemat(curveobject.data) # Add material
-
- if Btrace.animate:
- bpy.ops.curve.btgrow() # Add grow curve
-
- return {'FINISHED'}
-
-
-###########################################################################
-## Particle Connect
-## connect all particles in active system with a continuous animated curve
-###########################################################################
-
-class OBJECT_OT_traceallparticles(bpy.types.Operator):
- bl_idname = 'particles.connect'
- bl_label = 'Connect Particles'
- bl_description = 'Create a continuous animated curve from particles in active system'
+ try:
+ Btrace = context.window_manager.curve_tracer
+ particle_step = Btrace.particle_step # step size in frames
+ obj = bpy.context.object
+ ps = obj.particle_systems.active
+ curvelist = []
+ curve_handle = Btrace.curve_handle
+ check_materials = True
+
+ if curve_handle == 'AUTOMATIC': # hackish naming conflict
+ curve_handle = 'AUTO'
+ if curve_handle == 'FREE_ALIGN': # hackish naming conflict
+ curve_handle = 'FREE'
+
+ # Check if Btrace group exists, if not create
+ bgroup = bpy.data.groups.keys()
+ if 'Btrace' not in bgroup:
+ bpy.ops.group.create(name="Btrace")
+
+ if Btrace.curve_join:
+ tracer = curvetracer('Tracer', 'Splines')
+ for x in ps.particles:
+ if not Btrace.curve_join:
+ tracer = curvetracer('Tracer.000', 'Spline.000')
+ spline = tracer[0].splines.new('BEZIER')
+ # add point to spline based on step size
+ spline.bezier_points.add((x.lifetime - 1) // particle_step)
+ for t in list(range(int(x.lifetime))):
+ bpy.context.scene.frame_set(t + x.birth_time)
+ if not t % particle_step:
+ p = spline.bezier_points[t // particle_step]
+ p.co = x.location
+ p.handle_right_type = curve_handle
+ p.handle_left_type = curve_handle
+ particlecurve = tracer[1]
+ curvelist.append(particlecurve)
+ # add to group
+ bpy.ops.object.select_all(action='DESELECT')
+ for curveobject in curvelist:
+ curveobject.select = True
+ bpy.context.scene.objects.active = curveobject
+ bpy.ops.object.group_link(group="Btrace")
+ # Materials
+ trace_mats = addtracemat(curveobject.data)
+ if not trace_mats and check_materials is True:
+ check_materials = False
+
+ if Btrace.animate:
+ bpy.ops.curve.btgrow() # Add grow curve
+
+ if check_materials is False:
+ self.report({'WARNING'}, "Some Materials could not be added")
+
+ return {'FINISHED'}
+
+ except Exception as e:
+ error_handlers(self, "particles.particletrace", e,
+ "Particle Trace could not be completed")
+
+ return {'CANCELLED'}
+
+
+# Particle Connect
+# connect all particles in active system with a continuous animated curve
+
+class OBJECT_OT_traceallparticles(Operator):
+ bl_idname = "particles.connect"
+ bl_label = "Connect Particles"
+ bl_description = ("Create a continuous animated curve from particles in active system\n"
+ "Needs an Object with a particle system attached")
bl_options = {'REGISTER', 'UNDO'}
@classmethod
def poll(cls, context):
- return (bpy.context.object and bpy.context.object.particle_systems)
+ return (context.object is not None and
+ context.object.particle_systems)
def execute(self, context):
+ try:
+ obj = context.object
+ ps = obj.particle_systems.active
+ setting = ps.settings
+
+ # Grids distribution not supported
+ if setting.distribution == 'GRID':
+ self.report({'INFO'},
+ "Grid distribution mode for particles not supported")
+ return{'CANCELLED'}
+
+ Btrace = context.window_manager.curve_tracer
+ # Get frame start
+ particle_f_start = Btrace.particle_f_start
+ # Get frame end
+ particle_f_end = Btrace.particle_f_end
+ curve_handle = Btrace.curve_handle
+ # hackish because of naming conflict in api
+ if curve_handle == 'AUTOMATIC':
+ curve_handle = 'AUTO'
+ if curve_handle == 'FREE_ALIGN':
+ curve_handle = 'FREE'
+
+ # define what kind of object to create
+ tracer = bpy.data.curves.new('Splines', 'CURVE')
+ # Create new object with settings listed above
+ curve = bpy.data.objects.new('Tracer', tracer)
+ # Link newly created object to the scene
+ bpy.context.scene.objects.link(curve)
+ # add a new Bezier point in the new curve
+ spline = tracer.splines.new('BEZIER')
+ spline.bezier_points.add(setting.count - 1)
- obj = bpy.context.object
- ps = obj.particle_systems.active
- set = ps.settings
+ tracer.dimensions = '3D'
+ tracer.resolution_u = Btrace.curve_u
+ tracer.bevel_resolution = Btrace.curve_resolution
+ tracer.fill_mode = 'FULL'
+ tracer.bevel_depth = Btrace.curve_depth
+
+ if Btrace.particle_auto:
+ f_start = int(setting.frame_start)
+ f_end = int(setting.frame_end + setting.lifetime)
+ else:
+ if particle_f_end <= particle_f_start:
+ particle_f_end = particle_f_start + 1
+ f_start = particle_f_start
+ f_end = particle_f_end
+
+ for bFrames in range(f_start, f_end):
+ bpy.context.scene.frame_set(bFrames)
+ if not (bFrames - f_start) % Btrace.particle_step:
+ for bFrames in range(setting.count):
+ if ps.particles[bFrames].alive_state != 'UNBORN':
+ e = bFrames
+ bp = spline.bezier_points[bFrames]
+ pt = ps.particles[e]
+ bp.co = pt.location
+ bp.handle_right_type = curve_handle
+ bp.handle_left_type = curve_handle
+ bp.keyframe_insert('co')
+ bp.keyframe_insert('handle_left')
+ bp.keyframe_insert('handle_right')
+ # Select new curve
+ bpy.ops.object.select_all(action='DESELECT')
+ curve.select = True
+ bpy.context.scene.objects.active = curve
+
+ # Materials
+ trace_mats = addtracemat(curve.data)
+ if not trace_mats:
+ self.report({'WARNING'}, "Some Materials could not be added")
+
+ if Btrace.animate:
+ bpy.ops.curve.btgrow()
- # Grids distribution not supported
- if set.distribution == 'GRID':
- self.report({'INFO'},"Grid distribution mode for particles not supported.")
return{'FINISHED'}
- Btrace = bpy.context.window_manager.curve_tracer
- particle_f_start = Btrace.particle_f_start # Get frame start
- particle_f_end = Btrace.particle_f_end # Get frame end
- curve_handle = Btrace.curve_handle
- if curve_handle == 'AUTOMATIC': # hackish because of naming conflict in api
- curve_handle = 'AUTO'
- if curve_handle == 'FREE_ALIGN':
- curve_handle = 'FREE'
- tracer = bpy.data.curves.new('Splines','CURVE') # define what kind of object to create
- curve = bpy.data.objects.new('Tracer',tracer) # Create new object with settings listed above
- bpy.context.scene.objects.link(curve) # Link newly created object to the scene
- spline = tracer.splines.new('BEZIER') # add a new Bezier point in the new curve
- spline.bezier_points.add(set.count-1)
-
- tracer.dimensions = '3D'
- tracer.resolution_u = Btrace.curve_u
- tracer.bevel_resolution = Btrace.curve_resolution
- tracer.fill_mode = 'FULL'
- tracer.bevel_depth = Btrace.curve_depth
-
- if Btrace.particle_auto:
- f_start = int(set.frame_start)
- f_end = int(set.frame_end + set.lifetime)
- else:
- if particle_f_end <= particle_f_start:
- particle_f_end = particle_f_start + 1
- f_start = particle_f_start
- f_end = particle_f_end
-
- for bFrames in range(f_start, f_end):
- bpy.context.scene.frame_set(bFrames)
- if not (bFrames-f_start) % Btrace.particle_step:
- for bFrames in range(set.count):
- if ps.particles[bFrames].alive_state != 'UNBORN':
- e = bFrames
- bp = spline.bezier_points[bFrames]
- pt = ps.particles[e]
- bp.co = pt.location
- #bp.handle_left = pt.location
- #bp.handle_right = pt.location
- bp.handle_right_type = curve_handle
- bp.handle_left_type = curve_handle
- bp.keyframe_insert('co')
- bp.keyframe_insert('handle_left')
- bp.keyframe_insert('handle_right')
- # Select new curve
- bpy.ops.object.select_all(action='DESELECT')
- curve.select = True
- bpy.context.scene.objects.active = curve
- addtracemat(curve.data) #Add material
- if Btrace.animate:
- bpy.ops.curve.btgrow()
- return{'FINISHED'}
-
-################## ################## ################## ############
-## Writing Tool
-## Writes a curve by animating its point's radii
-##
-################## ################## ################## ############
-class OBJECT_OT_writing(bpy.types.Operator):
- bl_idname = 'curve.btwriting'
- bl_label = 'Write'
- bl_description = 'Use Grease Pencil to write and convert to curves'
+ except Exception as e:
+ error_handlers(self, "particles.connect", e,
+ "Connect Particles could not be completed")
+
+ return {'CANCELLED'}
+
+
+# Writing Tool
+# Writes a curve by animating its point's radii
+
+class OBJECT_OT_writing(Operator):
+ bl_idname = "curve.btwriting"
+ bl_label = "Write"
+ bl_description = ("Use Grease Pencil to write and convert to curves\n"
+ "Needs an existing Grease Pencil layer attached to the Scene")
bl_options = {'REGISTER', 'UNDO'}
- # @classmethod ### Removed so panel still draws if nothing is selected
- # def poll(cls, context):
- # return (context.scene.grease_pencil or context.object.grease_pencil != None)
+ @classmethod
+ def poll(cls, context):
+ gp = context.scene.grease_pencil
+ return gp and gp.layers
def execute(self, context):
- Btrace = bpy.context.window_manager.curve_tracer
- obj = bpy.context.object
- gactive = bpy.context.active_object # set selected object before convert
- bpy.ops.gpencil.convert(type='CURVE')
- gactiveCurve = bpy.context.active_object # get curve after convert
- # render ready curve
- gactiveCurve.data.resolution_u = Btrace.curve_u
- gactiveCurve.data.bevel_resolution = Btrace.curve_resolution # Set bevel resolution from Panel options
- gactiveCurve.data.fill_mode = 'FULL'
- gactiveCurve.data.bevel_depth = Btrace.curve_depth # Set bevel depth from Panel options
-
- writeObj = bpy.context.selected_objects
- if Btrace.animate:
- for i in writeObj:
- bpy.context.scene.objects.active = i
- bpy.ops.curve.btgrow()
- addtracemat(bpy.context.object.data) #Add material
- else:
- for i in writeObj:
- bpy.context.scene.objects.active = i
- addtracemat(bpy.context.object.data) #Add material
-
- # Delete grease pencil strokes
- bpy.context.scene.objects.active = gactive
- bpy.ops.gpencil.data_unlink()
- bpy.context.scene.objects.active = gactiveCurve
- # Smooth object
- bpy.ops.object.shade_smooth()
- # Return to first frame
- bpy.context.scene.frame_set(Btrace.anim_f_start)
-
- return{'FINISHED'}
-
-################## ################## ################## ############
-## Create Curve
-## Convert mesh to curve using either Continuous, All Edges, or Sharp Edges
-## Option to create noise
-################## ################## ################## ############
-
-class OBJECT_OT_convertcurve(bpy.types.Operator):
+ try:
+ # first check if the Grease Pencil is attached to the Scene
+ tool_settings = context.scene.tool_settings
+ source_data = tool_settings.grease_pencil_source
+ if source_data in {"OBJECT"}:
+ self.report({'WARNING'},
+ "Operation Cancelled. "
+ "The Grease Pencil data-block is attached to an Object")
+ return {"CANCELLED"}
+
+ Btrace = context.window_manager.curve_tracer
+ # this is hacky - store objects in the scene for comparison later
+ store_objects = [ob for ob in context.scene.objects]
+
+ gactive = context.active_object
+ # checking if there are any strokes the easy way
+ if not bpy.ops.gpencil.convert.poll():
+ self.report({'WARNING'},
+ "Operation Cancelled. "
+ "Are there any Grease Pencil Strokes ?")
+ return {'CANCELLED'}
+
+ bpy.ops.gpencil.convert(type='CURVE')
+ # get curve after convert (compare the scenes to get the difference)
+ scene_obj = context.scene.objects
+ check_materials = True
+
+ for obj in scene_obj:
+ if obj not in store_objects and obj.type == "CURVE":
+ gactiveCurve = obj
+ break
+
+ # render ready curve
+ gactiveCurve.data.resolution_u = Btrace.curve_u
+ # Set bevel resolution from Panel options
+ gactiveCurve.data.bevel_resolution = Btrace.curve_resolution
+ gactiveCurve.data.fill_mode = 'FULL'
+ # Set bevel depth from Panel options
+ gactiveCurve.data.bevel_depth = Btrace.curve_depth
+
+ writeObj = context.selected_objects
+ if Btrace.animate:
+ for i in writeObj:
+ context.scene.objects.active = i
+ bpy.ops.curve.btgrow()
+ # Materials
+ trace_mats = addtracemat(bpy.context.object.data)
+ if not trace_mats and check_materials is True:
+ check_materials = False
+ else:
+ for i in writeObj:
+ context.scene.objects.active = i
+ # Materials
+ trace_mats = addtracemat(bpy.context.object.data)
+ if not trace_mats and check_materials is True:
+ check_materials = False
+
+ # Delete grease pencil strokes
+ context.scene.objects.active = gactive
+ bpy.ops.gpencil.data_unlink()
+ context.scene.objects.active = gactiveCurve
+ # Smooth object
+ bpy.ops.object.shade_smooth()
+ # Return to first frame
+ bpy.context.scene.frame_set(Btrace.anim_f_start)
+
+ if check_materials is False:
+ self.report({'WARNING'}, "Some Materials could not be added")
+
+ return{'FINISHED'}
+
+ except Exception as e:
+ error_handlers(self, "curve.btwriting", e,
+ "Grease Pencil conversion could not be completed")
+
+ return {'CANCELLED'}
+
+
+# Create Curve
+# Convert mesh to curve using either Continuous, All Edges, or Sharp Edges
+# Option to create noise
+
+class OBJECT_OT_convertcurve(Operator):
bl_idname = "object.btconvertcurve"
bl_label = "Btrace: Create Curve"
- bl_description = "Convert mesh to curve using either Continuous, All Edges, or Sharp Edges"
+ bl_description = ("Convert Mesh to Curve using either Continuous, "
+ "All Edges or Sharp Edges\n"
+ "Active Object has to be of a Mesh or Font type")
bl_options = {'REGISTER', 'UNDO'}
- def execute(self, context):
- import bpy, random, mathutils
- from mathutils import Vector
-
- Btrace = bpy.context.window_manager.curve_tracer
- traceobjects = bpy.context.selected_objects # create a list with all the selected objects
+ @classmethod
+ def poll(cls, context):
+ return (context.object is not None and
+ context.object.type in {"MESH", "FONT"})
- obj = bpy.context.object
+ def execute(self, context):
+ try:
+ Btrace = context.window_manager.curve_tracer
+ obj = context.object
- ### Convert Font
- if obj.type == 'FONT':
- bpy.ops.object.mode_set(mode='OBJECT')
- bpy.ops.object.convert(target='CURVE') # Convert edges to curve
- bpy.context.object.data.dimensions = '3D'
+ # Convert Font
+ if obj.type == 'FONT':
+ bpy.ops.object.mode_set(mode='OBJECT')
+ bpy.ops.object.convert(target='CURVE') # Convert edges to curve
+ bpy.context.object.data.dimensions = '3D'
- # make a continuous edge through all vertices
- if obj.type == 'MESH':
- # Add noise to mesh
- if Btrace.distort_curve:
- for v in obj.data.vertices:
- for u in range(3):
- v.co[u] += Btrace.distort_noise * (random.uniform(-1,1))
+ # make a continuous edge through all vertices
+ if obj.type == 'MESH':
+ # Add noise to mesh
+ if Btrace.distort_curve:
+ for v in obj.data.vertices:
+ for u in range(3):
+ v.co[u] += Btrace.distort_noise * (rand_uniform(-1, 1))
- if Btrace.convert_edgetype == 'CONTI':
- ## Start Continuous edge
- bpy.ops.object.mode_set(mode='EDIT')
- bpy.ops.mesh.select_all(action='SELECT')
- bpy.ops.mesh.delete(type='EDGE_FACE')
- bpy.ops.mesh.select_all(action='DESELECT')
- verts = bpy.context.object.data.vertices
- bpy.ops.object.mode_set(mode='OBJECT')
- li = []
- p1 = random.randint(0,len(verts)-1)
-
- for v in verts:
- li.append(v.index)
- li.remove(p1)
- for z in range(len(li)):
- x = []
- for px in li:
- d = verts[p1].co - verts[px].co # find distance from first vert
- x.append(d.length)
- p2 = li[x.index(min(x))] # find the shortest distance list index
- verts[p1].select = verts[p2].select = True
+ if Btrace.convert_edgetype == 'CONTI':
+ # Start Continuous edge
bpy.ops.object.mode_set(mode='EDIT')
- bpy.context.tool_settings.mesh_select_mode = [True, False, False]
- bpy.ops.mesh.edge_face_add()
+ bpy.ops.mesh.select_all(action='SELECT')
+ bpy.ops.mesh.delete(type='EDGE_FACE')
bpy.ops.mesh.select_all(action='DESELECT')
+ verts = bpy.context.object.data.vertices
bpy.ops.object.mode_set(mode='OBJECT')
- # verts[p1].select = verts[p2].select = False #Doesn't work after Bmesh merge
- li.remove(p2) # remove item from list.
- p1 = p2
- # Convert edges to curve
- bpy.ops.object.mode_set(mode='OBJECT')
- bpy.ops.object.convert(target='CURVE')
+ li = []
+ p1 = rand_randint(0, len(verts) - 1)
+
+ for v in verts:
+ li.append(v.index)
+ li.remove(p1)
+ for z in range(len(li)):
+ x = []
+ for px in li:
+ d = verts[p1].co - verts[px].co # find distance from first vert
+ x.append(d.length)
+ p2 = li[x.index(min(x))] # find the shortest distance list index
+ verts[p1].select = verts[p2].select = True
+ bpy.ops.object.mode_set(mode='EDIT')
+ bpy.context.tool_settings.mesh_select_mode = [True, False, False]
+ bpy.ops.mesh.edge_face_add()
+ bpy.ops.mesh.select_all(action='DESELECT')
+ bpy.ops.object.mode_set(mode='OBJECT')
+ li.remove(p2) # remove item from list.
+ p1 = p2
+ # Convert edges to curve
+ bpy.ops.object.mode_set(mode='OBJECT')
+ bpy.ops.object.convert(target='CURVE')
- if Btrace.convert_edgetype == 'EDGEALL':
- ## Start All edges
- bpy.ops.object.mode_set(mode='EDIT')
- bpy.ops.mesh.select_all(action='SELECT')
- bpy.ops.mesh.delete(type='ONLY_FACE')
- bpy.ops.object.mode_set()
- bpy.ops.object.convert(target='CURVE')
- for sp in obj.data.splines:
- sp.type = Btrace.curve_spline
-
- obj = bpy.context.object
- # Set spline type to custom property in panel
- bpy.ops.object.editmode_toggle()
- bpy.ops.curve.spline_type_set(type=Btrace.curve_spline)
- # Set handle type to custom property in panel
- bpy.ops.curve.handle_type_set(type=Btrace.curve_handle)
- bpy.ops.object.editmode_toggle()
- obj.data.fill_mode = 'FULL'
- # Set resolution to custom property in panel
- obj.data.bevel_resolution = Btrace.curve_resolution
- obj.data.resolution_u = Btrace.curve_u
- # Set depth to custom property in panel
- obj.data.bevel_depth = Btrace.curve_depth
- # Smooth object
- bpy.ops.object.shade_smooth()
- # Modulate curve radius and add distortion
- if Btrace.distort_curve:
- scale = Btrace.distort_modscale
- if scale == 0:
- return {'FINISHED'}
- for u in obj.data.splines:
- for v in u.bezier_points:
- v.radius = scale*round(random.random(),3)
- return {'FINISHED'}
-
-
-################## ################## ################## ############
-## Mesh Follow, trace vertex or faces
-## Create curve at center of selection item, extruded along animation
-## Needs to be animated mesh!!!
-################## ################## ################## ############
-
-class OBJECT_OT_meshfollow(bpy.types.Operator):
+ if Btrace.convert_edgetype == 'EDGEALL':
+ # Start All edges
+ bpy.ops.object.mode_set(mode='EDIT')
+ bpy.ops.mesh.select_all(action='SELECT')
+ bpy.ops.mesh.delete(type='ONLY_FACE')
+ bpy.ops.object.mode_set()
+ bpy.ops.object.convert(target='CURVE')
+ for sp in obj.data.splines:
+ sp.type = Btrace.curve_spline
+
+ obj = context.object
+ # Set spline type to custom property in panel
+ bpy.ops.object.editmode_toggle()
+ bpy.ops.curve.spline_type_set(type=Btrace.curve_spline)
+ # Set handle type to custom property in panel
+ bpy.ops.curve.handle_type_set(type=Btrace.curve_handle)
+ bpy.ops.object.editmode_toggle()
+ obj.data.fill_mode = 'FULL'
+ # Set resolution to custom property in panel
+ obj.data.bevel_resolution = Btrace.curve_resolution
+ obj.data.resolution_u = Btrace.curve_u
+ # Set depth to custom property in panel
+ obj.data.bevel_depth = Btrace.curve_depth
+ # Smooth object
+ bpy.ops.object.shade_smooth()
+ # Modulate curve radius and add distortion
+ if Btrace.distort_curve:
+ scale = Btrace.distort_modscale
+ if scale == 0:
+ return {'FINISHED'}
+ for u in obj.data.splines:
+ for v in u.bezier_points:
+ v.radius = scale * round(rand_random(), 3)
+
+ return {'FINISHED'}
+
+ except Exception as e:
+ error_handlers(self, "object.btconvertcurve", e,
+ "Conversion could not be completed")
+
+ return {'CANCELLED'}
+
+
+# Mesh Follow, trace vertex or faces
+# Create curve at center of selection item, extruded along animation
+# Needs to be an animated mesh!!!
+
+class OBJECT_OT_meshfollow(Operator):
bl_idname = "object.btmeshfollow"
bl_label = "Btrace: Vertex Trace"
bl_description = "Trace Vertex or Face on an animated mesh"
bl_options = {'REGISTER', 'UNDO'}
-
@classmethod
def poll(cls, context):
return (context.object and context.object.type in {'MESH'})
def execute(self, context):
- import bpy, random
- from mathutils import Vector
-
- Btrace = bpy.context.window_manager.curve_tracer
- distort_curve = Btrace.distort_curve # modulate the resulting curve
- stepsize = Btrace.particle_step
- traceobjects = bpy.context.selected_objects # create a list with all the selected objects
-
- obj = bpy.context.object
- scn = bpy.context.scene
- meshdata = obj.data
- cursor = bpy.context.scene.cursor_location.copy() # Store the location to restore at end of script
- drawmethod = Btrace.fol_mesh_type # Draw from Edges, Verts, or Faces
- if drawmethod == 'VERTS':
- meshobjs = obj.data.vertices
- if drawmethod == 'FACES':
- meshobjs = obj.data.polygons # untested
- if drawmethod == 'EDGES':
- meshobjs = obj.data.edges # untested
-
- # Frame properties
- start_frame, end_frame = Btrace.fol_start_frame, Btrace.fol_end_frame
- if start_frame > end_frame: # Make sure the math works
- startframe = end_frame - 5 # if start past end, goto (end - 5)
- frames = int((end_frame - start_frame) / stepsize)
-
- def getsel_option(): # Get selection objects.
- sel = []
- seloption, fol_mesh_type = Btrace.fol_sel_option, Btrace.fol_mesh_type # options = 'random', 'custom', 'all'
- if fol_mesh_type == 'OBJECT':
- pass
- else:
- if seloption == 'CUSTOM':
- for i in meshobjs:
- if i.select == True:
+ try:
+ Btrace = context.window_manager.curve_tracer
+ stepsize = Btrace.particle_step
+
+ obj = context.object
+ scn = context.scene
+ drawmethod = Btrace.fol_mesh_type # Draw from Edges, Verts, or Faces
+
+ if drawmethod == 'VERTS':
+ meshobjs = obj.data.vertices
+ if drawmethod == 'FACES':
+ meshobjs = obj.data.polygons # untested
+ if drawmethod == 'EDGES':
+ meshobjs = obj.data.edges # untested
+
+ # Frame properties
+ start_frame, end_frame = Btrace.fol_start_frame, Btrace.fol_end_frame
+ if start_frame > end_frame: # Make sure the math works
+ start_frame = end_frame - 5 # if start past end, goto (end - 5)
+ frames = int((end_frame - start_frame) / stepsize)
+
+ def getsel_option(): # Get selection objects
+ sel = []
+ # options are 'random', 'custom', 'all'
+ seloption, fol_mesh_type = Btrace.fol_sel_option, Btrace.fol_mesh_type
+ if fol_mesh_type == 'OBJECT':
+ pass
+ else:
+ if seloption == 'CUSTOM':
+ for i in meshobjs:
+ if i.select is True:
+ sel.append(i.index)
+ if seloption == 'RANDOM':
+ for i in list(meshobjs):
+ sel.append(i.index)
+ finalsel = int(len(sel) * Btrace.fol_perc_verts)
+ remove = len(sel) - finalsel
+ for i in range(remove):
+ sel.pop(rand_randint(0, len(sel) - 1))
+ if seloption == 'ALL':
+ for i in list(meshobjs):
sel.append(i.index)
- if seloption == 'RANDOM':
- for i in list(meshobjs):
- sel.append(i.index)
- finalsel = int(len(sel) * Btrace.fol_perc_verts)
- remove = len(sel) - finalsel
- for i in range(remove):
- sel.pop(random.randint(0, len(sel) - 1))
- if seloption == 'ALL':
- for i in list(meshobjs):
- sel.append(i.index)
-
- return sel
-
- def get_coord(objindex):
- obj_co = [] # list of vector coordinates to use
- frame_x = start_frame
- for i in range(frames): # create frame numbers list
- scn.frame_set(frame_x)
- if drawmethod != 'OBJECT':
- followed_item = meshobjs[objindex]
- if drawmethod == 'VERTS':
- g_co = obj.matrix_local * followed_item.co # find Vert vector
-
- if drawmethod == 'FACES':
- g_co = obj.matrix_local * followed_item.normal # find Face vector
-
- if drawmethod == 'EDGES':
- v1 = followed_item.vertices[0]
- v2 = followed_item.vertices[1]
- co1 = bpy.context.object.data.vertices[v1]
- co2 = bpy.context.object.data.vertices[v2]
- localcenter = co1.co.lerp(co2.co, 0.5)
- g_co = obj.matrix_world * localcenter
-
- if drawmethod == 'OBJECT':
- g_co = objindex.location.copy()
-
- obj_co.append(g_co)
- frame_x = frame_x + stepsize
-
- scn.frame_set(start_frame)
- return obj_co
-
- def make_curve(co_list):
- Btrace = bpy.context.window_manager.curve_tracer
- tracer = bpy.data.curves.new('tracer','CURVE')
- tracer.dimensions = '3D'
- spline = tracer.splines.new('BEZIER')
- spline.bezier_points.add(len(co_list)- 1)
- curve = bpy.data.objects.new('curve',tracer)
- scn.objects.link(curve)
- curvelist.append(curve)
- # render ready curve
- tracer.resolution_u = Btrace.curve_u
- tracer.bevel_resolution = Btrace.curve_resolution # Set bevel resolution from Panel options
- tracer.fill_mode = 'FULL'
- tracer.bevel_depth = Btrace.curve_depth # Set bevel depth from Panel options
- curve_handle = Btrace.curve_handle
- if curve_handle == 'AUTOMATIC': # hackish AUTOMATIC doesn't work here
- curve_handle = 'AUTO'
-
- # move bezier points to objects
- for i in range(len(co_list)):
- p = spline.bezier_points[i]
- p.co = co_list[i]
- p.handle_right_type = curve_handle
- p.handle_left_type = curve_handle
- return curve
-
- # Run methods
- # Check if Btrace group exists, if not create
- bgroup = bpy.data.groups.keys()
- if 'Btrace' not in bgroup:
- bpy.ops.group.create(name="Btrace")
-
- Btrace = bpy.context.window_manager.curve_tracer
- sel = getsel_option() # Get selection
- curvelist = [] # list to use for grow curve
-
- if Btrace.fol_mesh_type == 'OBJECT':
- vector_list = get_coord(obj)
- curvelist.append(make_curve(vector_list))
- else:
- for i in sel:
- vector_list = get_coord(i)
- curvelist.append(make_curve(vector_list))
- # Select new curves and add to group
- bpy.ops.object.select_all(action='DESELECT')
- for curveobject in curvelist:
- if curveobject.type == 'CURVE':
- curveobject.select = True
- bpy.context.scene.objects.active = curveobject
- bpy.ops.object.group_link(group="Btrace")
- addtracemat(curveobject.data)
- curveobject.select = False
- if Btrace.animate: # Add grow curve
- for curveobject in curvelist:
- curveobject.select = True
- bpy.ops.curve.btgrow()
- for curveobject in curvelist:
- curveobject.select = False
+ return sel
+
+ def get_coord(objindex):
+ obj_co = [] # list of vector coordinates to use
+ frame_x = start_frame
+ for i in range(frames): # create frame numbers list
+ scn.frame_set(frame_x)
+ if drawmethod != 'OBJECT':
+ followed_item = meshobjs[objindex]
+ if drawmethod == 'VERTS':
+ # find Vert vector
+ g_co = obj.matrix_local * followed_item.co
+
+ if drawmethod == 'FACES':
+ # find Face vector
+ g_co = obj.matrix_local * followed_item.normal
+
+ if drawmethod == 'EDGES':
+ v1 = followed_item.vertices[0]
+ v2 = followed_item.vertices[1]
+ co1 = bpy.context.object.data.vertices[v1]
+ co2 = bpy.context.object.data.vertices[v2]
+ localcenter = co1.co.lerp(co2.co, 0.5)
+ g_co = obj.matrix_world * localcenter
+
+ if drawmethod == 'OBJECT':
+ g_co = objindex.location.copy()
+
+ obj_co.append(g_co)
+ frame_x = frame_x + stepsize
+
+ scn.frame_set(start_frame)
+ return obj_co
+
+ def make_curve(co_list):
+ Btrace = bpy.context.window_manager.curve_tracer
+ tracer = bpy.data.curves.new('tracer', 'CURVE')
+ tracer.dimensions = '3D'
+ spline = tracer.splines.new('BEZIER')
+ spline.bezier_points.add(len(co_list) - 1)
+ curve = bpy.data.objects.new('curve', tracer)
+ scn.objects.link(curve)
+ curvelist.append(curve)
+ # render ready curve
+ tracer.resolution_u = Btrace.curve_u
+ # Set bevel resolution from Panel options
+ tracer.bevel_resolution = Btrace.curve_resolution
+ tracer.fill_mode = 'FULL'
+ # Set bevel depth from Panel options
+ tracer.bevel_depth = Btrace.curve_depth
+ curve_handle = Btrace.curve_handle
+
+ # hackish AUTOMATIC doesn't work here
+ if curve_handle == 'AUTOMATIC':
+ curve_handle = 'AUTO'
+
+ # move bezier points to objects
+ for i in range(len(co_list)):
+ p = spline.bezier_points[i]
+ p.co = co_list[i]
+ p.handle_right_type = curve_handle
+ p.handle_left_type = curve_handle
+ return curve
- obj.select = False # Deselect original object
- return {'FINISHED'}
+ # Run methods
+ # Check if Btrace group exists, if not create
+ bgroup = bpy.data.groups.keys()
+ if 'Btrace' not in bgroup:
+ bpy.ops.group.create(name="Btrace")
-###################################################################
-#### Add Tracer Material
-###################################################################
+ Btrace = bpy.context.window_manager.curve_tracer
+ sel = getsel_option() # Get selection
+ curvelist = [] # list to use for grow curve
+ check_materials = True
-def addtracemat(matobj):
- matslots = bpy.context.object.data.materials.items() # Check if a material exists, skip if it does
- if len(matslots) < 1: # Make sure there is only one material slot
- engine = bpy.context.scene.render.engine
- Btrace = bpy.context.window_manager.curve_tracer
- if not Btrace.mat_run_color_blender: # Check if color blender is to be run
- if Btrace.trace_mat_random: # Create Random color for each item
- # Use random color from chosen palette, assign color lists for each palette
- import random
- brightColors = [Btrace.brightColor1, Btrace.brightColor2, Btrace.brightColor3, Btrace.brightColor4]
- bwColors = [Btrace.bwColor1, Btrace.bwColor2]
- customColors = [Btrace.mmColor1, Btrace.mmColor2, Btrace.mmColor3, Btrace.mmColor4, Btrace.mmColor5, Btrace.mmColor6, Btrace.mmColor7, Btrace.mmColor8]
- earthColors = [Btrace.earthColor1, Btrace.earthColor2, Btrace.earthColor3, Btrace.earthColor4, Btrace.earthColor5]
- greenblueColors = [Btrace.greenblueColor1, Btrace.greenblueColor2, Btrace.greenblueColor3]
- if Btrace.mmColors == 'BRIGHT':
- #print(random.randint(0, len(brightColors) - 1))
- mat_color = brightColors[random.randint(0, len(brightColors) - 1)]
- if Btrace.mmColors == 'BW':
- mat_color = bwColors[random.randint(0, len(bwColors) - 1)]
- if Btrace.mmColors == 'CUSTOM':
- mat_color = customColors[random.randint(0, len(customColors) - 1)]
- if Btrace.mmColors == 'EARTH':
- mat_color = earthColors[random.randint(0, len(earthColors) - 1)]
- if Btrace.mmColors == 'GREENBLUE':
- mat_color = greenblueColors[random.randint(0, len(greenblueColors) - 1)]
- if Btrace.mmColors == 'RANDOM':
- mat_color = (random.random(), random.random(), random.random())
- else: # Choose Single color
- mat_color = Btrace.trace_mat_color
- # mat_color = Btrace.trace_mat_color
- TraceMat = bpy.data.materials.new('TraceMat')
- # add cycles or BI render material options
- if engine == 'CYCLES':
- TraceMat.use_nodes = True
- Diffuse_BSDF = TraceMat.node_tree.nodes['Diffuse BSDF']
- r, g, b = mat_color[0], mat_color[1], mat_color[2]
- Diffuse_BSDF.inputs[0].default_value = [r, g, b, 1]
- TraceMat.diffuse_color = mat_color
+ if Btrace.fol_mesh_type == 'OBJECT':
+ vector_list = get_coord(obj)
+ curvelist.append(make_curve(vector_list))
else:
- TraceMat.diffuse_color = mat_color
- TraceMat.specular_intensity = 0.5
- # Add material to object
- matobj.materials.append(bpy.data.materials.get(TraceMat.name))
-
- else: # Run color blender operator
- bpy.ops.object.colorblender()
+ for i in sel:
+ vector_list = get_coord(i)
+ curvelist.append(make_curve(vector_list))
+ # Select new curves and add to group
+ bpy.ops.object.select_all(action='DESELECT')
+ for curveobject in curvelist:
+ if curveobject.type == 'CURVE':
+ curveobject.select = True
+ context.scene.objects.active = curveobject
+ bpy.ops.object.group_link(group="Btrace")
+ # Materials
+ trace_mats = addtracemat(curveobject.data)
+ if not trace_mats and check_materials is True:
+ check_materials = False
+
+ curveobject.select = False
+
+ if Btrace.animate: # Add grow curve
+ for curveobject in curvelist:
+ curveobject.select = True
+ bpy.ops.curve.btgrow()
+ for curveobject in curvelist:
+ curveobject.select = False
- return {'FINISHED'}
+ obj.select = False # Deselect original object
-###################################################################
-#### Add Color Blender Material
-###################################################################
+ if check_materials is False:
+ self.report({'WARNING'}, "Some Materials could not be added")
-# This is the magical material changer!
-class OBJECT_OT_materialChango(bpy.types.Operator):
- bl_idname = 'object.colorblender'
- bl_label = 'Color Blender'
- bl_options = {'REGISTER', 'UNDO'}
+ return {'FINISHED'}
- def execute(self, context):
+ except Exception as e:
+ error_handlers(self, "object.btmeshfollow", e,
+ "Vertex Trace could not be completed")
- import bpy, random
- Btrace = bpy.context.window_manager.curve_tracer # properties panel
- colorObjects = bpy.context.selected_objects
-
- # Set color lists
- brightColors = [Btrace.brightColor1, Btrace.brightColor2, Btrace.brightColor3, Btrace.brightColor4]
- bwColors = [Btrace.bwColor1, Btrace.bwColor2]
- customColors = [Btrace.mmColor1, Btrace.mmColor2, Btrace.mmColor3, Btrace.mmColor4, Btrace.mmColor5, Btrace.mmColor6, Btrace.mmColor7, Btrace.mmColor8]
- earthColors = [Btrace.earthColor1, Btrace.earthColor2, Btrace.earthColor3, Btrace.earthColor4, Btrace.earthColor5]
- greenblueColors = [Btrace.greenblueColor1, Btrace.greenblueColor2, Btrace.greenblueColor3]
-
- colorList = Btrace.mmColors
- engine = bpy.context.scene.render.engine
-
- # Go through each selected object and run the operator
- for i in colorObjects:
- theObj = i
- # Check to see if object has materials
- checkMaterials = len(theObj.data.materials)
- if engine == 'CYCLES':
- materialName = "colorblendMaterial"
- madMat = bpy.data.materials.new(materialName)
- madMat.use_nodes = True
- if checkMaterials == 0:
- theObj.data.materials.append(madMat)
- else:
- theObj.material_slots[0].material = madMat
- else: # This is internal
- if checkMaterials == 0:
- # Add a material
- materialName = "colorblendMaterial"
- madMat = bpy.data.materials.new(materialName)
- theObj.data.materials.append(madMat)
- else:
- pass # pass since we have what we need
- # assign the first material of the object to "mat"
- madMat = theObj.data.materials[0]
+ return {'CANCELLED'}
- # Numbers of frames to skip between keyframes
- skip = Btrace.mmSkip
+# Add Tracer Material
+def addtracemat(matobj):
+ try:
+ # Check if a material exists, skip if it does
+ matslots = bpy.context.object.data.materials.items()
+ if len(matslots) < 1: # Make sure there is only one material slot
+ engine = bpy.context.scene.render.engine
+ Btrace = bpy.context.window_manager.curve_tracer
- # Random material function
- def colorblenderRandom():
- randomRGB = (random.random(), random.random(), random.random())
- if engine == 'CYCLES':
- Diffuse_BSDF = madMat.node_tree.nodes['Diffuse BSDF']
- mat_color = randomRGB
- r, g, b = mat_color[0], mat_color[1], mat_color[2]
- Diffuse_BSDF.inputs[0].default_value = [r, g, b, 1]
- madMat.diffuse_color = mat_color
+ # Check if color blender is to be run
+ if not Btrace.mat_run_color_blender:
+ # Create Random color for each item
+ if Btrace.trace_mat_random:
+ # Use random color from chosen palette,
+ # assign color lists for each palette
+ brightColors = [
+ Btrace.brightColor1, Btrace.brightColor2,
+ Btrace.brightColor3, Btrace.brightColor4
+ ]
+ bwColors = [
+ Btrace.bwColor1, Btrace.bwColor2
+ ]
+ customColors = [
+ Btrace.mmColor1, Btrace.mmColor2, Btrace.mmColor3,
+ Btrace.mmColor4, Btrace.mmColor5, Btrace.mmColor6,
+ Btrace.mmColor7, Btrace.mmColor8
+ ]
+ earthColors = [
+ Btrace.earthColor1, Btrace.earthColor2,
+ Btrace.earthColor3, Btrace.earthColor4,
+ Btrace.earthColor5
+ ]
+ greenblueColors = [
+ Btrace.greenblueColor1, Btrace.greenblueColor2,
+ Btrace.greenblueColor3
+ ]
+ if Btrace.mmColors == 'BRIGHT':
+ mat_color = brightColors[
+ rand_randint(0, len(brightColors) - 1)
+ ]
+ if Btrace.mmColors == 'BW':
+ mat_color = bwColors[
+ rand_randint(0, len(bwColors) - 1)
+ ]
+ if Btrace.mmColors == 'CUSTOM':
+ mat_color = customColors[
+ rand_randint(0, len(customColors) - 1)
+ ]
+ if Btrace.mmColors == 'EARTH':
+ mat_color = earthColors[
+ rand_randint(0, len(earthColors) - 1)
+ ]
+ if Btrace.mmColors == 'GREENBLUE':
+ mat_color = greenblueColors[
+ rand_randint(0, len(greenblueColors) - 1)
+ ]
+ if Btrace.mmColors == 'RANDOM':
+ mat_color = (rand_random(), rand_random(), rand_random())
else:
- madMat.diffuse_color = randomRGB
+ # Choose Single color
+ mat_color = Btrace.trace_mat_color
- def colorblenderCustom():
+ TraceMat = bpy.data.materials.new('TraceMat')
+ # add cycles or BI render material options
if engine == 'CYCLES':
- Diffuse_BSDF = madMat.node_tree.nodes['Diffuse BSDF']
- mat_color = random.choice(customColors)
+ TraceMat.use_nodes = True
+ Diffuse_BSDF = TraceMat.node_tree.nodes['Diffuse BSDF']
r, g, b = mat_color[0], mat_color[1], mat_color[2]
Diffuse_BSDF.inputs[0].default_value = [r, g, b, 1]
- madMat.diffuse_color = mat_color
+ TraceMat.diffuse_color = mat_color
else:
- madMat.diffuse_color = random.choice(customColors)
+ TraceMat.diffuse_color = mat_color
+ TraceMat.specular_intensity = 0.5
+ # Add material to object
+ matobj.materials.append(bpy.data.materials.get(TraceMat.name))
- # Black and white color
- def colorblenderBW():
- if engine == 'CYCLES':
- Diffuse_BSDF = madMat.node_tree.nodes['Diffuse BSDF']
- mat_color = random.choice(bwColors)
- r, g, b = mat_color[0], mat_color[1], mat_color[2]
- Diffuse_BSDF.inputs[0].default_value = [r, g, b, 1]
- madMat.diffuse_color = mat_color
- else:
- madMat.diffuse_color = random.choice(bwColors)
+ else:
+ # Run color blender operator
+ bpy.ops.object.colorblender()
- # Bright colors
- def colorblenderBright():
- if engine == 'CYCLES':
- Diffuse_BSDF = madMat.node_tree.nodes['Diffuse BSDF']
- mat_color = random.choice(brightColors)
- r, g, b = mat_color[0], mat_color[1], mat_color[2]
- Diffuse_BSDF.inputs[0].default_value = [r, g, b, 1]
- madMat.diffuse_color = mat_color
- else:
- madMat.diffuse_color = random.choice(brightColors)
+ return True
- # Earth Tones
- def colorblenderEarth():
- if engine == 'CYCLES':
- Diffuse_BSDF = madMat.node_tree.nodes['Diffuse BSDF']
- mat_color = random.choice(earthColors)
- r, g, b = mat_color[0], mat_color[1], mat_color[2]
- Diffuse_BSDF.inputs[0].default_value = [r, g, b, 1]
- madMat.diffuse_color = mat_color
- else:
- madMat.diffuse_color = random.choice(earthColors)
+ except Exception as e:
+ error_handlers(False, "addtracemat", e, "Function error", True)
- # Green to Blue Tones
- def colorblenderGreenBlue():
- if engine == 'CYCLES':
- Diffuse_BSDF = madMat.node_tree.nodes['Diffuse BSDF']
- mat_color = random.choice(greenblueColors)
- r, g, b = mat_color[0], mat_color[1], mat_color[2]
- Diffuse_BSDF.inputs[0].default_value = [r, g, b, 1]
- madMat.diffuse_color = mat_color
- else:
- madMat.diffuse_color = random.choice(greenblueColors)
-
- # define frame start/end variables
- scn = bpy.context.scene
- start = scn.frame_start
- end = scn.frame_end
- # Go to each frame in iteration and add material
- while start<=(end+(skip-1)):
-
- bpy.context.scene.frame_set(frame=start)
-
- # Check what colors setting is checked and run the appropriate function
- if Btrace.mmColors=='RANDOM':
- colorblenderRandom()
- elif Btrace.mmColors=='CUSTOM':
- colorblenderCustom()
- elif Btrace.mmColors=='BW':
- colorblenderBW()
- elif Btrace.mmColors=='BRIGHT':
- colorblenderBright()
- elif Btrace.mmColors=='EARTH':
- colorblenderEarth()
- elif Btrace.mmColors=='GREENBLUE':
- colorblenderGreenBlue()
- else:
- pass
+ return False
+
+
+# Add Color Blender Material
+# This is the magical material changer!
+class OBJECT_OT_materialChango(Operator):
+ bl_idname = "object.colorblender"
+ bl_label = "Color Blender"
+ bl_options = {'REGISTER', 'UNDO'}
- # Add keyframe to material
+ def execute(self, context):
+ try:
+ # properties panel
+ Btrace = context.window_manager.curve_tracer
+ colorObjects = context.selected_objects
+
+ # Set color lists
+ brightColors = [
+ Btrace.brightColor1, Btrace.brightColor2,
+ Btrace.brightColor3, Btrace.brightColor4
+ ]
+ bwColors = [Btrace.bwColor1, Btrace.bwColor2]
+ customColors = [
+ Btrace.mmColor1, Btrace.mmColor2, Btrace.mmColor3,
+ Btrace.mmColor4, Btrace.mmColor5, Btrace.mmColor6,
+ Btrace.mmColor7, Btrace.mmColor8
+ ]
+ earthColors = [
+ Btrace.earthColor1, Btrace.earthColor2, Btrace.earthColor3,
+ Btrace.earthColor4, Btrace.earthColor5
+ ]
+ greenblueColors = [
+ Btrace.greenblueColor1, Btrace.greenblueColor2,
+ Btrace.greenblueColor3
+ ]
+ engine = context.scene.render.engine
+
+ # Go through each selected object and run the operator
+ for i in colorObjects:
+ theObj = i
+ # Check to see if object has materials
+ checkMaterials = len(theObj.data.materials)
if engine == 'CYCLES':
- madMat.node_tree.nodes['Diffuse BSDF'].inputs[0].keyframe_insert('default_value')
- madMat.keyframe_insert('diffuse_color') # not sure if this is need, it's viewport color only
- else:
- madMat.keyframe_insert('diffuse_color')
+ materialName = "colorblendMaterial"
+ madMat = bpy.data.materials.new(materialName)
+ madMat.use_nodes = True
+ if checkMaterials == 0:
+ theObj.data.materials.append(madMat)
+ else:
+ theObj.material_slots[0].material = madMat
+ else: # This is internal
+ if checkMaterials == 0:
+ # Add a material
+ materialName = "colorblendMaterial"
+ madMat = bpy.data.materials.new(materialName)
+ theObj.data.materials.append(madMat)
+ else:
+ pass # pass since we have what we need
+ # assign the first material of the object to "mat"
+ madMat = theObj.data.materials[0]
+
+ # Numbers of frames to skip between keyframes
+ skip = Btrace.mmSkip
+
+ # Random material function
+ def colorblenderRandom():
+ randomRGB = (rand_random(), rand_random(), rand_random())
+ if engine == 'CYCLES':
+ Diffuse_BSDF = madMat.node_tree.nodes['Diffuse BSDF']
+ mat_color = randomRGB
+ r, g, b = mat_color[0], mat_color[1], mat_color[2]
+ Diffuse_BSDF.inputs[0].default_value = [r, g, b, 1]
+ madMat.diffuse_color = mat_color
+ else:
+ madMat.diffuse_color = randomRGB
+
+ def colorblenderCustom():
+ if engine == 'CYCLES':
+ Diffuse_BSDF = madMat.node_tree.nodes['Diffuse BSDF']
+ mat_color = rand_choice(customColors)
+ r, g, b = mat_color[0], mat_color[1], mat_color[2]
+ Diffuse_BSDF.inputs[0].default_value = [r, g, b, 1]
+ madMat.diffuse_color = mat_color
+ else:
+ madMat.diffuse_color = rand_choice(customColors)
+
+ # Black and white color
+ def colorblenderBW():
+ if engine == 'CYCLES':
+ Diffuse_BSDF = madMat.node_tree.nodes['Diffuse BSDF']
+ mat_color = rand_choice(bwColors)
+ r, g, b = mat_color[0], mat_color[1], mat_color[2]
+ Diffuse_BSDF.inputs[0].default_value = [r, g, b, 1]
+ madMat.diffuse_color = mat_color
+ else:
+ madMat.diffuse_color = rand_choice(bwColors)
+
+ # Bright colors
+ def colorblenderBright():
+ if engine == 'CYCLES':
+ Diffuse_BSDF = madMat.node_tree.nodes['Diffuse BSDF']
+ mat_color = rand_choice(brightColors)
+ r, g, b = mat_color[0], mat_color[1], mat_color[2]
+ Diffuse_BSDF.inputs[0].default_value = [r, g, b, 1]
+ madMat.diffuse_color = mat_color
+ else:
+ madMat.diffuse_color = rand_choice(brightColors)
+
+ # Earth Tones
+ def colorblenderEarth():
+ if engine == 'CYCLES':
+ Diffuse_BSDF = madMat.node_tree.nodes['Diffuse BSDF']
+ mat_color = rand_choice(earthColors)
+ r, g, b = mat_color[0], mat_color[1], mat_color[2]
+ Diffuse_BSDF.inputs[0].default_value = [r, g, b, 1]
+ madMat.diffuse_color = mat_color
+ else:
+ madMat.diffuse_color = rand_choice(earthColors)
+
+ # Green to Blue Tones
+ def colorblenderGreenBlue():
+ if engine == 'CYCLES':
+ Diffuse_BSDF = madMat.node_tree.nodes['Diffuse BSDF']
+ mat_color = rand_choice(greenblueColors)
+ r, g, b = mat_color[0], mat_color[1], mat_color[2]
+ Diffuse_BSDF.inputs[0].default_value = [r, g, b, 1]
+ madMat.diffuse_color = mat_color
+ else:
+ madMat.diffuse_color = rand_choice(greenblueColors)
+
+ # define frame start/end variables
+ scn = context.scene
+ start = scn.frame_start
+ end = scn.frame_end
+
+ # Go to each frame in iteration and add material
+ while start <= (end + (skip - 1)):
+ bpy.context.scene.frame_set(frame=start)
+
+ # Check what colors setting is checked and run the appropriate function
+ if Btrace.mmColors == 'RANDOM':
+ colorblenderRandom()
+ elif Btrace.mmColors == 'CUSTOM':
+ colorblenderCustom()
+ elif Btrace.mmColors == 'BW':
+ colorblenderBW()
+ elif Btrace.mmColors == 'BRIGHT':
+ colorblenderBright()
+ elif Btrace.mmColors == 'EARTH':
+ colorblenderEarth()
+ elif Btrace.mmColors == 'GREENBLUE':
+ colorblenderGreenBlue()
+ else:
+ pass
+
+ # Add keyframe to material
+ if engine == 'CYCLES':
+ madMat.node_tree.nodes[
+ 'Diffuse BSDF'].inputs[0].keyframe_insert('default_value')
+ # not sure if this is need, it's viewport color only
+ madMat.keyframe_insert('diffuse_color')
+ else:
+ madMat.keyframe_insert('diffuse_color')
+
+ # Increase frame number
+ start += skip
+
+ return{'FINISHED'}
+
+ except Exception as e:
+ error_handlers(self, "object.colorblender", e,
+ "Color Blender could not be completed")
+
+ return {'CANCELLED'}
- # Increase frame number
- start += skip
- return{'FINISHED'}
-###### This clears the keyframes ######
-class OBJECT_OT_clearColorblender(bpy.types.Operator):
- bl_idname = 'object.colorblenderclear'
- bl_label = 'Clear colorblendness'
+# This clears the keyframes
+class OBJECT_OT_clearColorblender(Operator):
+ bl_idname = "object.colorblenderclear"
+ bl_label = "Clear colorblendness"
+ bl_description = "Clear the color keyframes"
bl_options = {'REGISTER', 'UNDO'}
def invoke(self, context, event):
+ try:
+ colorObjects = context.selected_objects
+ engine = context.scene.render.engine
- import bpy, random
- mcolorblend = context.window_manager.colorblender_operator # properties panel
- colorObjects = bpy.context.selected_objects
-
- # Go through each selected object and run the operator
- for i in colorObjects:
- theObj = i
- # assign the first material of the object to "mat"
- matCl = theObj.data.materials[0]
+ # Go through each selected object and run the operator
+ for i in colorObjects:
+ theObj = i
+ # assign the first material of the object to "mat"
+ matCl = theObj.data.materials[0]
+
+ # define frame start/end variables
+ scn = context.scene
+ start = scn.frame_start
+ end = scn.frame_end
+
+ # Remove all keyframes from diffuse_color, super sloppy
+ while start <= (end + 100):
+ context.scene.frame_set(frame=start)
+ try:
+ if engine == 'CYCLES':
+ matCl.node_tree.nodes[
+ 'Diffuse BSDF'].inputs[0].keyframe_delete('default_value')
+ elif engine == 'BLENDER_RENDER':
+ matCl.keyframe_delete('diffuse_color')
+ except:
+ pass
+ start += 1
- # define frame start/end variables
- scn = bpy.context.scene
- start = scn.frame_start
- end = scn.frame_end
+ return{'FINISHED'}
- # Remove all keyframes from diffuse_color, super sloppy need to find better way
- while start <= (end * 2):
- bpy.context.scene.frame_set(frame=start)
- matCl.keyframe_delete('diffuse_color')
- start += 1
+ except Exception as e:
+ error_handlers(self, "object.colorblenderclear", e,
+ "Reset Keyframes could not be completed")
- return{'FINISHED'}
+ return {'CANCELLED'}
-################## ################## ################## ############
-## F-Curve Noise
-## will add noise modifiers to each selected object f-curves
-## change type to: 'rotation' | 'location' | 'scale' | '' to effect all
-## first record a keyframe for this to work (to generate the f-curves)
-################## ################## ################## ############
+# F-Curve Noise
+# will add noise modifiers to each selected object f-curves
+# change type to: 'rotation' | 'location' | 'scale' | '' to effect all
+# first record a keyframe for this to work (to generate the f-curves)
-class OBJECT_OT_fcnoise(bpy.types.Operator):
+class OBJECT_OT_fcnoise(Operator):
bl_idname = "object.btfcnoise"
bl_label = "Btrace: F-curve Noise"
bl_options = {'REGISTER', 'UNDO'}
def execute(self, context):
- import bpy, random
-
- Btrace = bpy.context.window_manager.curve_tracer
- amp = Btrace.fcnoise_amp
- timescale = Btrace.fcnoise_timescale
- addkeyframe = Btrace.fcnoise_key
-
- # This sets properties for Loc, Rot and Scale if they're checked in the Tools window
- noise_rot = 'rotation'
- noise_loc = 'location'
- noise_scale = 'scale'
- if not Btrace.fcnoise_rot:
- noise_rot = 'none'
- if not Btrace.fcnoise_loc:
- noise_loc = 'none'
- if not Btrace.fcnoise_scale:
- noise_scale = 'none'
-
- type = noise_loc, noise_rot, noise_scale # Add settings from panel for type of keyframes
- amplitude = amp
- time_scale = timescale
-
- for i in bpy.context.selected_objects:
- # Add keyframes, this is messy and should only add keyframes for what is checked
- if addkeyframe == True:
- bpy.ops.anim.keyframe_insert(type="LocRotScale")
- for obj in bpy.context.selected_objects:
- if obj.animation_data:
- for c in obj.animation_data.action.fcurves:
- if c.data_path.startswith(type):
- # clean modifiers
- for m in c.modifiers :
- c.modifiers.remove(m)
- # add noide modifiers
- n = c.modifiers.new('NOISE')
- n.strength = amplitude
- n.scale = time_scale
- n.phase = random.randint(0,999)
- return {'FINISHED'}
-
-################## ################## ################## ############
-## Curve Grow Animation
-## Animate curve radius over length of time
-################## ################## ################## ############
-class OBJECT_OT_curvegrow(bpy.types.Operator):
- bl_idname = 'curve.btgrow'
- bl_label = 'Run Script'
- bl_description = 'Keyframe points radius'
+ try:
+ Btrace = context.window_manager.curve_tracer
+ amp = Btrace.fcnoise_amp
+ timescale = Btrace.fcnoise_timescale
+ addkeyframe = Btrace.fcnoise_key
+
+ # This sets properties for Loc, Rot and Scale
+ # if they're checked in the Tools window
+ noise_rot = 'rotation'
+ noise_loc = 'location'
+ noise_scale = 'scale'
+ if not Btrace.fcnoise_rot:
+ noise_rot = 'none'
+ if not Btrace.fcnoise_loc:
+ noise_loc = 'none'
+ if not Btrace.fcnoise_scale:
+ noise_scale = 'none'
+
+ # Add settings from panel for type of keyframes
+ types = noise_loc, noise_rot, noise_scale
+ amplitude = amp
+ time_scale = timescale
+
+ for i in context.selected_objects:
+ # Add keyframes, this is messy and should only
+ # add keyframes for what is checked
+ if addkeyframe is True:
+ bpy.ops.anim.keyframe_insert(type="LocRotScale")
+ for obj in context.selected_objects:
+ if obj.animation_data:
+ for c in obj.animation_data.action.fcurves:
+ if c.data_path.startswith(types):
+ # clean modifiers
+ for m in c.modifiers:
+ c.modifiers.remove(m)
+ # add noide modifiers
+ n = c.modifiers.new('NOISE')
+ n.strength = amplitude
+ n.scale = time_scale
+ n.phase = rand_randint(0, 999)
+
+ return {'FINISHED'}
+
+ except Exception as e:
+ error_handlers(self, "object.btfcnoise", e,
+ "F-curve Noise could not be completed")
+
+ return {'CANCELLED'}
+
+
+# Curve Grow Animation
+# Animate curve radius over length of time
+
+class OBJECT_OT_curvegrow(Operator):
+ bl_idname = "curve.btgrow"
+ bl_label = "Run Script"
+ bl_description = "Keyframe points radius"
bl_options = {'REGISTER', 'UNDO'}
@classmethod
@@ -1520,109 +1154,107 @@ class OBJECT_OT_curvegrow(bpy.types.Operator):
return (context.object and context.object.type in {'CURVE'})
def execute(self, context):
- Btrace = bpy.context.window_manager.curve_tracer
- anim_f_start, anim_length, anim_auto = Btrace.anim_f_start, Btrace.anim_length, Btrace.anim_auto
- curve_resolution, curve_depth = Btrace.curve_resolution, Btrace.curve_depth
- # make the curve visible
- objs = bpy.context.selected_objects
- for i in objs: # Execute on multiple selected objects
- bpy.context.scene.objects.active = i
- obj = bpy.context.active_object
- try:
- obj.data.fill_mode = 'FULL'
- except:
- obj.data.dimensions = '3D'
- obj.data.fill_mode = 'FULL'
- if not obj.data.bevel_resolution:
- obj.data.bevel_resolution = curve_resolution
- if not obj.data.bevel_depth:
- obj.data.bevel_depth = curve_depth
- if anim_auto:
- anim_f_start = bpy.context.scene.frame_start
- anim_length = bpy.context.scene.frame_end
- # get points data and beautify
- actual, total = anim_f_start, 0
- for sp in obj.data.splines:
- total += len(sp.points) + len(sp.bezier_points)
- step = anim_length / total
- for sp in obj.data.splines:
- sp.radius_interpolation = 'BSPLINE'
- po = [p for p in sp.points] + [p for p in sp.bezier_points]
- if not Btrace.anim_keepr:
- for p in po:
- p.radius = 1
- if Btrace.anim_tails and not sp.use_cyclic_u:
- po[0].radius = po[-1].radius = 0
- po[1].radius = po[-2].radius = .65
- ra = [p.radius for p in po]
-
- # record the keyframes
- for i in range(len(po)):
- po[i].radius = 0
- po[i].keyframe_insert('radius', frame=actual)
- actual += step
- po[i].radius = ra[i]
- po[i].keyframe_insert('radius', frame=(actual + Btrace.anim_delay))
-
- if Btrace.anim_f_fade:
- po[i].radius = ra[i]
- po[i].keyframe_insert('radius', frame=(actual + Btrace.anim_f_fade - step))
+ try:
+ # not so nice with the nested try blocks, however the inside one
+ # is used as a switch statement
+ Btrace = context.window_manager.curve_tracer
+ anim_f_start, anim_length, anim_auto = Btrace.anim_f_start, \
+ Btrace.anim_length, \
+ Btrace.anim_auto
+ curve_resolution, curve_depth = Btrace.curve_resolution, \
+ Btrace.curve_depth
+ # make the curve visible
+ objs = context.selected_objects
+ # Execute on multiple selected objects
+ for i in objs:
+ context.scene.objects.active = i
+ obj = context.active_object
+ try:
+ obj.data.fill_mode = 'FULL'
+ except:
+ obj.data.dimensions = '3D'
+ obj.data.fill_mode = 'FULL'
+ if not obj.data.bevel_resolution:
+ obj.data.bevel_resolution = curve_resolution
+ if not obj.data.bevel_depth:
+ obj.data.bevel_depth = curve_depth
+ if anim_auto:
+ anim_f_start = bpy.context.scene.frame_start
+ anim_length = bpy.context.scene.frame_end
+ # get points data and beautify
+ actual, total = anim_f_start, 0
+ for sp in obj.data.splines:
+ total += len(sp.points) + len(sp.bezier_points)
+ step = anim_length / total
+ for sp in obj.data.splines:
+ sp.radius_interpolation = 'BSPLINE'
+ po = [p for p in sp.points] + [p for p in sp.bezier_points]
+ if not Btrace.anim_keepr:
+ for p in po:
+ p.radius = 1
+ if Btrace.anim_tails and not sp.use_cyclic_u:
+ po[0].radius = po[-1].radius = 0
+ po[1].radius = po[-2].radius = .65
+ ra = [p.radius for p in po]
+
+ # record the keyframes
+ for i in range(len(po)):
po[i].radius = 0
- po[i].keyframe_insert('radius', frame=(actual + Btrace.anim_delay + Btrace.anim_f_fade))
+ po[i].keyframe_insert('radius', frame=actual)
+ actual += step
+ po[i].radius = ra[i]
+ po[i].keyframe_insert(
+ 'radius',
+ frame=(actual + Btrace.anim_delay)
+ )
+
+ if Btrace.anim_f_fade:
+ po[i].radius = ra[i]
+ po[i].keyframe_insert(
+ 'radius',
+ frame=(actual + Btrace.anim_f_fade - step)
+ )
+ po[i].radius = 0
+ po[i].keyframe_insert(
+ 'radius',
+ frame=(actual + Btrace.anim_delay + Btrace.anim_f_fade)
+ )
+
+ bpy.context.scene.frame_set(Btrace.anim_f_start)
- bpy.context.scene.frame_set(Btrace.anim_f_start)
- return{'FINISHED'}
-
-################## ################## ################## ############
-## Remove animation and curve radius data
-################## ################## ################## ############
-class OBJECT_OT_reset(bpy.types.Operator):
- bl_idname = 'object.btreset'
- bl_label = 'Clear animation'
- bl_description = 'Remove animation / curve radius data'
+ return{'FINISHED'}
+
+ except Exception as e:
+ error_handlers(self, "curve.btgrow", e,
+ "Grow curve could not be completed")
+
+ return {'CANCELLED'}
+
+
+# Remove animation and curve radius data
+class OBJECT_OT_reset(Operator):
+ bl_idname = "object.btreset"
+ bl_label = "Clear animation"
+ bl_description = "Remove animation / curve radius data"
bl_options = {'REGISTER', 'UNDO'}
def execute(self, context):
- objs = bpy.context.selected_objects
- for i in objs: # Execute on multiple selected objects
- bpy.context.scene.objects.active = i
- obj = bpy.context.active_object
- obj.animation_data_clear()
- if obj.type == 'CURVE':
- for sp in obj.data.splines:
- po = [p for p in sp.points] + [p for p in sp.bezier_points]
- for p in po:
- p.radius = 1
- return{'FINISHED'}
-
-### Define Classes to register
-classes = [
- TracerProperties,
- TracerPropertiesMenu,
- addTracerObjectPanel,
- OBJECT_OT_convertcurve,
- OBJECT_OT_objecttrace,
- OBJECT_OT_objectconnect,
- OBJECT_OT_writing,
- OBJECT_OT_particletrace,
- OBJECT_OT_traceallparticles,
- OBJECT_OT_curvegrow,
- OBJECT_OT_reset,
- OBJECT_OT_fcnoise,
- OBJECT_OT_meshfollow,
- OBJECT_OT_materialChango,
- OBJECT_OT_clearColorblender
- ]
-
-def register():
- for c in classes:
- bpy.utils.register_class(c)
- bpy.types.WindowManager.curve_tracer = bpy.props.PointerProperty(type=TracerProperties)
- bpy.types.WindowManager.btrace_menu = bpy.props.PointerProperty(type=TracerPropertiesMenu, update=deselect_others)
-
-def unregister():
- for c in classes:
- bpy.utils.unregister_class(c)
- del bpy.types.WindowManager.curve_tracer
-if __name__ == "__main__":
- register()
+ try:
+ objs = context.selected_objects
+ for i in objs: # Execute on multiple selected objects
+ context.scene.objects.active = i
+ obj = context.active_object
+ obj.animation_data_clear()
+ if obj.type == 'CURVE':
+ for sp in obj.data.splines:
+ po = [p for p in sp.points] + [p for p in sp.bezier_points]
+ for p in po:
+ p.radius = 1
+
+ return{'FINISHED'}
+
+ except Exception as e:
+ error_handlers(self, "object.btreset", e,
+ "Clear animation could not be completed")
+
+ return {'CANCELLED'}
diff --git a/btrace/bTrace_props.py b/btrace/bTrace_props.py
new file mode 100644
index 00000000..bff3b88f
--- /dev/null
+++ b/btrace/bTrace_props.py
@@ -0,0 +1,951 @@
+# ##### 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 #####
+
+import bpy
+from bpy.types import (
+ Panel,
+ PropertyGroup,
+ )
+from bpy.props import (
+ FloatProperty,
+ EnumProperty,
+ IntProperty,
+ BoolProperty,
+ FloatVectorProperty,
+ )
+
+
+# Class to define properties
+class TracerProperties(PropertyGroup):
+ """Options for tools"""
+ curve_spline = EnumProperty(
+ name="Spline",
+ items=(("POLY", "Poly", "Use Poly spline type"),
+ ("NURBS", "Nurbs", "Use Nurbs spline type"),
+ ("BEZIER", "Bezier", "Use Bezier spline type")),
+ description="Choose which type of spline to use when curve is created",
+ default="BEZIER"
+ )
+ curve_handle = EnumProperty(
+ name="Handle",
+ items=(("ALIGNED", "Aligned", "Use Aligned Handle Type"),
+ ("AUTOMATIC", "Automatic", "Use Auto Handle Type"),
+ ("FREE_ALIGN", "Free Align", "Use Free Handle Type"),
+ ("VECTOR", "Vector", "Use Vector Handle Type")),
+ description="Choose which type of handle to use when curve is created",
+ default="VECTOR"
+ )
+ curve_resolution = IntProperty(
+ name="Bevel Resolution",
+ min=1, max=32,
+ default=4,
+ description="Adjust the Bevel resolution"
+ )
+ curve_depth = FloatProperty(
+ name="Bevel Depth",
+ min=0.0, max=100.0,
+ default=0.1,
+ description="Adjust the Bevel depth"
+ )
+ curve_u = IntProperty(
+ name="Resolution U",
+ min=0, max=64,
+ default=12,
+ description="Adjust the Surface resolution"
+ )
+ curve_join = BoolProperty(
+ name="Join Curves",
+ default=False,
+ description="Join all the curves after they have been created"
+ )
+ curve_smooth = BoolProperty(
+ name="Smooth",
+ default=True,
+ description="Render curve smooth"
+ )
+ # Option to Duplicate Mesh
+ object_duplicate = BoolProperty(
+ name="Apply to Copy",
+ default=False,
+ description="Apply curve to a copy of object"
+ )
+ # Distort Mesh options
+ distort_modscale = IntProperty(
+ name="Modulation Scale",
+ min=0, max=50,
+ default=2,
+ description="Add a scale to modulate the curve at random points, set to 0 to disable"
+ )
+ distort_noise = FloatProperty(
+ name="Mesh Noise",
+ min=0.0, max=50.0,
+ default=0.00,
+ description="Adjust noise added to mesh before adding curve"
+ )
+ # Particle Options
+ particle_step = IntProperty(
+ name="Step Size",
+ min=1, max=50,
+ default=5,
+ description="Sample one every this number of frames"
+ )
+ particle_auto = BoolProperty(
+ name="Auto Frame Range",
+ default=True,
+ description="Calculate Frame Range from particles life"
+ )
+ particle_f_start = IntProperty(
+ name='Start Frame',
+ min=1, max=5000,
+ default=1,
+ description='Start frame'
+ )
+ particle_f_end = IntProperty(
+ name="End Frame",
+ min=1, max=5000,
+ default=250,
+ description="End frame"
+ )
+ # F-Curve Modifier Properties
+ fcnoise_rot = BoolProperty(
+ name="Rotation",
+ default=False,
+ description="Affect Rotation"
+ )
+ fcnoise_loc = BoolProperty(
+ name="Location",
+ default=True,
+ description="Affect Location"
+ )
+ fcnoise_scale = BoolProperty(
+ name="Scale",
+ default=False,
+ description="Affect Scale"
+ )
+ fcnoise_amp = IntProperty(
+ name="Amp",
+ min=1, max=500,
+ default=5,
+ description="Adjust the amplitude"
+ )
+ fcnoise_timescale = FloatProperty(
+ name="Time Scale",
+ min=1, max=500,
+ default=50,
+ description="Adjust the time scale"
+ )
+ fcnoise_key = BoolProperty(
+ name="Add Keyframe",
+ default=True,
+ description="Keyframe is needed for tool, this adds a LocRotScale keyframe"
+ )
+ show_curve_settings = BoolProperty(
+ name="Curve Settings",
+ default=False,
+ description="Change the curve settings for the created curve"
+ )
+ material_settings = BoolProperty(
+ name="Material Settings",
+ default=False,
+ description="Change the material settings for the created curve"
+ )
+ particle_settings = BoolProperty(
+ name="Particle Settings",
+ default=False,
+ description="Show the settings for the created curve"
+ )
+ animation_settings = BoolProperty(
+ name="Animation Settings",
+ default=False,
+ description="Show the settings for the Animations"
+ )
+ distort_curve = BoolProperty(
+ name="Add Distortion",
+ default=False,
+ description="Set options to distort the final curve"
+ )
+ connect_noise = BoolProperty(
+ name="F-Curve Noise",
+ default=False,
+ description="Adds F-Curve Noise Modifier to selected objects"
+ )
+ settings_objectTrace = BoolProperty(
+ name="Object Trace Settings",
+ default=False,
+ description="Trace selected mesh object with a curve"
+ )
+ settings_objectsConnect = BoolProperty(
+ name="Objects Connect Settings",
+ default=False,
+ description="Connect objects with a curve controlled by hooks"
+ )
+ settings_objectTrace = BoolProperty(
+ name="Object Trace Settings",
+ default=False,
+ description="Trace selected mesh object with a curve"
+ )
+ respect_order = BoolProperty(
+ name="Order",
+ default=False,
+ description="Remember order objects were selected"
+ )
+ settings_particleTrace = BoolProperty(
+ name="Particle Trace Settings",
+ default=False,
+ description="Trace particle path with a curve"
+ )
+ settings_particleConnect = BoolProperty(
+ name="Particle Connect Settings",
+ default=False,
+ description="Connect particles with a curves and animated over particle lifetime"
+ )
+ settings_growCurve = BoolProperty(
+ name="Grow Curve Settings",
+ default=False,
+ description="Animate curve bevel over time by keyframing points radius"
+ )
+ settings_fcurve = BoolProperty(
+ name="F-Curve Settings",
+ default=False,
+ description="F-Curve Settings"
+ )
+ settings_toggle = BoolProperty(
+ name="Settings",
+ default=False,
+ description="Toggle Settings"
+ )
+ # Animation Options
+ anim_auto = BoolProperty(
+ name="Auto Frame Range",
+ default=True,
+ description="Automatically calculate Frame Range"
+ )
+ anim_f_start = IntProperty(
+ name="Start",
+ min=1, max=2500,
+ default=1,
+ description="Start frame / Hidden object"
+ )
+ anim_length = IntProperty(
+ name="Duration",
+ min=1,
+ soft_max=1000, max=2500,
+ default=100,
+ description="Animation Length"
+ )
+ anim_f_fade = IntProperty(
+ name="Fade After",
+ min=0,
+ soft_max=250, max=2500,
+ default=10,
+ description="Fade after this frames / Zero means no fade"
+ )
+ anim_delay = IntProperty(
+ name="Grow",
+ min=0, max=50,
+ default=5,
+ description="Frames it takes a point to grow"
+ )
+ anim_tails = BoolProperty(
+ name='Tails on endpoints',
+ default=True,
+ description='Set radius to zero for open splines endpoints'
+ )
+ anim_keepr = BoolProperty(
+ name="Keep Radius",
+ default=True,
+ description="Try to keep radius data from original curve"
+ )
+ animate = BoolProperty(
+ name="Animate Result",
+ default=False,
+ description="Animate the final curve objects"
+ )
+ # Convert to Curve options
+ convert_conti = BoolProperty(
+ name="Continuous",
+ default=True,
+ description="Create a continuous curve using verts from mesh"
+ )
+ convert_everyedge = BoolProperty(
+ name="Every Edge",
+ default=False,
+ description="Create a curve from all verts in a mesh"
+ )
+ convert_edgetype = EnumProperty(
+ name="Edge Type for Curves",
+ items=(("CONTI", "Continuous", "Create a continuous curve using verts from mesh"),
+ ("EDGEALL", "All Edges", "Create a curve from every edge in a mesh")),
+ description="Choose which type of spline to use when curve is created",
+ default="CONTI"
+ )
+ convert_joinbefore = BoolProperty(
+ name="Join objects before convert",
+ default=False,
+ description="Join all selected mesh to one object before converting to mesh"
+ )
+ # Mesh Follow Options
+ fol_edge_select = BoolProperty(
+ name="Edge",
+ default=False,
+ description="Grow from edges"
+ )
+ fol_vert_select = BoolProperty(
+ name="Vertex",
+ default=False,
+ description="Grow from verts"
+ )
+ fol_face_select = BoolProperty(
+ name="Face",
+ default=True,
+ description="Grow from faces"
+ )
+ fol_mesh_type = EnumProperty(
+ name="Mesh type",
+ default="VERTS",
+ description="Mesh feature to draw cruves from",
+ items=(("VERTS", "Verts", "Draw from Verts"),
+ ("EDGES", "Edges", "Draw from Edges"),
+ ("FACES", "Faces", "Draw from Faces"),
+ ("OBJECT", "Object", "Draw from Object origin"))
+ )
+ fol_start_frame = IntProperty(
+ name="Start Frame",
+ min=1, max=2500,
+ default=1,
+ description="Start frame for range to trace"
+ )
+ fol_end_frame = IntProperty(
+ name="End Frame",
+ min=1, max=2500,
+ default=250,
+ description="End frame for range to trace"
+ )
+ fol_perc_verts = FloatProperty(
+ name="Reduce selection by",
+ min=0.001, max=1.000,
+ default=0.5,
+ description="percentage of total verts to trace"
+ )
+ fol_sel_option = EnumProperty(
+ name="Selection type",
+ description="Choose which objects to follow",
+ default="RANDOM",
+ items=(("RANDOM", "Random", "Follow Random items"),
+ ("CUSTOM", "Custom Select", "Follow selected items"),
+ ("ALL", "All", "Follow all items"))
+ )
+ trace_mat_color = FloatVectorProperty(
+ name="Material Color",
+ description="Choose material color",
+ min=0, max=1,
+ default=(0.0, 0.3, 0.6),
+ subtype="COLOR"
+ )
+ trace_mat_random = BoolProperty(
+ name="Random Color",
+ default=False,
+ description='Make the material colors random'
+ )
+ # Material custom Properties properties
+ mat_simple_adv_toggle = EnumProperty(
+ name="Material Options",
+ items=(("SIMPLE", "Simple", "Show Simple Material Options"),
+ ("ADVANCED", "Advanced", "Show Advanced Material Options")),
+ description="Choose which Material Options to show",
+ default="SIMPLE"
+ )
+ mat_run_color_blender = BoolProperty(
+ name="Run Color Blender",
+ default=False,
+ description="Generate colors from a color scheme"
+ )
+ mmColors = EnumProperty(
+ items=(("RANDOM", "Random", "Use random colors"),
+ ("CUSTOM", "Custom", "Use custom colors"),
+ ("BW", "Black/White", "Use Black and White"),
+ ("BRIGHT", "Bright Colors", "Use Bright colors"),
+ ("EARTH", "Earth", "Use Earth colors"),
+ ("GREENBLUE", "Green to Blue", "Use Green to Blue colors")),
+ description="Choose which type of colors the materials uses",
+ default="BRIGHT",
+ name="Define a color palette"
+ )
+ # Custom property for how many keyframes to skip
+ mmSkip = IntProperty(
+ name="frames",
+ min=1, max=500,
+ default=20,
+ description="Number of frames between each keyframes"
+ )
+ # Custom property to enable/disable random order for the
+ mmBoolRandom = BoolProperty(
+ name="Random Order",
+ default=False,
+ description="Randomize the order of the colors"
+ )
+ # Custom Color properties
+ mmColor1 = FloatVectorProperty(
+ min=0, max=1,
+ default=(0.8, 0.8, 0.8),
+ description="Custom Color 1", subtype="COLOR"
+ )
+ mmColor2 = FloatVectorProperty(
+ min=0, max=1,
+ default=(0.8, 0.8, 0.3),
+ description="Custom Color 2",
+ subtype="COLOR"
+ )
+ mmColor3 = FloatVectorProperty(
+ min=0, max=1,
+ default=(0.8, 0.5, 0.6),
+ description="Custom Color 3",
+ subtype="COLOR"
+ )
+ mmColor4 = FloatVectorProperty(
+ min=0, max=1,
+ default=(0.2, 0.8, 0.289),
+ description="Custom Color 4",
+ subtype="COLOR"
+ )
+ mmColor5 = FloatVectorProperty(
+ min=0, max=1,
+ default=(1.0, 0.348, 0.8),
+ description="Custom Color 5",
+ subtype="COLOR"
+ )
+ mmColor6 = FloatVectorProperty(
+ min=0, max=1,
+ default=(0.4, 0.67, 0.8),
+ description="Custom Color 6",
+ subtype="COLOR"
+ )
+ mmColor7 = FloatVectorProperty(
+ min=0, max=1,
+ default=(0.66, 0.88, 0.8),
+ description="Custom Color 7",
+ subtype="COLOR"
+ )
+ mmColor8 = FloatVectorProperty(
+ min=0, max=1,
+ default=(0.8, 0.38, 0.22),
+ description="Custom Color 8",
+ subtype="COLOR"
+ )
+ # BW Color properties
+ bwColor1 = FloatVectorProperty(
+ min=0, max=1,
+ default=(0.0, 0.0, 0.0),
+ description="Black/White Color 1",
+ subtype="COLOR"
+ )
+ bwColor2 = FloatVectorProperty(
+ min=0, max=1,
+ default=(1.0, 1.0, 1.0),
+ description="Black/White Color 2",
+ subtype="COLOR"
+ )
+ # Bright Color properties
+ brightColor1 = FloatVectorProperty(
+ min=0, max=1,
+ default=(1.0, 0.0, 0.75),
+ description="Bright Color 1",
+ subtype="COLOR"
+ )
+ brightColor2 = FloatVectorProperty(
+ min=0, max=1,
+ default=(0.0, 1.0, 1.0),
+ description="Bright Color 2",
+ subtype="COLOR"
+ )
+ brightColor3 = FloatVectorProperty(
+ min=0, max=1,
+ default=(0.0, 1.0, 0.0),
+ description="Bright Color 3",
+ subtype="COLOR"
+ )
+ brightColor4 = FloatVectorProperty(
+ min=0, max=1,
+ default=(1.0, 1.0, 0.0),
+ description="Bright Color 4", subtype="COLOR"
+ )
+ # Earth Color Properties
+ earthColor1 = FloatVectorProperty(
+ min=0, max=1,
+ default=(0.068, 0.019, 0.014),
+ description="Earth Color 1",
+ subtype="COLOR"
+ )
+ earthColor2 = FloatVectorProperty(
+ min=0, max=1,
+ default=(0.089, 0.060, 0.047),
+ description="Earth Color 2",
+ subtype="COLOR"
+ )
+ earthColor3 = FloatVectorProperty(
+ min=0, max=1,
+ default=(0.188, 0.168, 0.066),
+ description="Earth Color 3",
+ subtype="COLOR"
+ )
+ earthColor4 = FloatVectorProperty(
+ min=0, max=1,
+ default=(0.445, 0.296, 0.065),
+ description="Earth Color 4",
+ subtype="COLOR"
+ )
+ earthColor5 = FloatVectorProperty(
+ min=0, max=1,
+ default=(0.745, 0.332, 0.065),
+ description="Earth Color 5",
+ subtype="COLOR"
+ )
+ # Green to Blue Color properties
+ greenblueColor1 = FloatVectorProperty(
+ min=0, max=1,
+ default=(0.296, 0.445, 0.074),
+ description="Green/Blue Color 1",
+ subtype="COLOR"
+ )
+ greenblueColor2 = FloatVectorProperty(
+ min=0, max=1,
+ default=(0.651, 1.0, 0.223),
+ description="Green/Blue Color 2",
+ subtype="COLOR"
+ )
+ greenblueColor3 = FloatVectorProperty(
+ min=0, max=1,
+ default=(0.037, 0.047, 0.084),
+ description="Green/Blue Color 3",
+ subtype="COLOR"
+ )
+
+ # Toolbar show/hide booleans for tool options
+ btrace_menu_items = [
+ ('tool_help', "Help",
+ "Pick one of the options below", "INFO", 0),
+ ('tool_objectTrace', "Object Trace",
+ "Trace selected mesh object with a curve", "FORCE_MAGNETIC", 1),
+ ('tool_objectsConnect', "Objects Connect",
+ "Connect objects with a curve controlled by hooks", "OUTLINER_OB_EMPTY", 2),
+ ('tool_meshFollow', "Mesh Follow",
+ "Follow selection items on animated mesh object", "DRIVER", 3),
+ ('tool_handwrite', "Handwriting",
+ "Create and Animate curve using the grease pencil", "BRUSH_DATA", 4),
+ ('tool_particleTrace', "Particle Trace",
+ "Trace particle path with a curve", "PARTICLES", 5),
+ ('tool_particleConnect', "Particle Connect",
+ "Connect particles with a curves and animated over particle lifetime", "MOD_PARTICLES", 6),
+ ('tool_growCurve', "Grow Curve",
+ "Animate curve bevel over time by keyframing points radius", "META_BALL", 7),
+ ('tool_fcurve', "F-Curve Noise",
+ "Add F-Curve noise to selected objects", "RNDCURVE", 8),
+ ('tool_colorblender', "Color Blender",
+ "Pick the color of the created curves", "COLOR", 9),
+ ]
+ btrace_toolmenu = EnumProperty(
+ name="Tools",
+ items=btrace_menu_items,
+ description="",
+ default='tool_help'
+ )
+
+
+# Draw Brush panel in Toolbar
+class addTracerObjectPanel(Panel):
+ bl_label = "Btrace"
+ bl_space_type = "VIEW_3D"
+ bl_region_type = "TOOLS"
+ bl_context = "objectmode"
+ bl_category = "Create"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ def draw(self, context):
+ layout = self.layout
+ Btrace = context.window_manager.curve_tracer
+ addon_prefs = context.user_preferences.addons["btrace"].preferences
+ switch_expand = addon_prefs.expand_enum
+ obj = context.object
+
+ # Color Blender Panel options
+ def color_blender():
+ # Buttons for Color Blender
+ row = box.row()
+ row.label("Color palette")
+ row.prop(Btrace, "mmColors", text="")
+
+ # Show Custom Colors if selected
+ if Btrace.mmColors == 'CUSTOM':
+ row = box.row(align=True)
+ for i in range(1, 9):
+ row.prop(Btrace, "mmColor" + str(i), text="")
+ # Show Earth Colors
+ elif Btrace.mmColors == 'BW':
+ row = box.row(align=True)
+ row.prop(Btrace, "bwColor1", text="")
+ row.prop(Btrace, "bwColor2", text="")
+ # Show Earth Colors
+ elif Btrace.mmColors == 'BRIGHT':
+ row = box.row(align=True)
+ for i in range(1, 5):
+ row.prop(Btrace, "brightColor" + str(i), text="")
+ # Show Earth Colors
+ elif Btrace.mmColors == 'EARTH':
+ row = box.row(align=True)
+ for i in range(1, 6):
+ row.prop(Btrace, "earthColor" + str(i), text="")
+ # Show Earth Colors
+ elif Btrace.mmColors == 'GREENBLUE':
+ row = box.row(align=True)
+ for i in range(1, 4):
+ row.prop(Btrace, "greenblueColor" + str(i), text="")
+ elif Btrace.mmColors == 'RANDOM':
+ row = box.row()
+
+ # Curve noise settings
+ def curve_noise():
+ row = box.row()
+ row.label(text="F-Curve Noise", icon='RNDCURVE')
+ row = box.row(align=True)
+ row.prop(Btrace, "fcnoise_rot", toggle=True)
+ row.prop(Btrace, "fcnoise_loc", toggle=True)
+ row.prop(Btrace, "fcnoise_scale", toggle=True)
+
+ col = box.column(align=True)
+ col.prop(Btrace, "fcnoise_amp")
+ col.prop(Btrace, "fcnoise_timescale")
+ box.prop(Btrace, "fcnoise_key")
+
+ # Curve Panel options
+ def curve_settings():
+ # Button for curve options
+ row = self.layout.row()
+ row = box.row(align=True)
+
+ row.prop(Btrace, "show_curve_settings",
+ icon='CURVE_BEZCURVE', text="Curve Settings")
+ row.prop(Btrace, "material_settings",
+ icon='MATERIAL_DATA', text="Material Settings")
+
+ if Btrace.material_settings:
+ row = box.row()
+ row.label(text="Material Settings", icon='COLOR')
+ row = box.row()
+ row.prop(Btrace, "trace_mat_random")
+ if not Btrace.trace_mat_random:
+ row = box.row()
+ row.prop(Btrace, "trace_mat_color", text="")
+ else:
+ row.prop(Btrace, "mat_run_color_blender")
+ if Btrace.mat_run_color_blender:
+ row = box.row()
+ row.operator("object.colorblenderclear",
+ text="Reset Material Keyframes",
+ icon="KEY_DEHLT")
+ row.prop(Btrace, "mmSkip", text="Keyframe every")
+ color_blender()
+ row = box.row()
+
+ if Btrace.show_curve_settings:
+ # selected curve options
+ if len(context.selected_objects) > 0 and obj.type == 'CURVE':
+ col = box.column(align=True)
+ col.label(text="Edit Curves for:", icon='IPO_BEZIER')
+ col.separator()
+ col.label(text="Selected Curve Bevel Options")
+ row = col.row(align=True)
+ row.prop(obj.data, "bevel_depth", text="Depth")
+ row.prop(obj.data, "bevel_resolution", text="Resolution")
+ row = col.row(align=True)
+ row.prop(obj.data, "resolution_u")
+ else: # For new curve
+ box.label(text="New Curve Settings", icon='CURVE_BEZCURVE')
+ box.prop(Btrace, "curve_spline")
+ box.prop(Btrace, "curve_handle")
+ box.label(text="Bevel Options")
+ col = box.column(align=True)
+ row = col.row(align=True)
+ row.prop(Btrace, "curve_depth", text="Depth")
+ row.prop(Btrace, "curve_resolution", text="Resolution")
+ row = col.row(align=True)
+ row.prop(Btrace, "curve_u")
+
+ # Grow Animation Panel options
+ def add_grow():
+ # Button for grow animation option
+ row = box.row()
+ row.label(text="Animate Final Curve", icon="SPACE2")
+ row = box.row()
+ row.prop(Btrace, "animate", text="Add Grow Curve Animation", icon="META_BALL")
+ box.separator()
+ if Btrace.animate:
+ box.label(text="Frame Animation Settings:", icon="META_BALL")
+ col = box.column(align=True)
+ col.prop(Btrace, "anim_auto")
+ if not Btrace.anim_auto:
+ row = col.row(align=True)
+ row.prop(Btrace, "anim_f_start")
+ row.prop(Btrace, "anim_length")
+ row = col.row(align=True)
+ row.prop(Btrace, "anim_delay")
+ row.prop(Btrace, "anim_f_fade")
+
+ box.label(text="Additional Settings")
+ row = box.row()
+ row.prop(Btrace, "anim_tails")
+ row.prop(Btrace, "anim_keepr")
+
+ # Start Btrace Panel
+ if switch_expand == 'list':
+ layout.label(text="Available Tools:", icon="COLLAPSEMENU")
+ col = layout.column(align=True)
+ col.prop(Btrace, "btrace_toolmenu", text="")
+ elif switch_expand == 'col':
+ col = layout.column(align=True)
+ col.prop(Btrace, "btrace_toolmenu", expand=True)
+ elif switch_expand == 'row':
+ row = layout.row(align=True)
+ row.alignment = 'CENTER'
+ row.prop(Btrace, "btrace_toolmenu", text="", expand=True)
+
+ # Start Object Tools
+ sel = context.selected_objects
+
+ # Default option (can be expanded into help)
+ if Btrace.btrace_toolmenu == 'tool_help':
+ row = layout.row()
+ row.label("Pick an option", icon="HELP")
+
+ # Object Trace
+ elif Btrace.btrace_toolmenu == 'tool_objectTrace':
+ row = layout.row()
+ row.label(text=" Trace Tool:", icon="FORCE_CURVE")
+ box = self.layout.box()
+ row = box.row()
+ row.label(text="Object Trace", icon="FORCE_MAGNETIC")
+ row.operator("object.btobjecttrace", text="Run!", icon="PLAY")
+ row = box.row()
+ row.prop(Btrace, "settings_toggle", icon="MODIFIER", text="Settings")
+ myselected = "Selected %d" % len(context.selected_objects)
+ row.label(text=myselected)
+ if Btrace.settings_toggle:
+ box.label(text="Edge Type for Curves:", icon="IPO_CONSTANT")
+ row = box.row(align=True)
+ row.prop(Btrace, "convert_edgetype", text="")
+ box.prop(Btrace, "object_duplicate")
+ if len(sel) > 1:
+ box.prop(Btrace, "convert_joinbefore")
+ else:
+ Btrace.convert_joinbefore = False
+ row = box.row()
+ row.prop(Btrace, "distort_curve")
+ if Btrace.distort_curve:
+ col = box.column(align=True)
+ col.prop(Btrace, "distort_modscale")
+ col.prop(Btrace, "distort_noise")
+ row = box.row()
+ curve_settings() # Show Curve/material settings
+ add_grow() # Grow settings here
+
+ # Objects Connect
+ elif Btrace.btrace_toolmenu == 'tool_objectsConnect':
+ row = layout.row()
+ row.label(text=" Trace Tool:", icon="FORCE_CURVE")
+ box = self.layout.box()
+ row = box.row()
+ row.label(text="Objects Connect", icon="OUTLINER_OB_EMPTY")
+ row.operator("object.btobjectsconnect", text="Run!", icon="PLAY")
+ row = box.row()
+ row.prop(Btrace, "settings_toggle", icon='MODIFIER', text='Settings')
+ row.label(text="")
+ if Btrace.settings_toggle:
+ row = box.row()
+ row.prop(Btrace, "respect_order", text="Selection Options")
+ if Btrace.respect_order:
+ box.operator("object.select_order",
+ text="Click to start order selection",
+ icon='UV_SYNC_SELECT')
+ row = box.row()
+ row.prop(Btrace, "connect_noise", text="Add F-Curve Noise")
+ if Btrace.connect_noise:
+ curve_noise() # Show Curve Noise settings
+
+ curve_settings() # Show Curve/material settings
+ add_grow() # Grow settings here
+
+ # Mesh Follow
+ elif Btrace.btrace_toolmenu == 'tool_meshFollow':
+ row = layout.row()
+ row.label(text=" Trace Tool:", icon="FORCE_CURVE")
+ box = self.layout.box()
+ row = box.row()
+ row.label(text="Mesh Follow", icon="DRIVER")
+ row.operator("object.btmeshfollow", text="Run!", icon="PLAY")
+ row = box.row()
+ if Btrace.fol_mesh_type == 'OBJECT':
+ a, b = "Trace Object", "SNAP_VOLUME"
+ if Btrace.fol_mesh_type == 'VERTS':
+ a, b = "Trace Verts", "SNAP_VERTEX"
+ if Btrace.fol_mesh_type == 'EDGES':
+ a, b = "Trace Edges", "SNAP_EDGE"
+ if Btrace.fol_mesh_type == 'FACES':
+ a, b = "Trace Faces", "SNAP_FACE"
+ row.prop(Btrace, "settings_toggle", icon='MODIFIER', text='Settings')
+ row.label(text=a, icon=b)
+ if Btrace.settings_toggle:
+ col = box.column(align=True)
+ row = col.row(align=True)
+ row.prop(Btrace, "fol_mesh_type", expand=True)
+ row = col.row(align=True)
+ if Btrace.fol_mesh_type != 'OBJECT':
+ row.prop(Btrace, "fol_sel_option", expand=True)
+ row = box.row()
+ if Btrace.fol_sel_option == 'RANDOM':
+ row.label("Random Select of Total")
+ row.prop(Btrace, "fol_perc_verts", text="%")
+ if Btrace.fol_sel_option == 'CUSTOM':
+ row.label("Choose selection in Edit Mode")
+ if Btrace.fol_sel_option == 'ALL':
+ row.label("Select All items")
+ col = box.column(align=True)
+ col.label("Time Options", icon="TIME")
+ col.prop(Btrace, "particle_step")
+ row = col.row(align=True)
+ row.prop(Btrace, "fol_start_frame")
+ row.prop(Btrace, "fol_end_frame")
+ curve_settings() # Show Curve/material settings
+ add_grow() # Grow settings here
+
+ # Handwriting Tools
+ elif Btrace.btrace_toolmenu == 'tool_handwrite':
+ row = layout.row()
+ row.label(text=" Trace Tool:", icon="FORCE_CURVE")
+ box = self.layout.box()
+ row = box.row()
+ row.label(text='Handwriting', icon='BRUSH_DATA')
+ row.operator("curve.btwriting", text="Run!", icon='PLAY')
+ row = box.row()
+ row = box.row()
+ row.label(text='Grease Pencil Writing Tools')
+ col = box.column(align=True)
+ row = col.row(align=True)
+ row.operator("gpencil.draw", text="Draw", icon='BRUSH_DATA').mode = 'DRAW'
+ row.operator("gpencil.draw", text="Poly", icon='VPAINT_HLT').mode = 'DRAW_POLY'
+ row = col.row(align=True)
+ row.operator("gpencil.draw", text="Line", icon='ZOOMOUT').mode = 'DRAW_STRAIGHT'
+ row.operator("gpencil.draw", text="Erase", icon='TPAINT_HLT').mode = 'ERASER'
+ row = box.row()
+ row.operator("gpencil.data_unlink", text="Delete Grease Pencil Layer", icon="CANCEL")
+ row = box.row()
+ curve_settings() # Show Curve/material settings
+ add_grow() # Grow settings here
+
+ # Particle Trace
+ elif Btrace.btrace_toolmenu == 'tool_particleTrace':
+ row = layout.row()
+ row.label(text=" Trace Tool:", icon="FORCE_CURVE")
+ box = self.layout.box()
+ row = box.row()
+ row.label(text="Particle Trace", icon="PARTICLES")
+ row.operator("particles.particletrace", text="Run!", icon="PLAY")
+ row = box.row()
+ row.prop(Btrace, "settings_toggle", icon='MODIFIER', text='Settings')
+ row.label(text="")
+ if Btrace.settings_toggle:
+ box.prop(Btrace, "particle_step")
+ row = box.row()
+ row.prop(Btrace, "curve_join")
+ curve_settings() # Show Curve/material settings
+ add_grow() # Grow settings here
+
+ # Connect Particles
+ elif Btrace.btrace_toolmenu == 'tool_particleConnect':
+ row = layout.row()
+ row.label(text=" Trace Tool:", icon="FORCE_CURVE")
+ box = self.layout.box()
+ row = box.row()
+ row.label(text='Particle Connect', icon='MOD_PARTICLES')
+ row.operator("particles.connect", icon="PLAY", text='Run!')
+ row = box.row()
+ row.prop(Btrace, "settings_toggle", icon='MODIFIER', text='Settings')
+ row.label(text="")
+ if Btrace.settings_toggle:
+ box.prop(Btrace, "particle_step")
+ row = box.row()
+ row.prop(Btrace, 'particle_auto')
+ if not Btrace.particle_auto:
+ row = box.row(align=True)
+ row.prop(Btrace, 'particle_f_start')
+ row.prop(Btrace, 'particle_f_end')
+ curve_settings() # Show Curve/material settings
+ add_grow() # Grow settings here
+
+ # Grow Animation
+ elif Btrace.btrace_toolmenu == 'tool_growCurve':
+ row = layout.row()
+ row.label(text=" Curve Tool:", icon="OUTLINER_OB_CURVE")
+ box = self.layout.box()
+ row = box.row()
+ row.label(text="Grow Curve", icon="META_BALL")
+ row.operator("curve.btgrow", text="Run!", icon="PLAY")
+ row = box.row()
+ row.prop(Btrace, "settings_toggle", icon="MODIFIER", text="Settings")
+ row.operator("object.btreset", icon="KEY_DEHLT")
+ if Btrace.settings_toggle:
+ box.label(text="Frame Animation Settings:")
+ col = box.column(align=True)
+ col.prop(Btrace, "anim_auto")
+ if not Btrace.anim_auto:
+ row = col.row(align=True)
+ row.prop(Btrace, "anim_f_start")
+ row.prop(Btrace, "anim_length")
+ row = col.row(align=True)
+ row.prop(Btrace, "anim_delay")
+ row.prop(Btrace, "anim_f_fade")
+
+ box.label(text="Additional Settings")
+ row = box.row()
+ row.prop(Btrace, "anim_tails")
+ row.prop(Btrace, "anim_keepr")
+
+ # F-Curve Noise Curve
+ elif Btrace.btrace_toolmenu == 'tool_fcurve':
+ row = layout.row()
+ row.label(text=" Curve Tool:", icon="OUTLINER_OB_CURVE")
+ box = self.layout.box()
+ row = box.row()
+ row.label(text="F-Curve Noise", icon='RNDCURVE')
+ row.operator("object.btfcnoise", icon='PLAY', text="Run!")
+ row = box.row()
+ row.prop(Btrace, "settings_toggle", icon='MODIFIER', text='Settings')
+ row.operator("object.btreset", icon='KEY_DEHLT')
+ if Btrace.settings_toggle:
+ curve_noise()
+
+ # Color Blender
+ elif Btrace.btrace_toolmenu == 'tool_colorblender':
+ row = layout.row()
+ row.label(text=" Curve/Object Tool:", icon="OUTLINER_OB_CURVE")
+ box = self.layout.box()
+ row = box.row()
+ row.label(text="Color Blender", icon="COLOR")
+ row.operator("object.colorblender", icon='PLAY', text="Run!")
+ row = box.row()
+ row.operator("object.colorblenderclear", text="Reset Keyframes", icon="KEY_DEHLT")
+ row.prop(Btrace, "mmSkip", text="Keyframe every")
+ color_blender()