[unity] Fixed "Create Hinge Chain" undo. Closes #1905.

This commit is contained in:
Harald Csaszar 2026-03-03 10:52:50 +01:00
parent 699206316b
commit f62cb8b540
2 changed files with 30 additions and 11 deletions

View File

@ -315,15 +315,21 @@ namespace Spine.Unity.Editor {
UnityEditor.EditorUtility.DisplayDialog("No parent SkeletonUtilityBone found!", "Please select the first physically moving chain node, having a parent GameObject with a SkeletonUtilityBone component attached.", "OK"); UnityEditor.EditorUtility.DisplayDialog("No parent SkeletonUtilityBone found!", "Please select the first physically moving chain node, having a parent GameObject with a SkeletonUtilityBone component attached.", "OK");
return; return;
} }
int undoGroup = Undo.GetCurrentGroup();
Undo.SetCurrentGroupName("Create 2D Hinge Chain");
float mass = 10; float mass = 10;
const float rotationLimit = 20.0f; const float rotationLimit = 20.0f;
SetSkeletonUtilityToFlipByRotation(); SetSkeletonUtilityToFlipByRotation();
Undo.RecordObject(kinematicParentUtilityBone, "Create 2D Hinge Chain");
kinematicParentUtilityBone.mode = SkeletonUtilityBone.Mode.Follow; kinematicParentUtilityBone.mode = SkeletonUtilityBone.Mode.Follow;
kinematicParentUtilityBone.position = kinematicParentUtilityBone.rotation = kinematicParentUtilityBone.scale = kinematicParentUtilityBone.zPosition = true; kinematicParentUtilityBone.position = kinematicParentUtilityBone.rotation = kinematicParentUtilityBone.scale = kinematicParentUtilityBone.zPosition = true;
GameObject commonParentObject = new GameObject(skeletonUtility.name + " HingeChain Parent " + utilityBone.name); GameObject commonParentObject = new GameObject(skeletonUtility.name + " HingeChain Parent " + utilityBone.name);
Undo.RegisterCreatedObjectUndo(commonParentObject, "Create 2D Hinge Chain");
ActivateBasedOnFlipDirection commonParentActivateOnFlip = commonParentObject.AddComponent<ActivateBasedOnFlipDirection>(); ActivateBasedOnFlipDirection commonParentActivateOnFlip = commonParentObject.AddComponent<ActivateBasedOnFlipDirection>();
commonParentActivateOnFlip.skeletonRenderer = skeletonUtility.skeletonRenderer; commonParentActivateOnFlip.skeletonRenderer = skeletonUtility.skeletonRenderer;
commonParentActivateOnFlip.skeletonGraphic = skeletonUtility.skeletonGraphic; commonParentActivateOnFlip.skeletonGraphic = skeletonUtility.skeletonGraphic;
@ -355,6 +361,7 @@ namespace Spine.Unity.Editor {
rootFollowerKinematic.transform, kinematicParentUtilityBone.transform); rootFollowerKinematic.transform, kinematicParentUtilityBone.transform);
Duplicate2DHierarchyForFlippedChains(normalChainParentObject, commonParentActivateOnFlip, skeletonUtility.transform, rotationLimit); Duplicate2DHierarchyForFlippedChains(normalChainParentObject, commonParentActivateOnFlip, skeletonUtility.transform, rotationLimit);
Undo.CollapseUndoOperations(undoGroup);
UnityEditor.Selection.activeGameObject = commonParentObject; UnityEditor.Selection.activeGameObject = commonParentObject;
} }
@ -362,13 +369,15 @@ namespace Spine.Unity.Editor {
Transform jointParent, Transform utilityParent) { Transform jointParent, Transform utilityParent) {
mass *= 0.75f; mass *= 0.75f;
Undo.RecordObject(bone, "Create 2D Hinge Chain");
bone.parentReference = utilityParent; bone.parentReference = utilityParent;
bone.transform.SetParent(groupObject, true); // we need a flat hierarchy of all Joint objects in Unity. // Note: we need a flat hierarchy of all Joint objects in Unity.
Undo.SetTransformParent(bone.transform, groupObject, "Create 2D Hinge Chain");
AttachRigidbodyAndCollider2D(bone); AttachRigidbodyAndCollider2D(bone);
bone.mode = SkeletonUtilityBone.Mode.Override; bone.mode = SkeletonUtilityBone.Mode.Override;
bone.scale = bone.position = bone.zPosition = false; bone.scale = bone.position = bone.zPosition = false;
HingeJoint2D joint = bone.gameObject.AddComponent<HingeJoint2D>(); HingeJoint2D joint = Undo.AddComponent<HingeJoint2D>(bone.gameObject);
joint.connectedBody = jointParent.GetComponent<Rigidbody2D>(); joint.connectedBody = jointParent.GetComponent<Rigidbody2D>();
joint.useLimits = true; joint.useLimits = true;
ApplyJoint2DAngleLimits(joint, rotationLimit, jointParent, bone.transform); ApplyJoint2DAngleLimits(joint, rotationLimit, jointParent, bone.transform);
@ -475,17 +484,23 @@ namespace Spine.Unity.Editor {
UnityEditor.EditorUtility.DisplayDialog("No parent SkeletonUtilityBone found!", "Please select the first physically moving chain node, having a parent GameObject with a SkeletonUtilityBone component attached.", "OK"); UnityEditor.EditorUtility.DisplayDialog("No parent SkeletonUtilityBone found!", "Please select the first physically moving chain node, having a parent GameObject with a SkeletonUtilityBone component attached.", "OK");
return; return;
} }
int undoGroup = Undo.GetCurrentGroup();
Undo.SetCurrentGroupName("Create 3D Hinge Chain");
float mass = 10; float mass = 10;
const float rotationLimit = 20.0f; const float rotationLimit = 20.0f;
SetSkeletonUtilityToFlipByRotation(); SetSkeletonUtilityToFlipByRotation();
Undo.RecordObject(kinematicParentUtilityBone, "Create 3D Hinge Chain");
kinematicParentUtilityBone.mode = SkeletonUtilityBone.Mode.Follow; kinematicParentUtilityBone.mode = SkeletonUtilityBone.Mode.Follow;
kinematicParentUtilityBone.position = kinematicParentUtilityBone.rotation = kinematicParentUtilityBone.scale = kinematicParentUtilityBone.zPosition = true; kinematicParentUtilityBone.position = kinematicParentUtilityBone.rotation = kinematicParentUtilityBone.scale = kinematicParentUtilityBone.zPosition = true;
// HingeChain Parent // HingeChain Parent
// Needs to be on top hierarchy level (not attached to the moving skeleton at least) for physics to apply proper momentum. // Needs to be on top hierarchy level (not attached to the moving skeleton at least) for physics to apply proper momentum.
GameObject chainParentObject = new GameObject(skeletonUtility.name + " HingeChain Parent " + utilityBone.name); GameObject chainParentObject = new GameObject(skeletonUtility.name + " HingeChain Parent " + utilityBone.name);
Undo.RegisterCreatedObjectUndo(chainParentObject, "Create 3D Hinge Chain");
FollowSkeletonUtilityRootRotation followRotationComponent = chainParentObject.AddComponent<FollowSkeletonUtilityRootRotation>(); FollowSkeletonUtilityRootRotation followRotationComponent = chainParentObject.AddComponent<FollowSkeletonUtilityRootRotation>();
followRotationComponent.reference = skeletonUtility.boneRoot; followRotationComponent.reference = skeletonUtility.boneRoot;
@ -501,6 +516,7 @@ namespace Spine.Unity.Editor {
CreateHingeChain(utilityBone, mass, rotationLimit, chainParentObject.transform, rootFollowerKinematic.transform); CreateHingeChain(utilityBone, mass, rotationLimit, chainParentObject.transform, rootFollowerKinematic.transform);
Undo.CollapseUndoOperations(undoGroup);
UnityEditor.Selection.activeGameObject = chainParentObject; UnityEditor.Selection.activeGameObject = chainParentObject;
} }
@ -509,12 +525,14 @@ namespace Spine.Unity.Editor {
mass *= 0.75f; mass *= 0.75f;
Undo.RecordObject(bone, "Create 3D Hinge Chain");
bone.parentReference = jointParent; bone.parentReference = jointParent;
bone.transform.SetParent(groupObject.transform, true); // we need a flat hierarchy of all Joint objects in Unity. // Note: we need a flat hierarchy of all Joint objects in Unity.
Undo.SetTransformParent(bone.transform, groupObject.transform, "Create 3D Hinge Chain");
AttachRigidbodyAndCollider(bone); AttachRigidbodyAndCollider(bone);
bone.mode = SkeletonUtilityBone.Mode.Override; bone.mode = SkeletonUtilityBone.Mode.Override;
HingeJoint joint = bone.gameObject.AddComponent<HingeJoint>(); HingeJoint joint = Undo.AddComponent<HingeJoint>(bone.gameObject);
joint.axis = Vector3.forward; joint.axis = Vector3.forward;
joint.connectedBody = jointParent.GetComponent<Rigidbody>(); joint.connectedBody = jointParent.GetComponent<Rigidbody>();
joint.useLimits = true; joint.useLimits = true;
@ -543,6 +561,7 @@ namespace Spine.Unity.Editor {
void SetSkeletonUtilityToFlipByRotation () { void SetSkeletonUtilityToFlipByRotation () {
if (!skeletonUtility.flipBy180DegreeRotation) { if (!skeletonUtility.flipBy180DegreeRotation) {
Undo.RecordObject(skeletonUtility, "Create Hinge Chain");
skeletonUtility.flipBy180DegreeRotation = true; skeletonUtility.flipBy180DegreeRotation = true;
Debug.Log("Set SkeletonUtility " + skeletonUtility.name + " to flip by rotation instead of negative scale (required).", skeletonUtility); Debug.Log("Set SkeletonUtility " + skeletonUtility.name + " to flip by rotation instead of negative scale (required).", skeletonUtility);
} }
@ -551,35 +570,35 @@ namespace Spine.Unity.Editor {
static void AttachRigidbodyAndCollider (SkeletonUtilityBone utilBone, bool enableCollider = false) { static void AttachRigidbodyAndCollider (SkeletonUtilityBone utilBone, bool enableCollider = false) {
if (utilBone.GetComponent<Collider>() == null) { if (utilBone.GetComponent<Collider>() == null) {
if (utilBone.bone.Data.Length == 0) { if (utilBone.bone.Data.Length == 0) {
SphereCollider sphere = utilBone.gameObject.AddComponent<SphereCollider>(); SphereCollider sphere = Undo.AddComponent<SphereCollider>(utilBone.gameObject);
sphere.radius = 0.1f; sphere.radius = 0.1f;
sphere.enabled = enableCollider; sphere.enabled = enableCollider;
} else { } else {
float length = utilBone.bone.Data.Length; float length = utilBone.bone.Data.Length;
BoxCollider box = utilBone.gameObject.AddComponent<BoxCollider>(); BoxCollider box = Undo.AddComponent<BoxCollider>(utilBone.gameObject);
box.size = new Vector3(length, length / 3f, 0.2f); box.size = new Vector3(length, length / 3f, 0.2f);
box.center = new Vector3(length / 2f, 0, 0); box.center = new Vector3(length / 2f, 0, 0);
box.enabled = enableCollider; box.enabled = enableCollider;
} }
} }
utilBone.gameObject.AddComponent<Rigidbody>(); Undo.AddComponent<Rigidbody>(utilBone.gameObject);
} }
static void AttachRigidbodyAndCollider2D (SkeletonUtilityBone utilBone, bool enableCollider = false) { static void AttachRigidbodyAndCollider2D (SkeletonUtilityBone utilBone, bool enableCollider = false) {
if (utilBone.GetComponent<Collider2D>() == null) { if (utilBone.GetComponent<Collider2D>() == null) {
if (utilBone.bone.Data.Length == 0) { if (utilBone.bone.Data.Length == 0) {
CircleCollider2D sphere = utilBone.gameObject.AddComponent<CircleCollider2D>(); CircleCollider2D sphere = Undo.AddComponent<CircleCollider2D>(utilBone.gameObject);
sphere.radius = 0.1f; sphere.radius = 0.1f;
sphere.enabled = enableCollider; sphere.enabled = enableCollider;
} else { } else {
float length = utilBone.bone.Data.Length; float length = utilBone.bone.Data.Length;
BoxCollider2D box = utilBone.gameObject.AddComponent<BoxCollider2D>(); BoxCollider2D box = Undo.AddComponent<BoxCollider2D>(utilBone.gameObject);
box.size = new Vector3(length, length / 3f, 0.2f); box.size = new Vector3(length, length / 3f, 0.2f);
box.offset = new Vector3(length / 2f, 0, 0); box.offset = new Vector3(length / 2f, 0, 0);
box.enabled = enableCollider; box.enabled = enableCollider;
} }
} }
utilBone.gameObject.AddComponent<Rigidbody2D>(); Undo.AddComponent<Rigidbody2D>(utilBone.gameObject);
} }
} }
} }

View File

@ -2,7 +2,7 @@
"name": "com.esotericsoftware.spine.spine-unity", "name": "com.esotericsoftware.spine.spine-unity",
"displayName": "spine-unity Runtime", "displayName": "spine-unity Runtime",
"description": "This plugin provides the spine-unity runtime core and examples. Spine Examples can be installed via the Samples tab.", "description": "This plugin provides the spine-unity runtime core and examples. Spine Examples can be installed via the Samples tab.",
"version": "4.3.50", "version": "4.3.51",
"unity": "2018.3", "unity": "2018.3",
"author": { "author": {
"name": "Esoteric Software", "name": "Esoteric Software",