diff --git a/.specstory/history/2026-02-18_23-39Z-character-migrator-workflow-integration.md b/.specstory/history/2026-02-18_23-39Z-character-migrator-workflow-integration.md index 9a48258..e29527a 100644 --- a/.specstory/history/2026-02-18_23-39Z-character-migrator-workflow-integration.md +++ b/.specstory/history/2026-02-18_23-39Z-character-migrator-workflow-integration.md @@ -15290,3 +15290,325 @@ migbbody shapekeys apparently is experiencing the same issue where the action sl --- +_**Agent (model default, mode Agent)**_ + +
Thought Process + +The user is saying that MigBBody shapekeys (run_mig_bbody_shapekeys) has an issue where "the action slot is not applied" - similar to something they may have experienced elsewhere (perhaps NLA or animation data where an action isn't being applied correctly). Let me look at the run_mig_bbody_shapekeys function to see how it handles the shape key action and what might be missing. +
+ +--- + + + + + +--- + + +
Tool use: **read_file_v2** • Read file: T:\Dynamic-Link-Manager\ops\migrator.py + +
+
+ +--- + + +
+Tool use: **ripgrep_raw_search** + + +Parameters: + +```json +{ + "pattern": "shapekey|shape_key|action|animation_data", + "path": "T:\\Dynamic-Link-Manager\\ops\\migrator.py", + "caseInsensitive": false +} +``` +Additional data: + +```json +{ + "isPruned": true, + "pattern": "shapekey|shape_key|action|animation_data", + "path": "T:\\Dynamic-Link-Manager\\ops\\migrator.py", + "outputMode": "content", + "totalFiles": 1, + "totalMatches": 49, + "topFiles": [ + { + "uri": "ops\\migrator.py", + "matchCount": 49 + } + ] +} +``` +Status: **completed** + + +
+
+ +--- + +
Thought Process + +I see. For MigNLA they added handling for Blender 4.4+ "slotted actions" - they copy `action_slot`, `last_slot_identifier`, `action_blend_type`, `action_extrapolation`, `action_influence` so the action slot is properly applied. For the base body shape keys, the code only does: +- ob.data.shape_keys.animation_data_create() if no animation_data +- Then finds an action by name (body_name + "Action", etc.) and sets ob.data.shape_keys.animation_data.action = action + +So it's not copying the action from the *original* base body - it's looking up an action by naming convention. And it's not copying the action_slot / slot-related props on the shape_keys' animation_data. So two potential issues: +1. The action might need to come from orig_base.data.shape_keys.animation_data.action (copy from original base body) rather than (or in addition to) looking up by name. +2. Even when we set .action, in Blender 4.4+ the "action slot" might need to be set (action_slot, last_slot_identifier, action_blend_type, etc.) for it to actually show/apply. + +Let me look at what MigNLA does for the action slot again to mirror that for shape_keys.animation_data. +
+ +--- + + +Checking how MigNLA applies the action slot so we can mirror it for shape keys: + + +--- + + +
Tool use: **read_file_v2** • Read file: T:\Dynamic-Link-Manager\ops\migrator.py + +
+
+ +--- + +
Thought Process + +So for shape keys we need to: +1. Prefer copying the action (and slot) from the *original* base body's shape_keys.animation_data, not just look up by name. +2. When setting the action on rep's shape_keys.animation_data, also set last_slot_identifier (before action), then action, then action_slot, then action_blend_type, action_extrapolation, action_influence. + +Let me update run_mig_bbody_shapekeys to: +- Get orig_sk_ad = orig_base.data.shape_keys.animation_data if orig_base and orig_base.data.shape_keys +- If orig_sk_ad and orig_sk_ad.action: use that action; also copy slot props (last_slot_identifier, action_slot, action_blend_type, action_extrapolation, action_influence) to rep's shape_keys.animation_data +- Else: keep current fallback (look up action by name) but when assigning also try to copy slot-related props if they exist on the rep's animation_data (we might not have an origin to copy from, so we just set action and any slot props we can set generically - actually for fallback we only have the action by name, we don't have an "orig" shape_keys anim_data to copy slot from). So the main fix is: when we have orig_base and orig_base.data.shape_keys.animation_data with an action, use that action and copy all slot-related props from orig base body shape_keys to rep base body shape_keys. When we don't have that (name lookup path), we still set .action but we could try to set last_slot_identifier/action_slot if the rep's anim_data has those - but we'd have nothing to copy from. So the fix is: copy from orig base body shape_keys.animation_data when available (action + slot props), else fall back to name lookup and set action only. +
+ +--- + + +Applying MigNLA's action-slot handling to the base body's shape_keys: copy the action and slot props from the original base body's shape_keys.animation_data when present. + + +--- + + + +
Tool use: **edit_file_v2** • Edit file: T:\Dynamic-Link-Manager\ops\migrator.py + +
+ +
+ +--- + +
Thought Process + +When we don't have orig_sk_ad (no orig base body or no shape_keys on orig), we still look up action by name and set sk_ad.action = action, but we don't set any slot props (nothing to copy from). That's correct. Let me double-check: if action is set from name lookup, we still do sk_ad.action = action - yes, that's inside "if action:" and we do "sk_ad.action = action" unconditionally there. The "if orig_sk_ad" parts only add the slot props when we have an origin. Good. +
+ +--- + + + + + +--- + + +
+Tool use: **read_lints** + + +Parameters: + +```json +{ + "paths": [ + "T:\\Dynamic-Link-Manager\\ops\\migrator.py" + ] +} +``` +Result: + +```json +{ + "linterErrorsByFile": [ + { + "relativeWorkspacePath": "T:\\Dynamic-Link-Manager\\ops\\migrator.py" + } + ] +} +``` +Status: **completed** + + +
+
+ +--- + +
Thought Process + +Done. Summary for user. +
+ +--- + + +Summary of changes: + +**MigBBody shape keys – action and slot** + +1. **Source of the action** + The action is now taken from the **original** base body when possible: `orig_base.data.shape_keys.animation_data.action`. The previous name-based lookup (`body_name + "Action"`, etc.) is only used when the original has no shape key animation data. + +2. **Blender 4.4+ action slot** + When we have original base body shape key `animation_data`, we now copy the same slot-related fields as in MigNLA: + - Set **`last_slot_identifier`** before assigning the action (so the slot resolves correctly). + - Set **`action`**. + - Set **`action_slot`** from the original (with try/except). + - Copy **`action_blend_type`**, **`action_extrapolation`**, **`action_influence`** from the original. + +So the replacement base body’s shape key block gets the same action and the same slot/settings as the original, which should fix the action slot not being applied. If there is no original base body (or no shape key animation on it), behavior is unchanged: we still assign an action by name and do not set slot props. + +--- + +_**User**_ + +bump 0.1.1 and concisely summarize the last 5 commits in the changelog. + +--- + +_**Agent (model default, mode Agent)**_ + + + +--- + + + +--- + + +
Tool use: **run_terminal_command_v2** + +
+
+ +--- + + +
+Tool use: **glob_file_search** + +Status: **loading** + + +
+
+ +--- + + +
+Tool use: **ripgrep_raw_search** + +Status: **loading** + + +
+
+ +--- + + + +--- + + + +--- + + +
Tool use: **run_terminal_command_v2** + +
+
+ +--- + + +
+Tool use: **read_file_v2** + +Status: **loading** + + +
+
+ +--- + + +
+Tool use: **ripgrep_raw_search** + +Status: **loading** + + +
+
+ +--- + + + +--- + + + +--- + + + +
Tool use: **edit_file_v2** • Edit file: T:\Dynamic-Link-Manager\blender_manifest.toml + +Status: **loading** + +
+ +
+ +--- + + + +
Tool use: **edit_file_v2** • Edit file: T:\Dynamic-Link-Manager\CHANGELOG.md + +Status: **loading** + +
+ +
+ +--- + + + +--- + + + +--- + diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b5d6ff..c959f46 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## [0.1.1] - 2026-02-19 + +### Fixed +- MigBBody shapekeys: action slot not applying; now copy action and slot props (last_slot_identifier, action_slot, blend/extrapolation/influence) from original base body. +- RetargRelations: skip objects in Original Character’s hierarchy (linked collection); only retarget relations outside orig’s hierarchy. +- MigBoneConst: copy all constraint properties and targets (RNA POINTER/COLLECTION with orig→rep retarget), not just type/name/mute/influence. +- AnimLayers: detect/mirror via RNA (obj.als.turn_on) so “Animation Layer attributes migrated” reports correctly. +- MigCustProps: recursive id-property copy for nested groups; debug logging for armature/bone keys. + ## [0.1.0] - 2026-02-19 ### Added diff --git a/blender_manifest.toml b/blender_manifest.toml index 25eb737..6ace7f5 100644 --- a/blender_manifest.toml +++ b/blender_manifest.toml @@ -3,7 +3,7 @@ schema_version = "1.0.0" id = "dynamiclinkmanager" name = "Dynamic Link Manager" tagline = "Character migrator and linked library tools" -version = "0.1.0" +version = "0.1.1" type = "add-on" # Optional: Semantic Versioning