Add Lattice Magic
to Addons
#48
@ -71,7 +71,7 @@ def draw_lattice_reset(self, context):
|
|||||||
self.layout.operator(LATTICE_OT_Reset.bl_idname, text="Reset Point Positions", icon='FILE_REFRESH')
|
self.layout.operator(LATTICE_OT_Reset.bl_idname, text="Reset Point Positions", icon='FILE_REFRESH')
|
||||||
|
|
||||||
classes = [
|
classes = [
|
||||||
LATTICE_OT_Reset
|
LATTICE_OT_Reset
|
||||||
]
|
]
|
||||||
|
|
||||||
def register():
|
def register():
|
||||||
|
@ -35,7 +35,7 @@ def ensure_tweak_lattice_collection(scene: bpy.types.Scene) -> bpy.types.Collect
|
|||||||
|
|
||||||
def ensure_falloff_vgroup(
|
def ensure_falloff_vgroup(
|
||||||
lattice_ob: bpy.types.Object,
|
lattice_ob: bpy.types.Object,
|
||||||
vg_name="Group", multiplier=1) -> bpy.types.VertexGroup:
|
vg_name="Group", multiplier=1, expression="x") -> bpy.types.VertexGroup:
|
||||||
lattice = lattice_ob.data
|
lattice = lattice_ob.data
|
||||||
res_x, res_y, res_z = lattice.points_u, lattice.points_v, lattice.points_w
|
res_x, res_y, res_z = lattice.points_u, lattice.points_v, lattice.points_w
|
||||||
|
|
||||||
@ -53,8 +53,12 @@ def ensure_falloff_vgroup(
|
|||||||
|
|
||||||
coord = Vector((x+2, y+2, z+2))
|
coord = Vector((x+2, y+2, z+2))
|
||||||
distance_from_center = (coord-center).length
|
distance_from_center = (coord-center).length
|
||||||
influence = 1 - distance_from_center / max_res * 2
|
distance_factor = 1 - (distance_from_center / max_res * 2)
|
||||||
|
try:
|
||||||
|
influence = eval(expression.replace("x", "distance_factor"))
|
||||||
|
except:
|
||||||
|
return None
|
||||||
|
|
||||||
vg.add([index], influence * multiplier, 'REPLACE')
|
vg.add([index], influence * multiplier, 'REPLACE')
|
||||||
return vg
|
return vg
|
||||||
|
|
||||||
@ -171,6 +175,7 @@ class TWEAKLAT_OT_Create(bpy.types.Operator):
|
|||||||
# Create some custom properties
|
# Create some custom properties
|
||||||
hook['Lattice'] = lattice_ob
|
hook['Lattice'] = lattice_ob
|
||||||
hook['Multiplier'] = 1.0
|
hook['Multiplier'] = 1.0
|
||||||
|
hook['Expression'] = 'x'
|
||||||
|
|
||||||
rna_idprop_ui_create(
|
rna_idprop_ui_create(
|
||||||
hook, "Tweak Lattice", default = 1.0,
|
hook, "Tweak Lattice", default = 1.0,
|
||||||
@ -242,15 +247,36 @@ class TWEAKLAT_OT_Falloff(bpy.types.Operator):
|
|||||||
bl_label = "Adjust Falloff"
|
bl_label = "Adjust Falloff"
|
||||||
bl_options = {'REGISTER', 'UNDO', 'INTERNAL'}
|
bl_options = {'REGISTER', 'UNDO', 'INTERNAL'}
|
||||||
|
|
||||||
def update(self, context):
|
def update_falloff(self, context):
|
||||||
if self.doing_invoke: return
|
if self.doing_invoke: return
|
||||||
hook = context.object
|
hook = context.object
|
||||||
lattice_ob = hook['Lattice']
|
lattice_ob = hook['Lattice']
|
||||||
ensure_falloff_vgroup(lattice_ob, 'Hook', multiplier=self.multiplier)
|
ret = ensure_falloff_vgroup(lattice_ob, 'Hook', multiplier=self.multiplier, expression=self.expression)
|
||||||
|
self.is_expression_valid = ret != None
|
||||||
|
if ret:
|
||||||
|
hook['Expression'] = self.expression
|
||||||
hook['Multiplier'] = self.multiplier
|
hook['Multiplier'] = self.multiplier
|
||||||
|
|
||||||
|
is_expression_valid: BoolProperty(
|
||||||
|
name = "Error",
|
||||||
|
description = "Used to notify user if their expression is invalid",
|
||||||
|
default = True
|
||||||
|
)
|
||||||
# Actual parameters
|
# Actual parameters
|
||||||
multiplier: FloatProperty(name="Multiplier", default=1, update=update, min=0, soft_max=2)
|
multiplier: FloatProperty(
|
||||||
|
name="Multiplier",
|
||||||
|
description = "Multiplier on the weight values",
|
||||||
|
default=1,
|
||||||
|
update=update_falloff,
|
||||||
|
min=0,
|
||||||
|
soft_max=2
|
||||||
|
)
|
||||||
|
expression: StringProperty(
|
||||||
|
name="Expression",
|
||||||
|
default="x",
|
||||||
|
description = "Expression to calculate the weight values where 'x' is a 0-1 value representing a point's closeness to the lattice center",
|
||||||
|
update=update_falloff,
|
||||||
|
)
|
||||||
|
|
||||||
# Storage to share info between Invoke and Update
|
# Storage to share info between Invoke and Update
|
||||||
lattice_start_scale: FloatVectorProperty()
|
lattice_start_scale: FloatVectorProperty()
|
||||||
@ -268,6 +294,10 @@ class TWEAKLAT_OT_Falloff(bpy.types.Operator):
|
|||||||
self.hook_start_scale = hook.scale.copy()
|
self.hook_start_scale = hook.scale.copy()
|
||||||
lattice_ob = hook['Lattice']
|
lattice_ob = hook['Lattice']
|
||||||
self.lattice_start_scale = lattice_ob.scale.copy()
|
self.lattice_start_scale = lattice_ob.scale.copy()
|
||||||
|
if 'Expression' not in hook:
|
||||||
|
# Back-comp for Tweak Lattices created with older versions of the add-on.
|
||||||
|
hook['Expression'] = 'x'
|
||||||
|
self.expression = hook['Expression']
|
||||||
|
|
||||||
self.doing_invoke = False
|
self.doing_invoke = False
|
||||||
wm = context.window_manager
|
wm = context.window_manager
|
||||||
@ -277,6 +307,12 @@ class TWEAKLAT_OT_Falloff(bpy.types.Operator):
|
|||||||
layout = self.layout
|
layout = self.layout
|
||||||
layout.use_property_split = True
|
layout.use_property_split = True
|
||||||
layout.use_property_decorate = False
|
layout.use_property_decorate = False
|
||||||
|
layout.prop(self, 'expression', text="Expression", slider=True)
|
||||||
|
if not self.is_expression_valid:
|
||||||
|
row = layout.row()
|
||||||
|
row.alert = True
|
||||||
|
row.label(text="Invalid expression.", icon='ERROR')
|
||||||
|
|
||||||
layout.prop(self, 'multiplier', text="Strength", slider=True)
|
layout.prop(self, 'multiplier', text="Strength", slider=True)
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
|
Loading…
Reference in New Issue
Block a user