Add Lattice Magic
to Addons
#48
@ -193,6 +193,47 @@ class TWEAKLAT_OT_Create(Operator):
|
|||||||
return {'FINISHED'}
|
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):
|
class TWEAKLAT_OT_Falloff(Operator):
|
||||||
"""Adjust falloff of the hook vertex group of a Tweak Lattice"""
|
"""Adjust falloff of the hook vertex group of a Tweak Lattice"""
|
||||||
bl_idname = "lattice.tweak_lattice_adjust_falloww"
|
bl_idname = "lattice.tweak_lattice_adjust_falloww"
|
||||||
@ -385,16 +426,6 @@ class TWEAKLAT_OT_Remove_Object(Operator):
|
|||||||
return {'FINISHED'}
|
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):
|
class TWEAKLAT_PT_Main(Panel):
|
||||||
bl_space_type = 'VIEW_3D'
|
bl_space_type = 'VIEW_3D'
|
||||||
bl_region_type = 'UI'
|
bl_region_type = 'UI'
|
||||||
@ -405,7 +436,7 @@ class TWEAKLAT_PT_Main(Panel):
|
|||||||
def poll(cls, context):
|
def poll(cls, context):
|
||||||
hook, _lattice, _root = get_tweak_setup(context.object)
|
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):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
@ -427,6 +458,8 @@ class TWEAKLAT_PT_Main(Panel):
|
|||||||
layout.separator()
|
layout.separator()
|
||||||
layout.operator(TWEAKLAT_OT_Delete.bl_idname,
|
layout.operator(TWEAKLAT_OT_Delete.bl_idname,
|
||||||
text='Delete Tweak Lattice', icon='TRASH')
|
text='Delete Tweak Lattice', icon='TRASH')
|
||||||
|
layout.operator(TWEAKLAT_OT_Duplicate.bl_idname,
|
||||||
|
text='Duplicate Tweak Lattice', icon='DUPLICATE')
|
||||||
|
|
||||||
layout.separator()
|
layout.separator()
|
||||||
layout.label(text="Helper Objects")
|
layout.label(text="Helper Objects")
|
||||||
@ -497,6 +530,9 @@ class TWEAKLAT_PT_Main(Panel):
|
|||||||
|
|
||||||
def get_tweak_setup(obj: Object) -> Tuple[Object, Object, Object]:
|
def get_tweak_setup(obj: Object) -> Tuple[Object, Object, Object]:
|
||||||
"""Based on either the hook, lattice or root, return all three."""
|
"""Based on either the hook, lattice or root, return all three."""
|
||||||
|
if not obj:
|
||||||
|
return [None, None, None]
|
||||||
|
|
||||||
if obj.type == 'EMPTY':
|
if obj.type == 'EMPTY':
|
||||||
if 'Root' and 'Lattice' in obj:
|
if 'Root' and 'Lattice' in obj:
|
||||||
return obj, obj['Lattice'], obj['Root']
|
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]:
|
def get_objects_of_lattice(hook: Object) -> List[Object]:
|
||||||
objs = []
|
objs = []
|
||||||
ob_count = 0
|
for key, value in hook.items():
|
||||||
ob_prop_name = "object_"+str(ob_count)
|
if key.startswith("object_") and value:
|
||||||
while ob_prop_name in hook:
|
objs.append(value)
|
||||||
objs.append(hook[ob_prop_name])
|
|
||||||
return objs
|
return objs
|
||||||
|
|
||||||
|
|
||||||
@ -579,20 +615,20 @@ def add_objects_to_lattice(
|
|||||||
objects: List[Object]):
|
objects: List[Object]):
|
||||||
lattice_ob = hook['Lattice']
|
lattice_ob = hook['Lattice']
|
||||||
|
|
||||||
# Check for existing
|
|
||||||
offset = 0
|
|
||||||
while "object_"+str(offset) in hook:
|
|
||||||
offset += 1
|
|
||||||
|
|
||||||
for i, o in enumerate(objects):
|
for i, o in enumerate(objects):
|
||||||
o.select_set(False)
|
o.select_set(False)
|
||||||
if o.type != 'MESH' or o in hook.values():
|
if o.type != 'MESH' or o in hook.values():
|
||||||
offset -= 1
|
|
||||||
continue
|
continue
|
||||||
m = o.modifiers.new(name="Tweak Lattice", type='LATTICE')
|
m = o.modifiers.new(name=lattice_ob.name, type='LATTICE')
|
||||||
m.object = lattice_ob
|
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
|
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"]')
|
simple_driver(m, 'strength', hook, '["Tweak Lattice"]')
|
||||||
|
|
||||||
|
|
||||||
@ -628,6 +664,7 @@ def remove_objects_from_lattice(hook, objects):
|
|||||||
|
|
||||||
classes = [
|
classes = [
|
||||||
TWEAKLAT_OT_Create,
|
TWEAKLAT_OT_Create,
|
||||||
|
TWEAKLAT_OT_Duplicate,
|
||||||
TWEAKLAT_OT_Delete,
|
TWEAKLAT_OT_Delete,
|
||||||
TWEAKLAT_OT_Falloff,
|
TWEAKLAT_OT_Falloff,
|
||||||
TWEAKLAT_OT_Add_Objects,
|
TWEAKLAT_OT_Add_Objects,
|
||||||
|
Loading…
Reference in New Issue
Block a user