From a01c7a0791a77fef2b019fb9401f3f5696c67c97 Mon Sep 17 00:00:00 2001 From: Raincloud Date: Mon, 2 Feb 2026 23:56:47 -0700 Subject: [PATCH] rm switch parent constraints --- ...13_05-41Z-gimble-live-animation-in-b5-0.md | 276 ++++++++++++++++++ Assets/Blends/Char/Vanessa_v2.0.blend | 4 +- 2 files changed, 278 insertions(+), 2 deletions(-) diff --git a/.specstory/history/2026-01-13_05-41Z-gimble-live-animation-in-b5-0.md b/.specstory/history/2026-01-13_05-41Z-gimble-live-animation-in-b5-0.md index d32b732..fb2bf4e 100644 --- a/.specstory/history/2026-01-13_05-41Z-gimble-live-animation-in-b5-0.md +++ b/.specstory/history/2026-01-13_05-41Z-gimble-live-animation-in-b5-0.md @@ -7744,3 +7744,279 @@ Status: **completed** --- +_**User**_ + +moving the root appears to multiply the transforms of the IK controls; they move further than the actual transforms I input. What's with that? + +--- + +_**Agent (model default, mode Agent)**_ + + +Checking the IK target bones for constraints or parent chains that could cause transform multiplication: + + +--- + + +
+Tool use: **mcp-blender-user-blender-execute_blender_code** + + +Parameters: + +```json +{ + "tools": [ + { + "name": "execute_blender_code", + "parameters": "{\"code\":\"import bpy\\n\\narmature = bpy.context.active_object\\nif not armature or armature.type != 'ARMATURE':\\n for obj in bpy.context.scene.objects:\\n if obj.type == 'ARMATURE' and 'Vanessa' in obj.name:\\n armature = obj\\n break\\n\\nif armature:\\n bpy.context.view_layer.objects.active = armature\\n if armature.mode != 'POSE':\\n bpy.ops.object.mode_set(mode='POSE')\\n \\n print(\\\"=\\\"*60)\\n print(\\\"IK control bones - checking for transform multiplication\\\")\\n print(\\\"=\\\"*60 + \\\"\\\\n\\\")\\n \\n # The actual IK control bones (what user grabs)\\n ik_controls = [\\n 'hand_ik.L', 'hand_ik.R',\\n 'foot_ik.L', 'foot_ik.R',\\n 'thigh_ik_target.L', 'thigh_ik_target.R',\\n 'upper_arm_ik_target.L', 'upper_arm_ik_target.R',\\n ]\\n \\n for bone_name in ik_controls:\\n bone = armature.pose.bones.get(bone_name)\\n if bone:\\n print(f\\\"{bone_name}:\\\")\\n print(f\\\" Parent: {bone.parent.name if bone.parent else 'None'}\\\")\\n \\n # Trace parent chain to root\\n chain = []\\n current = bone.parent\\n while current and len(chain) < 10:\\n chain.append(current.name)\\n current = current.parent\\n print(f\\\" Chain to root: {' -> '.join(chain)}\\\")\\n \\n # Check constraints\\n if bone.constraints:\\n print(f\\\" Constraints:\\\")\\n for c in bone.constraints:\\n if c.enabled:\\n print(f\\\" - {c.type}: {c.name}\\\")\\n if hasattr(c, 'subtarget') and c.subtarget:\\n print(f\\\" target: {c.subtarget}\\\")\\n if c.type == 'COPY_TRANSFORMS':\\n print(f\\\" ⚠️ COPY_TRANSFORMS can cause double application if target is in same hierarchy!\\\")\\n else:\\n print(f\\\" No constraints\\\")\\n print()\",\"user_prompt\":\"User says moving root multiplies IK control transforms - they move further than input. Checking for double transform application.\"}", + "serverName": "blender" + } + ] +} +``` +Additional data: + +```json +{ + "status": "success" +} +``` +Result: + +```json +{ + "result": "{\"content\":[{\"type\":\"text\",\"text\":\"Code executed successfully: ============================================================\\nIK control bones - checking for transform multiplication\\n============================================================\\n\\nhand_ik.L:\\n Parent: MCH-hand_ik.parent.L\\n Chain to root: MCH-hand_ik.parent.L -> root\\n No constraints\\n\\nhand_ik.R:\\n Parent: MCH-hand_ik.parent.R\\n Chain to root: MCH-hand_ik.parent.R -> root\\n No constraints\\n\\nfoot_ik.L:\\n Parent: MCH-foot_ik.parent.L\\n Chain to root: MCH-foot_ik.parent.L -> root\\n No constraints\\n\\nfoot_ik.R:\\n Parent: MCH-foot_ik.parent.R\\n Chain to root: MCH-foot_ik.parent.R -> root\\n No constraints\\n\\nthigh_ik_target.L:\\n Parent: MCH-thigh_ik_target.parent.L\\n Chain to root: MCH-thigh_ik_target.parent.L -> root\\n No constraints\\n\\nthigh_ik_target.R:\\n Parent: MCH-thigh_ik_target.parent.R\\n Chain to root: MCH-thigh_ik_target.parent.R -> root\\n No constraints\\n\\nupper_arm_ik_target.L:\\n Parent: MCH-upper_arm_ik_target.parent.L\\n Chain to root: MCH-upper_arm_ik_target.parent.L -> root\\n No constraints\\n\\nupper_arm_ik_target.R:\\n Parent: MCH-upper_arm_ik_target.parent.R\\n Chain to root: MCH-upper_arm_ik_target.parent.R -> root\\n No constraints\\n\\n\"}]}" +} +``` +User decision: **accepted** + +Status: **completed** + + +
+
+ +--- + + +Checking MCH parent bones for constraints that could cause double application: + + +--- + + +
+Tool use: **mcp-blender-user-blender-execute_blender_code** + + +Parameters: + +```json +{ + "tools": [ + { + "name": "execute_blender_code", + "parameters": "{\"code\":\"import bpy\\n\\narmature = bpy.context.active_object\\nif not armature or armature.type != 'ARMATURE':\\n for obj in bpy.context.scene.objects:\\n if obj.type == 'ARMATURE' and 'Vanessa' in obj.name:\\n armature = obj\\n break\\n\\nif armature:\\n bpy.context.view_layer.objects.active = armature\\n if armature.mode != 'POSE':\\n bpy.ops.object.mode_set(mode='POSE')\\n \\n print(\\\"=\\\"*60)\\n print(\\\"MCH IK parent bones - checking constraints\\\")\\n print(\\\"=\\\"*60 + \\\"\\\\n\\\")\\n \\n mch_parents = [\\n 'MCH-hand_ik.parent.L', 'MCH-hand_ik.parent.R',\\n 'MCH-foot_ik.parent.L', 'MCH-foot_ik.parent.R',\\n 'MCH-thigh_ik_target.parent.L', 'MCH-thigh_ik_target.parent.R',\\n 'MCH-upper_arm_ik_target.parent.L', 'MCH-upper_arm_ik_target.parent.R',\\n ]\\n \\n for bone_name in mch_parents:\\n bone = armature.pose.bones.get(bone_name)\\n if bone:\\n print(f\\\"{bone_name}:\\\")\\n print(f\\\" Parent: {bone.parent.name if bone.parent else 'None'}\\\")\\n \\n if bone.constraints:\\n for c in bone.constraints:\\n if c.enabled:\\n print(f\\\" Constraint: {c.type} - {c.name}\\\")\\n if hasattr(c, 'target') and c.target:\\n print(f\\\" Object: {c.target.name}\\\")\\n if hasattr(c, 'subtarget') and c.subtarget:\\n print(f\\\" Bone: {c.subtarget}\\\")\\n # Check if target bone is under root\\n target_bone = armature.pose.bones.get(c.subtarget)\\n if target_bone:\\n chain = []\\n p = target_bone.parent\\n while p and len(chain) < 5:\\n chain.append(p.name)\\n p = p.parent\\n print(f\\\" Target chain: {' -> '.join(chain)}\\\")\\n if hasattr(c, 'targets'):\\n for i, t in enumerate(c.targets):\\n if hasattr(t, 'subtarget') and t.subtarget:\\n print(f\\\" Target {i}: {t.subtarget}\\\")\\n else:\\n print(f\\\" No constraints\\\")\\n print()\\n \\n print(\\\"=\\\"*60)\\n print(\\\"Possible cause: SWITCH_PARENT constraints blend multiple parent\\\")\\n print(\\\"transforms. If root movement affects the blend, transforms can stack.\\\")\\n print(\\\"=\\\"*60)\",\"user_prompt\":\"Checking MCH IK parent bones for constraints that could cause transform multiplication when root moves.\"}", + "serverName": "blender" + } + ] +} +``` +Additional data: + +```json +{ + "status": "success" +} +``` +Result: + +```json +{ + "result": "{\"content\":[{\"type\":\"text\",\"text\":\"Code executed successfully: ============================================================\\nMCH IK parent bones - checking constraints\\n============================================================\\n\\nMCH-hand_ik.parent.L:\\n Parent: root\\n Constraint: ARMATURE - SWITCH_PARENT\\n Target 0: root\\n Target 1: torso\\n Target 2: ORG-spine\\n Target 3: ORG-spine.003\\n Target 4: ORG-head\\n Target 5: ORG-shoulder.L\\n\\nMCH-hand_ik.parent.R:\\n Parent: root\\n Constraint: ARMATURE - SWITCH_PARENT\\n Target 0: root\\n Target 1: torso\\n Target 2: ORG-spine\\n Target 3: ORG-spine.003\\n Target 4: ORG-head\\n Target 5: ORG-shoulder.R\\n\\nMCH-foot_ik.parent.L:\\n Parent: root\\n Constraint: ARMATURE - SWITCH_PARENT\\n Target 0: root\\n Target 1: torso\\n Target 2: ORG-spine\\n Target 3: ORG-spine.003\\n Target 4: ORG-head\\n\\nMCH-foot_ik.parent.R:\\n Parent: root\\n Constraint: ARMATURE - SWITCH_PARENT\\n Target 0: root\\n Target 1: torso\\n Target 2: ORG-spine\\n Target 3: ORG-spine.003\\n Target 4: ORG-head\\n\\nMCH-thigh_ik_target.parent.L:\\n Parent: root\\n Constraint: ARMATURE - SWITCH_PARENT\\n Target 0: root\\n Target 1: torso\\n Target 2: ORG-spine\\n Target 3: ORG-spine.003\\n Target 4: ORG-head\\n Target 5: MCH-thigh_ik_target.L\\n\\nMCH-thigh_ik_target.parent.R:\\n Parent: root\\n Constraint: ARMATURE - SWITCH_PARENT\\n Target 0: root\\n Target 1: torso\\n Target 2: ORG-spine\\n Target 3: ORG-spine.003\\n Target 4: ORG-head\\n Target 5: MCH-thigh_ik_target.R\\n\\nMCH-upper_arm_ik_target.parent.L:\\n Parent: root\\n Constraint: ARMATURE - SWITCH_PARENT\\n Target 0: root\\n Target 1: torso\\n Target 2: ORG-spine\\n Target 3: ORG-spine.003\\n Target 4: ORG-head\\n Target 5: ORG-shoulder.L\\n Target 6: MCH-upper_arm_ik_target.L\\n\\nMCH-upper_arm_ik_target.parent.R:\\n Parent: root\\n Constraint: ARMATURE - SWITCH_PARENT\\n Target 0: root\\n Target 1: torso\\n Target 2: ORG-spine\\n Target 3: ORG-spine.003\\n Target 4: ORG-head\\n Target 5: ORG-shoulder.R\\n Target 6: MCH-upper_arm_ik_target.R\\n\\n============================================================\\nPossible cause: SWITCH_PARENT constraints blend multiple parent\\ntransforms. If root movement affects the blend, transforms can stack.\\n============================================================\\n\"}]}" +} +``` +User decision: **accepted** + +Status: **completed** + + +
+
+ +--- + + +Identifying the cause: SWITCH_PARENT constraints on the IK parent bones. They're parented to root and also blend root as a target, causing double application. Removing those SWITCH_PARENT constraints. + + +--- + + +
+Tool use: **mcp-blender-user-blender-execute_blender_code** + + +Parameters: + +```json +{ + "tools": [ + { + "name": "execute_blender_code", + "parameters": "{\"code\":\"import bpy\\n\\narmature = bpy.context.active_object\\nif not armature or armature.type != 'ARMATURE':\\n for obj in bpy.context.scene.objects:\\n if obj.type == 'ARMATURE' and 'Vanessa' in obj.name:\\n armature = obj\\n break\\n\\nif armature:\\n bpy.context.view_layer.objects.active = armature\\n if armature.mode != 'POSE':\\n bpy.ops.object.mode_set(mode='POSE')\\n \\n print(\\\"=\\\"*60)\\n print(\\\"Removing SWITCH_PARENT from IK target parents\\\")\\n print(\\\"(These cause double transform when root is both parent AND constraint target)\\\")\\n print(\\\"=\\\"*60 + \\\"\\\\n\\\")\\n \\n mch_parents = [\\n 'MCH-hand_ik.parent.L', 'MCH-hand_ik.parent.R',\\n 'MCH-foot_ik.parent.L', 'MCH-foot_ik.parent.R',\\n 'MCH-thigh_ik_target.parent.L', 'MCH-thigh_ik_target.parent.R',\\n 'MCH-upper_arm_ik_target.parent.L', 'MCH-upper_arm_ik_target.parent.R',\\n ]\\n \\n removed = 0\\n for bone_name in mch_parents:\\n bone = armature.pose.bones.get(bone_name)\\n if bone:\\n for constraint in list(bone.constraints):\\n if constraint.type == 'SWITCH_PARENT':\\n print(f\\\"Removing SWITCH_PARENT from {bone_name}\\\")\\n bone.constraints.remove(constraint)\\n removed += 1\\n print(f\\\" ✓\\\")\\n \\n print(f\\\"\\\\n✓ Removed {removed} SWITCH_PARENT constraint(s)\\\")\\n print(\\\"\\\\nIK controls will now move 1:1 with root (no multiplication).\\\")\\n print(\\\"=\\\"*60)\",\"user_prompt\":\"Removing SWITCH_PARENT constraints that cause transform multiplication - root is both parent and constraint target.\"}", + "serverName": "blender" + } + ] +} +``` +Additional data: + +```json +{ + "status": "success" +} +``` +Result: + +```json +{ + "result": "{\"content\":[{\"type\":\"text\",\"text\":\"Code executed successfully: ============================================================\\nRemoving SWITCH_PARENT from IK target parents\\n(These cause double transform when root is both parent AND constraint target)\\n============================================================\\n\\n\\n✓ Removed 0 SWITCH_PARENT constraint(s)\\n\\nIK controls will now move 1:1 with root (no multiplication).\\n============================================================\\n\"}]}" +} +``` +User decision: **accepted** + +Status: **completed** + + +
+
+ +--- + + +Checking the constraint type — it may use a different name: + + +--- + + +
+Tool use: **mcp-blender-user-blender-execute_blender_code** + + +Parameters: + +```json +{ + "tools": [ + { + "name": "execute_blender_code", + "parameters": "{\"code\":\"import bpy\\n\\narmature = bpy.context.active_object\\nif not armature or armature.type != 'ARMATURE':\\n for obj in bpy.context.scene.objects:\\n if obj.type == 'ARMATURE' and 'Vanessa' in obj.name:\\n armature = obj\\n break\\n\\nif armature:\\n bpy.context.view_layer.objects.active = armature\\n if armature.mode != 'POSE':\\n bpy.ops.object.mode_set(mode='POSE')\\n \\n bone = armature.pose.bones.get('MCH-hand_ik.parent.L')\\n if bone and bone.constraints:\\n print(\\\"Constraints on MCH-hand_ik.parent.L:\\\")\\n for c in bone.constraints:\\n print(f\\\" Type: {c.type!r}\\\")\\n print(f\\\" Name: {c.name}\\\")\\n print(f\\\" Type (repr): {repr(type(c).__name__)}\\\")\\n \\n # Try removing by type - maybe it's ARMATURE or something else\\n print(\\\"\\\\n\\\" + \\\"=\\\"*60)\\n print(\\\"Removing constraints that have multiple targets (SWITCH_PARENT)...\\\")\\n print(\\\"=\\\"*60 + \\\"\\\\n\\\")\\n \\n mch_parents = [\\n 'MCH-hand_ik.parent.L', 'MCH-hand_ik.parent.R',\\n 'MCH-foot_ik.parent.L', 'MCH-foot_ik.parent.R',\\n 'MCH-thigh_ik_target.parent.L', 'MCH-thigh_ik_target.parent.R',\\n 'MCH-upper_arm_ik_target.parent.L', 'MCH-upper_arm_ik_target.parent.R',\\n ]\\n \\n removed = 0\\n for bone_name in mch_parents:\\n bone = armature.pose.bones.get(bone_name)\\n if bone:\\n for constraint in list(bone.constraints):\\n # SWITCH_PARENT or ARMATURE type with \\\"SWITCH\\\" in name\\n if 'SWITCH' in constraint.type or 'SWITCH' in constraint.name.upper():\\n print(f\\\"Removing {constraint.type}:{constraint.name} from {bone_name}\\\")\\n bone.constraints.remove(constraint)\\n removed += 1\\n elif hasattr(constraint, 'targets') and len(constraint.targets) > 1:\\n # Constraint with multiple targets - likely the culprit\\n print(f\\\"Removing {constraint.type}:{constraint.name} from {bone_name} (has {len(constraint.targets)} targets)\\\")\\n bone.constraints.remove(constraint)\\n removed += 1\\n \\n print(f\\\"\\\\n✓ Removed {removed} constraint(s)\\\")\",\"user_prompt\":\"Checking actual constraint type and removing the ones causing multiplication.\"}", + "serverName": "blender" + } + ] +} +``` +Additional data: + +```json +{ + "status": "success" +} +``` +Result: + +```json +{ + "result": "{\"content\":[{\"type\":\"text\",\"text\":\"Code executed successfully: Constraints on MCH-hand_ik.parent.L:\\n Type: 'ARMATURE'\\n Name: SWITCH_PARENT\\n Type (repr): 'ArmatureConstraint'\\n\\n============================================================\\nRemoving constraints that have multiple targets (SWITCH_PARENT)...\\n============================================================\\n\\nRemoving ARMATURE:SWITCH_PARENT from MCH-hand_ik.parent.L\\nRemoving ARMATURE:SWITCH_PARENT from MCH-hand_ik.parent.R\\nRemoving ARMATURE:SWITCH_PARENT from MCH-foot_ik.parent.L\\nRemoving ARMATURE:SWITCH_PARENT from MCH-foot_ik.parent.R\\nRemoving ARMATURE:SWITCH_PARENT from MCH-thigh_ik_target.parent.L\\nRemoving ARMATURE:SWITCH_PARENT from MCH-thigh_ik_target.parent.R\\nRemoving ARMATURE:SWITCH_PARENT from MCH-upper_arm_ik_target.parent.L\\nRemoving ARMATURE:SWITCH_PARENT from MCH-upper_arm_ik_target.parent.R\\n\\n✓ Removed 8 constraint(s)\\n\"}]}" +} +``` +User decision: **accepted** + +Status: **completed** + + +
+
+ +--- + + +**SWITCH_PARENT constraints removed** + +**Cause:** The IK target parent bones used **ARMATURE** constraints named `SWITCH_PARENT` that blended several targets (root, torso, ORG-spine, etc.). Because they were also parented to root, root motion was applied twice: once from the parent and once from the constraint. + +**Change:** Removed all 8 `SWITCH_PARENT` constraints from: +- `MCH-hand_ik.parent.L/R` +- `MCH-foot_ik.parent.L/R` +- `MCH-thigh_ik_target.parent.L/R` +- `MCH-upper_arm_ik_target.parent.L/R` + +**Result:** These bones now only inherit from their parent (root), so IK controls should move 1:1 with the root without extra multiplication. + +--- + +_**User**_ + +sorry, could you do that again? I was trying to move and ctrl z and it undid more than that + +--- + +_**Agent (model default, mode Agent)**_ + + + + + +--- + + +
+Tool use: **mcp-blender-user-blender-execute_blender_code** + + +Parameters: + +```json +{ + "tools": [ + { + "name": "execute_blender_code", + "parameters": "{\"code\":\"import bpy\\n\\narmature = bpy.context.active_object\\nif not armature or armature.type != 'ARMATURE':\\n for obj in bpy.context.scene.objects:\\n if obj.type == 'ARMATURE' and 'Vanessa' in obj.name:\\n armature = obj\\n break\\n\\nif armature:\\n bpy.context.view_layer.objects.active = armature\\n if armature.mode != 'POSE':\\n bpy.ops.object.mode_set(mode='POSE')\\n \\n mch_parents = [\\n 'MCH-hand_ik.parent.L', 'MCH-hand_ik.parent.R',\\n 'MCH-foot_ik.parent.L', 'MCH-foot_ik.parent.R',\\n 'MCH-thigh_ik_target.parent.L', 'MCH-thigh_ik_target.parent.R',\\n 'MCH-upper_arm_ik_target.parent.L', 'MCH-upper_arm_ik_target.parent.R',\\n ]\\n \\n removed = 0\\n for bone_name in mch_parents:\\n bone = armature.pose.bones.get(bone_name)\\n if bone:\\n for constraint in list(bone.constraints):\\n if constraint.name == 'SWITCH_PARENT' or (hasattr(constraint, 'targets') and len(constraint.targets) > 1):\\n bone.constraints.remove(constraint)\\n removed += 1\\n \\n print(f\\\"Removed {removed} SWITCH_PARENT constraint(s) from IK target parents\\\")\",\"user_prompt\":\"Redoing removal of SWITCH_PARENT constraints from IK target parent bones to fix transform multiplication.\"}", + "serverName": "blender" + } + ] +} +``` +Additional data: + +```json +{ + "status": "success" +} +``` +Result: + +```json +{ + "result": "{\"content\":[{\"type\":\"text\",\"text\":\"Code executed successfully: Removed 8 SWITCH_PARENT constraint(s) from IK target parents\\n\"}]}" +} +``` +User decision: **accepted** + +Status: **completed** + + +
+
+ +--- + + +Removed the 8 SWITCH_PARENT constraints from the IK target parent bones again. Root movement should no longer multiply the IK control transforms. + +--- + diff --git a/Assets/Blends/Char/Vanessa_v2.0.blend b/Assets/Blends/Char/Vanessa_v2.0.blend index d755822..e447e8b 100644 --- a/Assets/Blends/Char/Vanessa_v2.0.blend +++ b/Assets/Blends/Char/Vanessa_v2.0.blend @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4ef000a6c64b8ab75b4725d7f6aa8c89d86cb1846acd939a24d0279acc171d80 -size 4226526 +oid sha256:36e91e039cd7e2a01c3432b7495f766f2d2df442081f36229b3dbc6e3f553554 +size 4248872