work: save startup because I'm sick of the arnoldesque materials

This commit is contained in:
2026-04-24 14:39:38 -06:00
parent b401eb4bcf
commit 2f8e5f472f
57 changed files with 2257 additions and 1643 deletions
+7 -6
View File
@@ -20,7 +20,7 @@
bl_info = {
"name": "Animation Layers",
"author": "Tal Hershkovich",
"version" : (2, 3, 8),
"version" : (2, 4, 0),
"blender" : (3, 2, 0),
"location": "View3D - Properties - Animation Panel",
"description": "Simplifying the NLA editor into an animation layers UI and workflow",
@@ -153,7 +153,6 @@ def update_panel(self, context):
bpy.utils.unregister_class(panel)
for panel in panels:
#print (panel.bl_category)
panel.bl_category = context.preferences.addons[__name__].preferences.category
bpy.utils.register_class(panel)
@@ -176,8 +175,9 @@ class AnimLayersAddonPreferences(bpy.types.AddonPreferences):
items = [('ANIMLAYERS', 'Anim Layers Settings', 'Use Anim Layers properties to adjust custom frame range'),
('NLA', 'NLA Settings', 'Use the nla properties to adjust custom frame range')])
lock_nlatracks: bpy.props.BoolProperty(name="Automatically lock the nla tracks for safety measures", description="Automatically lock nla tracks when creating layers for safety", default = True)
lock_nlatracks: bpy.props.BoolProperty(name="Automatically lock the NLA tracks", description="Automatically lock nla tracks when creating layers for safety", default = True)
auto_custom_range: bpy.props.BoolProperty(name="Switch automatically to custom frame range when editing NLA Strips", description="Automatically use custom frame range when adjusting NLA Strips manually", default = False)
#Property for ClearActiveAction
proceed: bpy.props.EnumProperty(name="Choose how to proceed", description="Select an option how to proceed with Anim Layers", override = {'LIBRARY_OVERRIDABLE'},
items = [
@@ -260,8 +260,9 @@ class AnimLayersAddonPreferences(bpy.types.AddonPreferences):
row.label(text = "Custom Frame Range Settings")
row.prop(self, "frame_range_settings", text = '')
col.prop(self, "lock_nlatracks")
row = col.row()
row.prop(self, "auto_custom_range")
row.prop(self, "lock_nlatracks")
classes = (AnimLayersSettings, AnimLayersSceneSettings, AnimLayersItems, AnimLayersObjects)
+28 -23
View File
@@ -399,7 +399,7 @@ def get_fcu_layer_keyframes(obj, context, track):
keyframes = []
# fcurves = get_fcurves(track.strips[0].action)
# fcurves = track.strips[0].action.fcurves
fcurves = get_fcurves(obj, track.strips[0].action)
fcurves = get_fcurves(obj, track.strips[0].action, obj.als.data_type)
#store all the keyframe locations from the fcurves of the layer
for fcu in fcurves:
if fcu.group is not None:
@@ -1546,6 +1546,8 @@ def strip_action_recalc(self, strip):
###################################################### HELPER FUNCTIONS ################################################
def redraw_areas(areas):
if not len(bpy.context.window_manager.windows):
return
for area in bpy.context.window_manager.windows[0].screen.areas:
if area.type in areas:
area.tag_redraw()
@@ -1621,7 +1623,7 @@ def select_layer_bones(self, context):
###################################################### CLASSES ###########################################################
class SelectBonesInLayer(bpy.types.Operator):
"""Select bones with keyframes in the current layer"""
"""Select bones with keyframes in the current layer, use shift to add to the current selection"""
bl_idname = "anim.bones_in_layer"
bl_label = "Select layer bones"
bl_icon = "BONE_DATA"
@@ -1864,18 +1866,9 @@ class AutoCustomFrameRange(bpy.types.Operator):
# return {'CANCELLED'}
def restore(self, context):
if hasattr(subscriptions, 'frame_range'):
frame_start, frame_end = subscriptions.frame_range
else:
frame_start, frame_end = subscriptions.get_frame_range(context.scene)
print('restore')
subscriptions.frameend_update_callback()
self.strip.repeat = 1 #change strip repeat but keep self.repeat value stored
self.strip.use_reverse = False
self.strip.frame_start = frame_start
self.strip.scale = self.layer.speed
self.strip.frame_end = frame_end
# update_action_frame_range(frame_start, frame_end, layer, strip)
subscriptions.subscriptions_add(context.scene)
def update_action_list(scene):
@@ -2596,9 +2589,7 @@ class RemoveFcurves(bpy.types.Operator):
if mod.type == 'CYCLES':
fcu.modifiers.remove(mod)
fcu.update()
for area in context.window_manager.windows[0].screen.areas:
if area.type == 'GRAPH_EDITOR' or area.type == 'VIEW_3D':
area.tag_redraw()
redraw_areas(['GRAPH_EDITOR', 'VIEW_3D'])
break
return {'FINISHED'}
@@ -3301,25 +3292,36 @@ def copy_action(action):
return new_action
def get_obj_slot(obj, action, data_type = 'OBJECT'):
def get_obj_slot(obj, action, data_type = None):
'''Get the slot in the action that this object is using either it's object, or shapekeys'''
if data_type is None:
data_type = obj.als.data_type
if not hasattr(action, 'slots'):
return None
if not len(action.slots):
# If no slots exist, create one for the object and return it
slot = add_action_slot(obj, action)
return slot
# data_type = obj.als.data_type
for slot in action.slots:
if slot.target_id_type != data_type:
continue
# if obj.als.data_type == 'OBJECT' and obj in slot.users():
# return slot
if data_type == 'KEY' and obj.data.shape_keys in slot.users():
return slot
elif obj in slot.users():
return slot
return None
return add_action_slot(obj, action)
def get_fcurves(obj: bpy.types.Object, action: bpy.types.Action, data_type = 'OBJECT'):
def get_fcurves(obj: bpy.types.Object, action: bpy.types.Action, data_type = None):
if data_type is None:
data_type = obj.als.data_type
if hasattr(action, 'layers'):
slot = get_obj_slot(obj, action, data_type)
@@ -3335,10 +3337,13 @@ def get_fcurves(obj: bpy.types.Object, action: bpy.types.Action, data_type = 'OB
return action.fcurves
return []
def get_channelbag(obj: bpy.types.Object, action: bpy.types.Action, data_type = 'OBJECT'):
def get_channelbag(obj: bpy.types.Object, action: bpy.types.Action, data_type = None):
'''Getting the container of the fcurves, either the action or channelbag
Using this when adding a new group to the action'''
if data_type is None:
data_type = obj.als.data_type
if hasattr(action, 'layers'):
slot = get_obj_slot(obj, action, data_type)
channelbag = None
@@ -1,16 +1,9 @@
{
"last_check": "2026-04-21 12:45:18.211769",
"backup_date": "March-27-2026",
"update_ready": true,
"last_check": "2026-04-21 12:47:39.126086",
"backup_date": "April-21-2026",
"update_ready": false,
"ignore": false,
"just_restored": false,
"just_updated": false,
"version_text": {
"link": "https://gitlab.com/api/v4/projects/22294607/repository/archive.zip?sha=dddd6932039b8a3e5fae3ce2de957f21a5942c84",
"version": [
2,
4,
0
]
}
"version_text": {}
}
@@ -20,7 +20,7 @@
bl_info = {
"name": "Animation Layers",
"author": "Tal Hershkovich",
"version" : (2, 3, 7),
"version" : (2, 3, 8),
"blender" : (3, 2, 0),
"location": "View3D - Properties - Animation Panel",
"description": "Simplifying the NLA editor into an animation layers UI and workflow",
@@ -271,7 +271,6 @@ def register_layers(obj, nla_tracks):
continue
strip = track.strips[0]
use_animated_influence(strip)
strip.influence = 1
#updating the ui list with the nla track names
def visible_layers(obj, nla_tracks):
@@ -355,9 +354,9 @@ def use_animated_influence(strip):
else:
keyframe = keyframes[0]
keyframes.remove(keyframe)
strip.influence = 1
strip.influence = 1
def check_override_layers(obj):
if obj.override_library is None:
return False
@@ -1298,7 +1297,6 @@ def load_action(self, context):
subscriptions.frameend_update_callback()
strip.use_sync_length = False
use_animated_influence(strip)
strip.influence = 1
return
subscriptions.subscriptions_remove()
strip = track.strips[0]
@@ -1949,7 +1947,6 @@ def add_animlayer(layer_name = 'Anim_Layer' , duplicate = False, index = 1, blen
new_strip.blend_type = blend_type
new_strip.use_sync_length = False
use_animated_influence(new_strip)
new_strip.influence = 1
return new_track
@@ -1,16 +1,16 @@
{
"last_check": "2026-03-27 11:33:07.238724",
"backup_date": "March-20-2026",
"last_check": "2026-04-21 12:47:39.126086",
"backup_date": "March-27-2026",
"update_ready": true,
"ignore": false,
"just_restored": false,
"just_updated": false,
"version_text": {
"link": "https://gitlab.com/api/v4/projects/22294607/repository/archive.zip?sha=eef950c6d5e620a8240db5c2a7b20955fe31df6f",
"link": "https://gitlab.com/api/v4/projects/22294607/repository/archive.zip?sha=dddd6932039b8a3e5fae3ce2de957f21a5942c84",
"version": [
2,
3,
8
4,
0
]
}
}
@@ -645,6 +645,7 @@ def AL_bake(frame_start, frame_end, nla_tracks, fcu_keys, additive, step, action
baked_action = track.strips[0].action
clean_no_user_slots(baked_action)
#create the baked fcurve
# baked_channelbag = anim_layers.get_channelbag(obj, baked_action, obj.als.data_type)
baked_channelbag = anim_layers.get_channelbag(obj, baked_action)
baked_fcurves = baked_channelbag.fcurves
@@ -73,7 +73,6 @@ def animlayers_frame(scene, context):
scene['framerange_preview'] = scene.use_preview_range
frameend_update_callback()
return
frame_start, frame_end = bake_ops.frame_start_end(scene)
# frame_start, frame_end = get_frame_range(scene)
reset_subscription = False
@@ -106,7 +105,6 @@ def animlayers_frame(scene, context):
for i, track in enumerate(nla_tracks):
if len(track.strips) != 1:
continue
#checks if the layer has a custom frame range
layer = obj.Anim_Layers[i]
if layer.custom_frame_range:
@@ -127,6 +125,7 @@ def animlayers_frame(scene, context):
if strip.frame_start < 0:
strip.frame_start = 0
anim_layers.update_action_frame_range(0, frame_end, layer, strip)
return
anim_layers.update_action_frame_range(strip.frame_start, current + 10.0, layer, strip)
strip.frame_end = current + 10.0
@@ -231,6 +230,9 @@ def track_layer_synchronization(obj, nla_tracks):
if obj.als.layer_index > len(obj.Anim_Layers)-1:
obj.als.layer_index = len(obj.Anim_Layers)-1
if not bpy.context.preferences.addons[__package__].preferences.auto_custom_range:
return
#update new layer with strip settings
frame_start, frame_end = get_frame_range(bpy.context.scene)
@@ -243,7 +245,6 @@ def track_layer_synchronization(obj, nla_tracks):
continue
if (strip.frame_start, strip.frame_end) != (frame_start, frame_end):
subscriptions_remove()
# print(f'strip.frame_start {strip.frame_start} strip.frame_end {strip.frame_end} frame_start {frame_start} frame_end {frame_end}')
bpy.ops.anim.custom_frame_range_warning('INVOKE_DEFAULT')
return
@@ -311,11 +312,16 @@ def sync_frame_range(scene, track, layer):
return
#Turn on custom frame range if the current strip is not following the scene frame range
# Should be activated when nla strips are edited manually in the nla editor, only when auto custom range is turned on, otherwise just update the strip frame range to the scene frame range
if (round(strip.frame_start, 2), round(strip.frame_end, 2)) != (round(frame_start, 2), round(frame_end, 2)):
subscriptions_remove()
# print('315 custom frame range')
bpy.ops.anim.custom_frame_range_warning('INVOKE_DEFAULT')
return
if bpy.context.preferences.addons[__package__].preferences.auto_custom_range:
subscriptions_remove()
# print('321 custom frame range')
bpy.ops.anim.custom_frame_range_warning('INVOKE_DEFAULT')
return
else:
frameend_update_callback()
return
def sync_strip_range(scene):
'''Checking all the strips if a value was changed in the nla (not including UI changes)
@@ -356,7 +362,6 @@ def sync_strip_range(scene):
if (strip_frame_start, round(strip_frame_end, 2)) != (frame_start, float(frame_end)):
subscriptions_remove()
# print('357 custom_frame_range_warning ')
# print(f'strip_frame_start {strip_frame_start} strip_frame_end {round(strip_frame_end, 2)} frame_start {frame_start} frame_end {float(frame_end)}')
bpy.ops.anim.custom_frame_range_warning('INVOKE_DEFAULT')
return
@@ -567,7 +572,6 @@ def subscribe_to_preview_frame_end(scene):
# Subscribing to preview frame end since it's not registering in the depsgraph
subscribe_preview_end = scene.path_resolve("frame_preview_end", False)
subscribe_use_preview = scene.path_resolve("use_preview_range", False)
# print('subscribe_to_preview_frame_end')
for subscribe in [subscribe_preview_end, subscribe_use_preview]:
bpy.msgbus.subscribe_rna(