Add Lattice Magic
to Addons
#48
@ -193,6 +193,47 @@ class TWEAKLAT_OT_Create(Operator):
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
|
||||
class TWEAKLAT_OT_Duplicate(Operator):
|
||||
"""Duplicate this Tweak Lattice set-up"""
|
||||
bl_idname = "lattice.duplicate_tweak_setup"
|
||||
bl_label = "Duplicate Tweak Lattice"
|
||||
bl_options = {'REGISTER', 'UNDO', 'INTERNAL'}
|
||||
|
||||
def execute(self, context):
|
||||
hook, lattice, root = get_tweak_setup(context.object)
|
||||
bpy.ops.object.select_all(action='DESELECT')
|
||||
|
||||
affected_objects = get_objects_of_lattice(hook)
|
||||
|
||||
visibilities = {}
|
||||
for ob in [hook, lattice, root]:
|
||||
ob.hide_set(False)
|
||||
visibilities[ob] = ob.hide_viewport
|
||||
ob.hide_viewport = False
|
||||
if not ob.visible_get():
|
||||
self.report({'ERROR'}, f'Object "{ob.name}" could not be made visible, cancelling.')
|
||||
return {'CANCELLED'}
|
||||
ob.select_set(True)
|
||||
|
||||
context.view_layer.objects.active = hook
|
||||
|
||||
bpy.ops.object.duplicate()
|
||||
new_hook, new_lattice, new_root = get_tweak_setup(context.object)
|
||||
|
||||
for key, value in new_hook.items():
|
||||
if key.startswith("object_"):
|
||||
del new_hook[key]
|
||||
|
||||
add_objects_to_lattice(new_hook, affected_objects)
|
||||
|
||||
# Restore visibilities
|
||||
for ob, new_ob in zip((hook, lattice, root), (new_hook, new_lattice, new_root)):
|
||||
ob.hide_viewport = new_ob.hide_viewport = visibilities[ob]
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
class TWEAKLAT_OT_Falloff(Operator):
|
||||
"""Adjust falloff of the hook vertex group of a Tweak Lattice"""
|
||||
bl_idname = "lattice.tweak_lattice_adjust_falloww"
|
||||
@ -385,16 +426,6 @@ class TWEAKLAT_OT_Remove_Object(Operator):
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
class TWEAKLAT_OT_Duplicate(Operator):
|
||||
"""Duplicate this Tweak Lattice set-up"""
|
||||
bl_idname = "lattice.duplicate_tweak_setup"
|
||||
bl_label = "Duplicate Tweak Lattice"
|
||||
bl_options = {'REGISTER', 'UNDO', 'INTERNAL'}
|
||||
|
||||
def execute(self, context):
|
||||
pass
|
||||
|
||||
|
||||
class TWEAKLAT_PT_Main(Panel):
|
||||
bl_space_type = 'VIEW_3D'
|
||||
bl_region_type = 'UI'
|
||||
@ -405,7 +436,7 @@ class TWEAKLAT_PT_Main(Panel):
|
||||
def poll(cls, context):
|
||||
hook, _lattice, _root = get_tweak_setup(context.object)
|
||||
|
||||
return context.object.type == 'MESH' or hook
|
||||
return context.object and context.object.type == 'MESH' or hook
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
@ -427,6 +458,8 @@ class TWEAKLAT_PT_Main(Panel):
|
||||
layout.separator()
|
||||
layout.operator(TWEAKLAT_OT_Delete.bl_idname,
|
||||
text='Delete Tweak Lattice', icon='TRASH')
|
||||
layout.operator(TWEAKLAT_OT_Duplicate.bl_idname,
|
||||
text='Duplicate Tweak Lattice', icon='DUPLICATE')
|
||||
|
||||
layout.separator()
|
||||
layout.label(text="Helper Objects")
|
||||
@ -497,6 +530,9 @@ class TWEAKLAT_PT_Main(Panel):
|
||||
|
||||
def get_tweak_setup(obj: Object) -> Tuple[Object, Object, Object]:
|
||||
"""Based on either the hook, lattice or root, return all three."""
|
||||
if not obj:
|
||||
return [None, None, None]
|
||||
|
||||
if obj.type == 'EMPTY':
|
||||
if 'Root' and 'Lattice' in obj:
|
||||
return obj, obj['Lattice'], obj['Root']
|
||||
@ -560,10 +596,10 @@ def add_radius_constraint(obj, hook, target):
|
||||
|
||||
def get_objects_of_lattice(hook: Object) -> List[Object]:
|
||||
objs = []
|
||||
ob_count = 0
|
||||
ob_prop_name = "object_"+str(ob_count)
|
||||
while ob_prop_name in hook:
|
||||
objs.append(hook[ob_prop_name])
|
||||
for key, value in hook.items():
|
||||
if key.startswith("object_") and value:
|
||||
objs.append(value)
|
||||
|
||||
return objs
|
||||
|
||||
|
||||
@ -579,20 +615,20 @@ def add_objects_to_lattice(
|
||||
objects: List[Object]):
|
||||
lattice_ob = hook['Lattice']
|
||||
|
||||
# Check for existing
|
||||
offset = 0
|
||||
while "object_"+str(offset) in hook:
|
||||
offset += 1
|
||||
|
||||
for i, o in enumerate(objects):
|
||||
o.select_set(False)
|
||||
if o.type != 'MESH' or o in hook.values():
|
||||
offset -= 1
|
||||
continue
|
||||
m = o.modifiers.new(name="Tweak Lattice", type='LATTICE')
|
||||
m = o.modifiers.new(name=lattice_ob.name, type='LATTICE')
|
||||
m.object = lattice_ob
|
||||
|
||||
# Make sure the property name is available.
|
||||
offset = 0
|
||||
while "object_"+str(offset) in hook:
|
||||
offset += 1
|
||||
hook["object_"+str(i+offset)] = o
|
||||
# Add driver to the modifier influence
|
||||
|
||||
# Add driver to the modifier influence.
|
||||
simple_driver(m, 'strength', hook, '["Tweak Lattice"]')
|
||||
|
||||
|
||||
@ -628,6 +664,7 @@ def remove_objects_from_lattice(hook, objects):
|
||||
|
||||
classes = [
|
||||
TWEAKLAT_OT_Create,
|
||||
TWEAKLAT_OT_Duplicate,
|
||||
TWEAKLAT_OT_Delete,
|
||||
TWEAKLAT_OT_Falloff,
|
||||
TWEAKLAT_OT_Add_Objects,
|
||||
|
Loading…
Reference in New Issue
Block a user