Skip to content
Snippets Groups Projects
Commit e882de0d authored by Andrew Hale's avatar Andrew Hale
Browse files

Moved Sapling to Trunk

[[Split portion of a mixed commit.]]
parent dcb97c6b
No related branches found
No related tags found
No related merge requests found
#====================== 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 ========================
bl_info = {
"name": "Sapling",
"author": "Andrew Hale (TrumanBlending)",
"version": (0, 2, 2),
"blender": (2, 5, 8),
"api": 37702,
"location": "View3D > Add > Curve",
"description": ("Adds a parametric tree. The method is presented by "
"Jason Weber & Joseph Penn in their paper 'Creation and Rendering of "
"Realistic Trees'."),
"warning": "", # used for warning icon and text in addons panel
"wiki_url": "",
"tracker_url": "",
"category": "Add Curve"}
if "bpy" in locals():
import imp
imp.reload(utils)
else:
from add_curve_sapling import utils
import bpy
import time
import os
#from utils import *
from mathutils import *
from math import pi, sin, degrees, radians, atan2, copysign
from random import random, uniform, seed, choice, getstate, setstate
from bpy.props import *
from add_curve_sapling.utils import *
#global splitError
useSet = False
shapeList = [('0', 'Conical (0)', 'Shape = 0'),
('1', 'Spherical (1)', 'Shape = 1'),
('2', 'Hemispherical (2)', 'Shape = 2'),
('3', 'Cylindrical (3)', 'Shape = 3'),
('4', 'Tapered Cylindrical (4)', 'Shape = 4'),
('5', 'Flame (5)', 'Shape = 5'),
('6', 'Inverse Conical (6)', 'Shape = 6'),
('7', 'Tend Flame (7)', 'Shape = 7')]
handleList = [('0', 'Auto', 'Auto'),
('1', 'Vector', 'Vector')]
settings = [('0', 'Geometry', 'Geometry'),
('1', 'Branch Splitting', 'Branch Splitting'),
('2', 'Branch Growth', 'Branch Growth'),
('3', 'Pruning', 'Pruning'),
('4', 'Leaves', 'Leaves'),
('5', 'Armature', 'Armature')]
def getPresetpath():
'''Support user defined scripts directory
Find the first ocurrence of add_curve_sapling/presets in possible script paths
and return it as preset path'''
presetpath = ""
for p in bpy.utils.script_paths():
presetpath = os.path.join(p, 'addons', 'add_curve_sapling', 'presets')
if os.path.exists(presetpath):
break
return presetpath
class ExportData(bpy.types.Operator):
'''This operator handles writing presets to file'''
bl_idname = 'sapling.exportdata'
bl_label = 'Export Preset'
data = StringProperty()
def execute(self, context):
# Unpack some data from the input
data, filename = eval(self.data)
try:
# Check whether the file exists by trying to open it.
f = open(os.path.join(getPresetpath(), filename + '.py'), 'r')
f.close()
# If it exists then report an error
self.report({'ERROR_INVALID_INPUT'}, 'Preset Already Exists')
return {'CANCELLED'}
except IOError:
if data:
# If it doesn't exist, create the file with the required data
f = open(os.path.join(getPresetpath(), filename + '.py'), 'w')
f.write(data)
f.close()
return {'FINISHED'}
else:
return {'CANCELLED'}
class ImportData(bpy.types.Operator):
'''This operator handles importing existing presets'''
bl_idname = 'sapling.importdata'
bl_label = 'Import Preset'
filename = StringProperty()
def execute(self, context):
# Make sure the operator knows about the global variables
global settings, useSet
# Read the preset data into the global settings
f = open(os.path.join(getPresetpath(), self.filename), 'r')
settings = f.readline()
f.close()
#print(settings)
settings = eval(settings)
# Set the flag to use the settings
useSet = True
return {'FINISHED'}
class PresetMenu(bpy.types.Menu):
'''Create the preset menu by finding all preset files
in the preset directory
'''
bl_idname = "sapling.presetmenu"
bl_label = "Presets"
def draw(self, context):
# Get all the sapling presets
presets = [a for a in os.listdir(getPresetpath()) if a[-3:] == '.py']
layout = self.layout
# Append all to the menu
for p in presets:
layout.operator("sapling.importdata", text=p[:-3]).filename = p
class AddTree(bpy.types.Operator):
bl_idname = "curve.tree_add"
bl_label = "Sapling"
bl_options = {'REGISTER', 'UNDO'}
chooseSet = EnumProperty(name='Settings',
description='Choose the settings to modify',
items=settings,
default='0')
bevel = BoolProperty(name='Bevel',
description='Whether the curve is bevelled',
default=False)
prune = BoolProperty(name='Prune',
description='Whether the tree is pruned',
default=False)
showLeaves = BoolProperty(name='Show Leaves',
description='Whether the leaves are shown',
default=False)
useArm = BoolProperty(name='Use Armature',
description='Whether the armature is generated',
default=False)
seed = IntProperty(name='Random Seed',
description='The seed of the random number generator',
default=0)
handleType = IntProperty(name='Handle Type',
description='The type of curve handles',
min=0,
max=1,
default=0)
levels = IntProperty(name='Levels',
description='Number of recursive branches (Levels)',
min=1,
max=6,
default=3)
length = FloatVectorProperty(name='Length',
description='The relative lengths of each branch level (nLength)',
min=0.0,
default=[1, 0.3, 0.6, 0.45],
size=4)
lengthV = FloatVectorProperty(name='Length Variation',
description='The relative length variations of each level (nLengthV)',
min=0.0,
default=[0, 0, 0, 0],
size=4)
branches = IntVectorProperty(name='Branches',
description='The number of branches grown at each level (nBranches)',
min=0,
default=[50, 30, 10, 10],
size=4)
curveRes = IntVectorProperty(name='Curve Resolution',
description='The number of segments on each branch (nCurveRes)',
min=1,
default=[3, 5, 3, 1],
size=4)
curve = FloatVectorProperty(name='Curvature',
description='The angle of the end of the branch (nCurve)',
default=[0, -40, -40, 0],
size=4)
curveV = FloatVectorProperty(name='Curvature Variation',
description='Variation of the curvature (nCurveV)',
default=[20, 50, 75, 0],
size=4)
curveBack = FloatVectorProperty(name='Back Curvature',
description='Curvature for the second half of a branch (nCurveBack)',
default=[0, 0, 0, 0],
size=4)
baseSplits = IntProperty(name='Base Splits',
description='Number of trunk splits at its base (nBaseSplits)',
min=0,
default=0)
segSplits = FloatVectorProperty(name='Segment Splits',
description='Number of splits per segment (nSegSplits)',
min=0,
default=[0, 0, 0, 0],
size=4)
splitAngle = FloatVectorProperty(name='Split Angle',
description='Angle of branch splitting (nSplitAngle)',
default=[0, 0, 0, 0],
size=4)
splitAngleV = FloatVectorProperty(name='Split Angle Variation',
description='Variation in the split angle (nSplitAngleV)',
default=[0, 0, 0, 0],
size=4)
scale = FloatProperty(name='Scale',
description='The tree scale (Scale)',
min=0.0,
default=13.0)
scaleV = FloatProperty(name='Scale Variation',
description='The variation in the tree scale (ScaleV)',
default=3.0)
attractUp = FloatProperty(name='Vertical Attraction',
description='Branch upward attraction',
default=0.0)
shape = EnumProperty(name='Shape',
description='The overall shape of the tree (Shape)',
items=shapeList,
default='7')
baseSize = FloatProperty(name='Base Size',
description='Fraction of tree height with no branches (BaseSize)',
min=0.0,
max=1.0,
default=0.4)
ratio = FloatProperty(name='Ratio',
description='Base radius size (Ratio)',
min=0.0,
default=0.015)
taper = FloatVectorProperty(name='Taper',
description='The fraction of tapering on each branch (nTaper)',
min=0.0,
max=1.0,
default=[1, 1, 1, 1],
size=4)
ratioPower = FloatProperty(name='Branch Radius Ratio',
description=('Power which defines the radius of a branch compared to '
'the radius of the branch it grew from (RatioPower)'),
min=0.0,
default=1.2)
downAngle = FloatVectorProperty(name='Down Angle',
description=('The angle between a new branch and the one it grew '
'from (nDownAngle)'),
default=[90, 60, 45, 45],
size=4)
downAngleV = FloatVectorProperty(name='Down Angle Variation',
description='Variation in the down angle (nDownAngleV)',
default=[0, -50, 10, 10],
size=4)
rotate = FloatVectorProperty(name='Rotate Angle',
description=('The angle of a new branch around the one it grew from '
'(nRotate)'),
default=[140, 140, 140, 77],
size=4)
rotateV = FloatVectorProperty(name='Rotate Angle Variation',
description='Variation in the rotate angle (nRotateV)',
default=[0, 0, 0, 0],
size=4)
scale0 = FloatProperty(name='Radius Scale',
description='The scale of the trunk radius (0Scale)',
min=0.0,
default=1.0)
scaleV0 = FloatProperty(name='Radius Scale Variation',
description='Variation in the radius scale (0ScaleV)',
default=0.2)
pruneWidth = FloatProperty(name='Prune Width',
description='The width of the envelope (PruneWidth)',
min=0.0,
default=0.4)
pruneWidthPeak = FloatProperty(name='Prune Width Peak',
description=('Fraction of envelope height where the maximum width '
'occurs (PruneWidthPeak)'),
min=0.0,
default=0.6)
prunePowerHigh = FloatProperty(name='Prune Power High',
description=('Power which determines the shape of the upper portion '
'of the envelope (PrunePowerHigh)'),
default=0.5)
prunePowerLow = FloatProperty(name='Prune Power Low',
description=('Power which determines the shape of the lower portion '
'of the envelope (PrunePowerLow)'),
default=0.001)
pruneRatio = FloatProperty(name='Prune Ratio',
description='Proportion of pruned length (PruneRatio)',
min=0.0,
max=1.0,
default=1.0)
leaves = IntProperty(name='Leaves',
description='Maximum number of leaves per branch (Leaves)',
default=25)
leafScale = FloatProperty(name='Leaf Scale',
description='The scaling applied to the whole leaf (LeafScale)',
min=0.0,
default=0.17)
leafScaleX = FloatProperty(name='Leaf Scale X',
description=('The scaling applied to the x direction of the leaf '
'(LeafScaleX)'),
min=0.0,
default=1.0)
bend = FloatProperty(name='Leaf Bend',
description='The proportion of bending applied to the leaf (Bend)',
min=0.0,
max=1.0,
default=0.0)
leafDist = EnumProperty(name='Leaf Distribution',
description='The way leaves are distributed on branches',
items=shapeList,
default='4')
bevelRes = IntProperty(name='Bevel Resolution',
description='The bevel resolution of the curves',
min=0,
default=0)
resU = IntProperty(name='Curve Resolution',
description='The resolution along the curves',
min=1,
default=4)
handleType = EnumProperty(name='Handle Type',
description='The type of handles used in the spline',
items=handleList,
default='1')
frameRate = FloatProperty(name='Frame Rate',
description=('The number of frames per second which can be used to '
'adjust the speed of animation'),
min=0.001,
default=1)
windSpeed = FloatProperty(name='Wind Speed',
description='The wind speed to apply to the armature (WindSpeed)',
default=2.0)
windGust = FloatProperty(name='Wind Gust',
description='The greatest increase over Wind Speed (WindGust)',
default=0.0)
armAnim = BoolProperty(name='Armature Animation',
description='Whether animation is added to the armature',
default=False)
presetName = StringProperty(name='Preset Name',
description='The name of the preset to be saved',
default='',
subtype='FILENAME')
limitImport = BoolProperty(name='Limit Import',
description='Limited imported tree to 2 levels & no leaves for speed',
default=True)
startCurv = FloatProperty(name='Trunk Starting Angle',
description=('The angle between vertical and the starting direction '
'of the trunk'),
min=0.0,
max=360,
default=0.0)
@classmethod
def poll(cls, context):
return context.mode == 'OBJECT'
def draw(self, context):
layout = self.layout
# Branch specs
#layout.label('Tree Definition')
# row = layout.row()
# row.prop(self, 'chooseSet')
# if self.chooseSet == '0':
box = layout.box()
box.label('Geometry')
row = box.row()
row.prop(self, 'bevel')
row = box.row()
row.prop(self, 'bevelRes')
row.prop(self, 'resU')
row = box.row()
row.prop(self, 'handleType')
row = box.row()
row.prop(self, 'shape')
row = box.row()
row.prop(self, 'seed')
row = box.row()
row.prop(self, 'ratio')
row = box.row()
col = row.column()
col.prop(self, 'scale')
col = row.column()
col.prop(self, 'scaleV')
row = box.row()
col = row.column()
col.prop(self, 'scale0')
col = row.column()
col.prop(self, 'scaleV0')
# Here we create a dict of all the properties.
# Unfortunately as_keyword doesn't work with vector properties,
# so we need something custom. This is it
data = []
for a, b in (self.as_keywords(ignore=("presetName", "limitImport"))).items():
# If the property is a vector property then evaluate it and
# convert to a string
if (repr(b))[:3] == 'bpy':
data.append((a, eval('(self.' + a + ')[:]')))
# Otherwise, it is fine so just add it
else:
data.append((a, b))
# Create the dict from the list
data = dict(data)
row = box.row()
row.prop(self, 'presetName')
# Send the data dict and the file name to the exporter
row.operator('sapling.exportdata').data = repr([repr(data),
self.presetName])
row = box.row()
row.menu('sapling.presetmenu', text='Load Preset')
row.prop(self, 'limitImport')
# if self.chooseSet == '1':
box = layout.box()
box.label('Branch Splitting')
row = box.row()
row.prop(self, 'levels')
row = box.row()
row.prop(self, 'baseSplits')
row = box.row()
row.prop(self, 'baseSize')
row = box.row()
col = row.column()
col.prop(self, 'branches')
col = row.column()
col.prop(self, 'segSplits')
row = box.row()
col = row.column()
col.prop(self, 'splitAngle')
col = row.column()
col.prop(self, 'splitAngleV')
row = box.row()
col = row.column()
col.prop(self, 'downAngle')
col = row.column()
col.prop(self, 'downAngleV')
row = box.row()
col = row.column()
col.prop(self, 'rotate')
col = row.column()
col.prop(self, 'rotateV')
row = box.row()
col = row.column()
col.prop(self, 'ratioPower')
# if self.chooseSet == '2':
box = layout.box()
box.label('Branch Growth')
row = box.row()
row.prop(self, 'startCurv')
row = box.row()
row.prop(self, 'attractUp')
row = box.row()
col = row.column()
col.prop(self, 'length')
col = row.column()
col.prop(self, 'lengthV')
row = box.row()
col = row.column()
col.prop(self, 'curve')
col = row.column()
col.prop(self, 'curveV')
row = box.row()
col = row.column()
col.prop(self, 'curveBack')
col = row.column()
col.prop(self, 'taper')
row = box.row()
col = row.column()
col.prop(self, 'curveRes')
# if self.chooseSet == '3':
box = layout.box()
box.label('Pruning')
row = box.row()
row.prop(self, 'prune')
row = box.row()
row.prop(self, 'pruneRatio')
row = box.row()
row.prop(self, 'pruneWidth')
row = box.row()
row.prop(self, 'pruneWidthPeak')
row = box.row()
row.prop(self, 'prunePowerHigh')
row.prop(self, 'prunePowerLow')
# if self.chooseSet == '4':
box = layout.box()
box.label('Leaves')
row = box.row()
row.prop(self, 'showLeaves')
row = box.row()
row.prop(self, 'leaves')
row = box.row()
row.prop(self, 'leafDist')
row = box.row()
col = row.column()
col.prop(self, 'leafScale')
col = row.column()
col.prop(self, 'leafScaleX')
row = box.row()
row.prop(self, 'bend')
# if self.chooseSet == '5':
box = layout.box()
box.label('Armature and Animation')
row = box.row()
row.prop(self, 'useArm')
row.prop(self, 'armAnim')
row = box.row()
row.prop(self, 'windSpeed')
row.prop(self, 'windGust')
row = box.row()
row.prop(self, 'frameRate')
def execute(self, context):
# Ensure the use of the global variables
global settings, useSet
start_time = time.time()
#bpy.ops.ImportData.filename = "quaking_aspen"
# If we need to set the properties from a preset then do it here
if useSet:
for a, b in settings.items():
setattr(self, a, b)
if self.limitImport:
setattr(self, 'levels', 2)
setattr(self, 'showLeaves', False)
useSet = False
addTree(self)
print("Tree creation in %0.1fs" %(time.time()-start_time))
return {'FINISHED'}
def invoke(self, context, event):
# global settings, useSet
# useSet = True
bpy.ops.sapling.importdata(filename = "quaking_aspen.py")
return self.execute(context)
def menu_func(self, context):
self.layout.operator(AddTree.bl_idname, text="Add Tree", icon='PLUGIN')
def register():
bpy.utils.register_module(__name__)
bpy.types.INFO_MT_curve_add.append(menu_func)
def unregister():
bpy.utils.unregister_module(__name__)
bpy.types.INFO_MT_curve_add.remove(menu_func)
if __name__ == "__main__":
register()
\ No newline at end of file
{'pruneWidthPeak': 0.6000000238418579, 'downAngleV': (0.0, -40.0, 10.0, 10.0), 'frameRate': 1.0, 'lengthV': (0.0, 0.05000000074505806, 0.10000000149011612, 0.0), 'shape': '4', 'seed': 0, 'bend': 0.0, 'armAnim': False, 'useArm': False, 'splitAngle': (0.0, 0.0, 0.0, 0.0), 'baseSize': 0.20000000298023224, 'baseSplits': 0, 'scaleV': 5.0, 'scale': 23.0, 'ratio': 0.014999999664723873, 'curveV': (40.0, 90.0, 150.0, 0.0), 'prunePowerHigh': 0.5, 'splitAngleV': (0.0, 0.0, 0.0, 0.0), 'resU': 4, 'segSplits': (0.0, 0.0, 0.0, 0.0), 'ratioPower': 1.2999999523162842, 'handleType': '1', 'length': (1.0, 0.30000001192092896, 0.6000000238418579, 0.4000000059604645), 'rotateV': (0.0, 0.0, 0.0, 0.0), 'attractUp': 0.5, 'scale0': 1.0, 'bevel': False, 'leafDist': '4', 'chooseSet': '0', 'levels': 4, 'downAngle': (90.0, 60.0, 30.0, 45.0), 'showLeaves': False, 'prunePowerLow': 0.0010000000474974513, 'scaleV0': 0.0, 'leafScaleX': 0.5, 'curveRes': (10, 10, 10, 1), 'rotate': (140.0, 140.0, 140.0, 140.0), 'branches': (0, 50, 25, 12), 'prune': False, 'bevelRes': 0, 'taper': (1.0, 1.0, 1.0, 1.0), 'pruneRatio': 1.0, 'leaves': 6, 'curve': (0.0, 0.0, -10.0, 0.0), 'leafScale': 0.30000001192092896, 'windSpeed': 2.0, 'pruneWidth': 0.4000000059604645, 'windGust': 0.0, 'startCurv': 0.0, 'curveBack': (0.0, 0.0, 0.0, 0.0)}
\ No newline at end of file
{'pruneWidthPeak': 0.6000000238418579, 'downAngleV': (0.0, -30.0, 10.0, 10.0), 'frameRate': 1.0, 'lengthV': (0.0, 0.10000000149011612, 0.05000000074505806, 0.0), 'shape': '2', 'seed': 0, 'bend': 0.0, 'armAnim': False, 'useArm': False, 'splitAngle': (10.0, 10.0, 10.0, 0.0), 'baseSize': 0.05000000074505806, 'baseSplits': 2, 'scaleV': 10.0, 'scale': 10.0, 'ratio': 0.017999999225139618, 'curveV': (90.0, 150.0, -30.0, 0.0), 'prunePowerHigh': 0.5, 'splitAngleV': (0.0, 10.0, 10.0, 0.0), 'resU': 4, 'segSplits': (0.4000000059604645, 0.20000000298023224, 0.10000000149011612, 0.0), 'ratioPower': 1.2999999523162842, 'handleType': '1', 'length': (1.0, 0.800000011920929, 0.20000000298023224, 0.4000000059604645), 'rotateV': (0.0, 0.0, 0.0, 0.0), 'attractUp': 0.800000011920929, 'scale0': 1.0, 'bevel': False, 'leafDist': '4', 'chooseSet': '0', 'levels': 3, 'downAngle': (0.0, 30.0, 45.0, 45.0), 'showLeaves': False, 'prunePowerLow': 0.0010000000474974513, 'scaleV0': 0.0, 'leafScaleX': 0.6600000262260437, 'curveRes': (8, 10, 3, 1), 'rotate': (0.0, 80.0, 140.0, 140.0), 'branches': (0, 40, 120, 0), 'prune': False, 'bevelRes': 0, 'taper': (1.0, 1.0, 1.0, 1.0), 'pruneRatio': 1.0, 'leaves': 25, 'curve': (0.0, 40.0, 0.0, 0.0), 'leafScale': 0.11999999731779099, 'windSpeed': 2.0, 'pruneWidth': 0.4000000059604645, 'windGust': 0.0, 'startCurv': 0.0, 'curveBack': (0.0, -70.0, 0.0, 0.0)}
\ No newline at end of file
{'pruneWidthPeak': 0.6000000238418579, 'downAngleV': (0.0, -50.0, 10.0, 10.0), 'frameRate': 1.0, 'lengthV': (0.0, 0.0, 0.0, 0.0), 'shape': '7', 'seed': 0, 'bend': 0.0, 'armAnim': False, 'useArm': False, 'splitAngle': (0.0, 0.0, 0.0, 0.0), 'baseSize': 0.4000000059604645, 'baseSplits': 0, 'scaleV': 3.0, 'scale': 13.0, 'ratio': 0.014999999664723873, 'curveV': (20.0, 50.0, 75.0, 0.0), 'prunePowerHigh': 0.5, 'splitAngleV': (0.0, 0.0, 0.0, 0.0), 'resU': 4, 'segSplits': (0.0, 0.0, 0.0, 0.0), 'ratioPower': 1.2000000476837158, 'handleType': '1', 'length': (1.0, 0.30000001192092896, 0.6000000238418579, 0.44999998807907104), 'rotateV': (0.0, 0.0, 0.0, 0.0), 'attractUp': 0.5, 'scale0': 1.0, 'bevel': False, 'leafDist': '4', 'chooseSet': '0', 'levels': 3, 'downAngle': (90.0, 60.0, 45.0, 45.0), 'showLeaves': False, 'prunePowerLow': 0.0010000000474974513, 'scaleV0': 0.20000000298023224, 'leafScaleX': 1.0, 'curveRes': (3, 5, 3, 1), 'rotate': (140.0, 140.0, 140.0, 77.0), 'branches': (0, 50, 30, 10), 'prune': False, 'bevelRes': 0, 'taper': (1.0, 1.0, 1.0, 1.0), 'pruneRatio': 1.0, 'leaves': 25, 'curve': (0.0, -40.0, -40.0, 0.0), 'leafScale': 0.17000000178813934, 'windSpeed': 2.0, 'pruneWidth': 0.4000000059604645, 'windGust': 0.0, 'startCurv': 0.0, 'curveBack': (0.0, 0.0, 0.0, 0.0)}
\ No newline at end of file
{'pruneWidthPeak': 0.6000000238418579, 'downAngleV': (0.0, 10.0, 10.0, 10.0), 'frameRate': 1.0, 'lengthV': (0.0, 0.10000000149011612, 0.0, 0.0), 'shape': '3', 'seed': 0, 'bend': 0.0, 'armAnim': False, 'useArm': False, 'splitAngle': (3.0, 30.0, 45.0, 0.0), 'baseSize': 0.05000000074505806, 'baseSplits': 2, 'scaleV': 5.0, 'scale': 15.0, 'ratio': 0.029999999329447746, 'curveV': (120.0, 90.0, 0.0, 0.0), 'prunePowerHigh': 0.5, 'splitAngleV': (0.0, 10.0, 20.0, 0.0), 'resU': 4, 'segSplits': (0.10000000149011612, 0.20000000298023224, 0.20000000298023224, 0.0), 'ratioPower': 2.0, 'handleType': '1', 'length': (0.800000011920929, 0.5, 1.5, 0.10000000149011612), 'rotateV': (0.0, 30.0, 30.0, 0.0), 'attractUp': -3.0, 'scale0': 1.0, 'bevel': False, 'leafDist': '4', 'chooseSet': '0', 'levels': 4, 'downAngle': (0.0, 20.0, 30.0, 20.0), 'showLeaves': False, 'prunePowerLow': 0.0010000000474974513, 'scaleV0': 0.0, 'leafScaleX': 0.20000000298023224, 'curveRes': (8, 16, 12, 1), 'rotate': (0.0, -120.0, -120.0, 140.0), 'branches': (0, 25, 10, 300), 'prune': True, 'bevelRes': 0, 'taper': (1.0, 1.0, 1.0, 1.0), 'pruneRatio': 1.0, 'leaves': 15, 'curve': (0.0, 40.0, 0.0, 0.0), 'leafScale': 0.11999999731779099, 'windSpeed': 2.0, 'pruneWidth': 0.4000000059604645, 'windGust': 0.0, 'startCurv': 0.0, 'curveBack': (20.0, 80.0, 0.0, 0.0)}
\ No newline at end of file
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment