129 lines
4.2 KiB
Python
129 lines
4.2 KiB
Python
# SPDX-FileCopyrightText: 2023 Blender Authors
|
|
#
|
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
"""NOTE: this is temporary UI code to show animation layers.
|
|
|
|
It is not meant for any particular use, just to have *something* in the UI.
|
|
"""
|
|
|
|
import threading
|
|
|
|
import bpy
|
|
from bpy.types import (
|
|
Panel,
|
|
WindowManager,
|
|
)
|
|
from bpy.props import PointerProperty
|
|
|
|
|
|
class VIEW3D_PT_animation_layers(Panel):
|
|
bl_space_type = 'VIEW_3D'
|
|
bl_region_type = 'UI'
|
|
bl_category = "Animation"
|
|
bl_label = "Baklava"
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
return context.preferences.experimental.use_animation_baklava and context.object
|
|
|
|
def draw(self, context) -> None:
|
|
layout = self.layout
|
|
layout.use_property_split = True
|
|
layout.use_property_decorate = False
|
|
|
|
# FIXME: this should be done in response to a message-bus callback, notifier, whatnot.
|
|
adt = context.object.animation_data
|
|
with _wm_selected_action_lock:
|
|
selected_action = getattr(adt, "action", None)
|
|
# Only set if it has to change, to avoid unnecessary notifies (that cause
|
|
# a redraw, that cause this code to be called, etc.)
|
|
if context.window_manager.selected_action != selected_action:
|
|
context.window_manager.selected_action = selected_action
|
|
|
|
col = layout.column()
|
|
# This has to go via an auxiliary property, as assigning an Animation
|
|
# data-block should be possible even when `context.object.animation_data`
|
|
# is `None`, and thus its `animation` property does not exist.
|
|
col.template_ID(context.window_manager, "selected_action")
|
|
|
|
col = layout.column(align=False)
|
|
anim = adt and adt.action
|
|
if anim:
|
|
binding_sub = col.column(align=True)
|
|
|
|
# Binding selector.
|
|
row = binding_sub.row(align=True)
|
|
row.prop(adt, "action_binding", text="Binding")
|
|
row.operator("anim.binding_unassign_object", text="", icon='X')
|
|
|
|
binding = anim.bindings.get(adt.action_binding, None)
|
|
if binding:
|
|
binding_sub.prop(binding, "name_display", text="Name")
|
|
|
|
internal_sub = binding_sub.box().column(align=True)
|
|
internal_sub.active = False
|
|
internal_sub.prop(adt, "action_binding_handle", text="handle")
|
|
if binding:
|
|
internal_sub.prop(binding, "name", text="Internal Name")
|
|
|
|
if adt:
|
|
col.prop(adt, "action_binding_name", text="ADT Binding Name")
|
|
else:
|
|
col.label(text="ADT Binding Name: -")
|
|
|
|
layout.separator()
|
|
|
|
if not anim:
|
|
layout.label(text="No layers")
|
|
return
|
|
|
|
for layer_idx, layer in reversed(list(enumerate(anim.layers))):
|
|
layerbox = layout.box()
|
|
col = layerbox.column(align=True)
|
|
col.prop(layer, "name", text="Layer {:d}:".format(layer_idx + 1))
|
|
col.prop(layer, "influence")
|
|
col.prop(layer, "mix_mode")
|
|
|
|
|
|
classes = (
|
|
VIEW3D_PT_animation_layers,
|
|
)
|
|
|
|
_wm_selected_action_lock = threading.Lock()
|
|
|
|
|
|
def _wm_selected_action_update(wm, context):
|
|
# Avoid responding to changes written by the panel above.
|
|
lock_ok = _wm_selected_action_lock.acquire(blocking=False)
|
|
if not lock_ok:
|
|
return
|
|
try:
|
|
if wm.selected_action is None and context.object.animation_data is None:
|
|
return
|
|
|
|
adt = context.object.animation_data_create()
|
|
if adt.action == wm.selected_action:
|
|
# Avoid writing to the property when the new value hasn't changed.
|
|
return
|
|
adt.action = wm.selected_action
|
|
finally:
|
|
_wm_selected_action_lock.release()
|
|
|
|
|
|
def register_props():
|
|
# Due to this hackyness, the WindowManager will increase the user count of
|
|
# the pointed-to Animation data-block.
|
|
WindowManager.selected_action = PointerProperty(
|
|
type=bpy.types.Action,
|
|
name="Action",
|
|
description="Action assigned to the active Object",
|
|
update=_wm_selected_action_update,
|
|
)
|
|
|
|
|
|
if __name__ == "__main__": # only for live edit.
|
|
register_, _ = bpy.utils.register_classes_factory(classes)
|
|
register_()
|
|
register_props()
|