mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-05 06:44:56 +08:00
[unity] BoneFollowerGraphic Component.
This commit is contained in:
parent
9223881909
commit
16821f0bf7
@ -135,13 +135,14 @@ RectTransform:
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_Children:
|
||||
- {fileID: 759111375}
|
||||
- {fileID: 189134935}
|
||||
m_Father: {fileID: 289700665}
|
||||
m_RootOrder: 0
|
||||
m_RootOrder: 1
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
||||
m_AnchoredPosition: {x: -13.605, y: 239}
|
||||
m_AnchoredPosition: {x: -13.604996, y: 239}
|
||||
m_SizeDelta: {x: 491, y: 708}
|
||||
m_Pivot: {x: 0.5, y: 0.14047737}
|
||||
--- !u!114 &57002145
|
||||
@ -165,6 +166,8 @@ MonoBehaviour:
|
||||
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
|
||||
skeletonDataAsset: {fileID: 11400000, guid: 3c48535ae5679204c950a22a7caaa5a4, type: 2}
|
||||
initialSkinName: default
|
||||
initialFlipX: 0
|
||||
initialFlipY: 0
|
||||
startingAnimation: main
|
||||
startingLoop: 1
|
||||
timeScale: 1
|
||||
@ -185,6 +188,99 @@ CanvasRenderer:
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 57002143}
|
||||
--- !u!1 &140863499
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
serializedVersion: 5
|
||||
m_Component:
|
||||
- component: {fileID: 140863500}
|
||||
- component: {fileID: 140863503}
|
||||
- component: {fileID: 140863502}
|
||||
- component: {fileID: 140863501}
|
||||
m_Layer: 5
|
||||
m_Name: Detached BoneFollowerGraphic
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &140863500
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 140863499}
|
||||
m_LocalRotation: {x: -0, y: -0, z: 0.6421143, w: 0.766609}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_Children: []
|
||||
m_Father: {fileID: 289700665}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
||||
m_AnchoredPosition: {x: -11.670258, y: 578.2387}
|
||||
m_SizeDelta: {x: 100, y: 54.64}
|
||||
m_Pivot: {x: -0.15, y: -2.04}
|
||||
--- !u!114 &140863501
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 140863499}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 0
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI,
|
||||
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
|
||||
m_FontData:
|
||||
m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
|
||||
m_FontSize: 50
|
||||
m_FontStyle: 1
|
||||
m_BestFit: 0
|
||||
m_MinSize: 5
|
||||
m_MaxSize: 50
|
||||
m_Alignment: 4
|
||||
m_AlignByGeometry: 0
|
||||
m_RichText: 1
|
||||
m_HorizontalOverflow: 1
|
||||
m_VerticalOverflow: 1
|
||||
m_LineSpacing: 1
|
||||
m_Text: Hello
|
||||
--- !u!222 &140863502
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 140863499}
|
||||
--- !u!114 &140863503
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 140863499}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: b42a195b47491d34b9bcbc40898bcb29, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
skeletonGraphic: {fileID: 57002145}
|
||||
initializeOnAwake: 1
|
||||
boneName: head
|
||||
followBoneRotation: 1
|
||||
followSkeletonFlip: 1
|
||||
followLocalScale: 0
|
||||
followZPosition: 1
|
||||
--- !u!1 &189134934
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@ -213,7 +309,7 @@ RectTransform:
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_Children: []
|
||||
m_Father: {fileID: 57002144}
|
||||
m_RootOrder: 0
|
||||
m_RootOrder: 1
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 1}
|
||||
m_AnchorMax: {x: 0.5, y: 1}
|
||||
@ -379,6 +475,7 @@ RectTransform:
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_Children:
|
||||
- {fileID: 140863500}
|
||||
- {fileID: 57002144}
|
||||
- {fileID: 1384013133}
|
||||
m_Father: {fileID: 2133858527}
|
||||
@ -478,6 +575,99 @@ Transform:
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!1 &759111374
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
serializedVersion: 5
|
||||
m_Component:
|
||||
- component: {fileID: 759111375}
|
||||
- component: {fileID: 759111378}
|
||||
- component: {fileID: 759111377}
|
||||
- component: {fileID: 759111376}
|
||||
m_Layer: 5
|
||||
m_Name: Child BoneFollowerGraphic
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &759111375
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 759111374}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0.012748675, w: 0.99991876}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_Children: []
|
||||
m_Father: {fileID: 57002144}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
||||
m_AnchoredPosition: {x: 214.28879, y: 127.327515}
|
||||
m_SizeDelta: {x: 35.7, y: 54.1}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!114 &759111376
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 759111374}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 0
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI,
|
||||
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
|
||||
m_FontData:
|
||||
m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
|
||||
m_FontSize: 24
|
||||
m_FontStyle: 1
|
||||
m_BestFit: 0
|
||||
m_MinSize: 2
|
||||
m_MaxSize: 50
|
||||
m_Alignment: 4
|
||||
m_AlignByGeometry: 0
|
||||
m_RichText: 1
|
||||
m_HorizontalOverflow: 1
|
||||
m_VerticalOverflow: 1
|
||||
m_LineSpacing: 1
|
||||
m_Text: World!
|
||||
--- !u!222 &759111377
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 759111374}
|
||||
--- !u!114 &759111378
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 759111374}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: b42a195b47491d34b9bcbc40898bcb29, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
skeletonGraphic: {fileID: 57002145}
|
||||
initializeOnAwake: 1
|
||||
boneName: handL
|
||||
followBoneRotation: 1
|
||||
followSkeletonFlip: 1
|
||||
followLocalScale: 0
|
||||
followZPosition: 1
|
||||
--- !u!1 &774800193
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@ -912,7 +1102,7 @@ RectTransform:
|
||||
m_Children:
|
||||
- {fileID: 1066372096}
|
||||
m_Father: {fileID: 289700665}
|
||||
m_RootOrder: 1
|
||||
m_RootOrder: 2
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
||||
@ -940,6 +1130,8 @@ MonoBehaviour:
|
||||
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
|
||||
skeletonDataAsset: {fileID: 11400000, guid: a467507a4ffb1d542a558739b2fede77, type: 2}
|
||||
initialSkinName: base
|
||||
initialFlipX: 0
|
||||
initialFlipY: 0
|
||||
startingAnimation: run
|
||||
startingLoop: 1
|
||||
timeScale: 1
|
||||
|
||||
@ -1641,21 +1641,21 @@ namespace Spine.Unity.Editor {
|
||||
}
|
||||
}
|
||||
|
||||
public static void DrawBoneNames (Transform transform, Skeleton skeleton) {
|
||||
public static void DrawBoneNames (Transform transform, Skeleton skeleton, float positionScale = 1f) {
|
||||
GUIStyle style = BoneNameStyle;
|
||||
foreach (Bone b in skeleton.Bones) {
|
||||
var pos = new Vector3(b.WorldX, b.WorldY, 0) + (new Vector3(b.A, b.C) * (b.Data.Length * 0.5f));
|
||||
var pos = new Vector3(b.WorldX * positionScale, b.WorldY * positionScale, 0) + (new Vector3(b.A, b.C) * (b.Data.Length * 0.5f));
|
||||
pos = transform.TransformPoint(pos);
|
||||
Handles.Label(pos, b.Data.Name, style);
|
||||
}
|
||||
}
|
||||
|
||||
public static void DrawBones (Transform transform, Skeleton skeleton) {
|
||||
public static void DrawBones (Transform transform, Skeleton skeleton, float positionScale = 1f) {
|
||||
float boneScale = 1.8f; // Draw the root bone largest;
|
||||
DrawCrosshairs2D(skeleton.Bones.Items[0].GetWorldPosition(transform), 0.08f);
|
||||
DrawCrosshairs2D(skeleton.Bones.Items[0].GetWorldPosition(transform), 0.08f, positionScale);
|
||||
|
||||
foreach (Bone b in skeleton.Bones) {
|
||||
DrawBone(transform, b, boneScale);
|
||||
DrawBone(transform, b, boneScale, positionScale);
|
||||
boneScale = 1f;
|
||||
}
|
||||
}
|
||||
@ -1668,45 +1668,45 @@ namespace Spine.Unity.Editor {
|
||||
_boneWireBuffer[4] = _boneWireBuffer[0]; // closed polygon.
|
||||
return _boneWireBuffer;
|
||||
}
|
||||
public static void DrawBoneWireframe (Transform transform, Bone b, Color color) {
|
||||
public static void DrawBoneWireframe (Transform transform, Bone b, Color color, float skeletonRenderScale = 1f) {
|
||||
Handles.color = color;
|
||||
var pos = new Vector3(b.WorldX, b.WorldY, 0);
|
||||
var pos = new Vector3(b.WorldX * skeletonRenderScale, b.WorldY * skeletonRenderScale, 0);
|
||||
float length = b.Data.Length;
|
||||
|
||||
if (length > 0) {
|
||||
Quaternion rot = Quaternion.Euler(0, 0, b.WorldRotationX);
|
||||
Vector3 scale = Vector3.one * length * b.WorldScaleX;
|
||||
Vector3 scale = Vector3.one * length * b.WorldScaleX * skeletonRenderScale;
|
||||
const float my = 1.5f;
|
||||
scale.y *= (SpineHandles.handleScale + 1f) * 0.5f;
|
||||
scale.y = Mathf.Clamp(scale.x, -my, my);
|
||||
scale.y *= (SpineHandles.handleScale + 1) * 0.5f;
|
||||
scale.y = Mathf.Clamp(scale.x, -my * skeletonRenderScale, my * skeletonRenderScale);
|
||||
Handles.DrawPolyLine(GetBoneWireBuffer(transform.localToWorldMatrix * Matrix4x4.TRS(pos, rot, scale)));
|
||||
var wp = transform.TransformPoint(pos);
|
||||
DrawBoneCircle(wp, color, transform.forward);
|
||||
DrawBoneCircle(wp, color, transform.forward, skeletonRenderScale);
|
||||
} else {
|
||||
var wp = transform.TransformPoint(pos);
|
||||
DrawBoneCircle(wp, color, transform.forward);
|
||||
DrawBoneCircle(wp, color, transform.forward, skeletonRenderScale);
|
||||
}
|
||||
}
|
||||
|
||||
public static void DrawBone (Transform transform, Bone b, float boneScale) {
|
||||
var pos = new Vector3(b.WorldX, b.WorldY, 0);
|
||||
public static void DrawBone (Transform transform, Bone b, float boneScale, float skeletonRenderScale = 1f) {
|
||||
var pos = new Vector3(b.WorldX * skeletonRenderScale, b.WorldY * skeletonRenderScale, 0);
|
||||
float length = b.Data.Length;
|
||||
if (length > 0) {
|
||||
Quaternion rot = Quaternion.Euler(0, 0, b.WorldRotationX);
|
||||
Vector3 scale = Vector3.one * length * b.WorldScaleX;
|
||||
Vector3 scale = Vector3.one * length * b.WorldScaleX * skeletonRenderScale;
|
||||
const float my = 1.5f;
|
||||
scale.y *= (SpineHandles.handleScale + 1f) * 0.5f;
|
||||
scale.y = Mathf.Clamp(scale.x, -my, my);
|
||||
scale.y = Mathf.Clamp(scale.x, -my * skeletonRenderScale, my * skeletonRenderScale);
|
||||
SpineHandles.GetBoneMaterial().SetPass(0);
|
||||
Graphics.DrawMeshNow(SpineHandles.BoneMesh, transform.localToWorldMatrix * Matrix4x4.TRS(pos, rot, scale));
|
||||
} else {
|
||||
var wp = transform.TransformPoint(pos);
|
||||
DrawBoneCircle(wp, SpineHandles.BoneColor, transform.forward, boneScale);
|
||||
DrawBoneCircle(wp, SpineHandles.BoneColor, transform.forward, boneScale * skeletonRenderScale);
|
||||
}
|
||||
}
|
||||
|
||||
public static void DrawBone (Transform transform, Bone b, float boneScale, Color color) {
|
||||
var pos = new Vector3(b.WorldX, b.WorldY, 0);
|
||||
public static void DrawBone (Transform transform, Bone b, float boneScale, Color color, float skeletonRenderScale = 1f) {
|
||||
var pos = new Vector3(b.WorldX * skeletonRenderScale, b.WorldY * skeletonRenderScale, 0);
|
||||
float length = b.Data.Length;
|
||||
if (length > 0) {
|
||||
Quaternion rot = Quaternion.Euler(0, 0, b.WorldRotationX);
|
||||
@ -1718,7 +1718,7 @@ namespace Spine.Unity.Editor {
|
||||
Graphics.DrawMeshNow(SpineHandles.BoneMesh, transform.localToWorldMatrix * Matrix4x4.TRS(pos, rot, scale));
|
||||
} else {
|
||||
var wp = transform.TransformPoint(pos);
|
||||
DrawBoneCircle(wp, color, transform.forward, boneScale);
|
||||
DrawBoneCircle(wp, color, transform.forward, boneScale * skeletonRenderScale);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1814,7 +1814,7 @@ namespace Spine.Unity.Editor {
|
||||
Handles.DrawLine(lastVert, firstVert);
|
||||
}
|
||||
|
||||
public static void DrawConstraints (Transform transform, Skeleton skeleton) {
|
||||
public static void DrawConstraints (Transform transform, Skeleton skeleton, float skeletonRenderScale = 1f) {
|
||||
Vector3 targetPos;
|
||||
Vector3 pos;
|
||||
bool active;
|
||||
@ -1826,19 +1826,19 @@ namespace Spine.Unity.Editor {
|
||||
handleColor = SpineHandles.TransformContraintColor;
|
||||
foreach (var tc in skeleton.TransformConstraints) {
|
||||
var targetBone = tc.Target;
|
||||
targetPos = targetBone.GetWorldPosition(transform);
|
||||
targetPos = targetBone.GetWorldPosition(transform, skeletonRenderScale);
|
||||
|
||||
if (tc.TranslateMix > 0) {
|
||||
if (tc.TranslateMix != 1f) {
|
||||
Handles.color = handleColor;
|
||||
foreach (var b in tc.Bones) {
|
||||
pos = b.GetWorldPosition(transform);
|
||||
pos = b.GetWorldPosition(transform, skeletonRenderScale);
|
||||
Handles.DrawDottedLine(targetPos, pos, Thickness);
|
||||
}
|
||||
}
|
||||
SpineHandles.DrawBoneCircle(targetPos, handleColor, normal, 1.3f);
|
||||
SpineHandles.DrawBoneCircle(targetPos, handleColor, normal, 1.3f * skeletonRenderScale);
|
||||
Handles.color = handleColor;
|
||||
SpineHandles.DrawCrosshairs(targetPos, 0.2f, targetBone.A, targetBone.B, targetBone.C, targetBone.D, transform);
|
||||
SpineHandles.DrawCrosshairs(targetPos, 0.2f, targetBone.A, targetBone.B, targetBone.C, targetBone.D, transform, skeletonRenderScale);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1846,25 +1846,25 @@ namespace Spine.Unity.Editor {
|
||||
handleColor = SpineHandles.IkColor;
|
||||
foreach (var ikc in skeleton.IkConstraints) {
|
||||
Bone targetBone = ikc.Target;
|
||||
targetPos = targetBone.GetWorldPosition(transform);
|
||||
targetPos = targetBone.GetWorldPosition(transform, skeletonRenderScale);
|
||||
var bones = ikc.Bones;
|
||||
active = ikc.Mix > 0;
|
||||
if (active) {
|
||||
pos = bones.Items[0].GetWorldPosition(transform);
|
||||
pos = bones.Items[0].GetWorldPosition(transform, skeletonRenderScale);
|
||||
switch (bones.Count) {
|
||||
case 1: {
|
||||
Handles.color = handleColor;
|
||||
Handles.DrawLine(targetPos, pos);
|
||||
SpineHandles.DrawBoneCircle(targetPos, handleColor, normal);
|
||||
var m = bones.Items[0].GetMatrix4x4();
|
||||
m.m03 = targetBone.WorldX;
|
||||
m.m13 = targetBone.WorldY;
|
||||
m.m03 = targetBone.WorldX * skeletonRenderScale;
|
||||
m.m13 = targetBone.WorldY * skeletonRenderScale;
|
||||
SpineHandles.DrawArrowhead(transform.localToWorldMatrix * m);
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
Bone childBone = bones.Items[1];
|
||||
Vector3 child = childBone.GetWorldPosition(transform);
|
||||
Vector3 child = childBone.GetWorldPosition(transform, skeletonRenderScale);
|
||||
Handles.color = handleColor;
|
||||
Handles.DrawLine(child, pos);
|
||||
Handles.DrawLine(targetPos, child);
|
||||
@ -1872,8 +1872,8 @@ namespace Spine.Unity.Editor {
|
||||
SpineHandles.DrawBoneCircle(child, handleColor, normal, 0.5f);
|
||||
SpineHandles.DrawBoneCircle(targetPos, handleColor, normal);
|
||||
var m = childBone.GetMatrix4x4();
|
||||
m.m03 = targetBone.WorldX;
|
||||
m.m13 = targetBone.WorldY;
|
||||
m.m03 = targetBone.WorldX * skeletonRenderScale;
|
||||
m.m13 = targetBone.WorldY * skeletonRenderScale;
|
||||
SpineHandles.DrawArrowhead(transform.localToWorldMatrix * m);
|
||||
break;
|
||||
}
|
||||
@ -1888,18 +1888,18 @@ namespace Spine.Unity.Editor {
|
||||
active = pc.TranslateMix > 0;
|
||||
if (active)
|
||||
foreach (var b in pc.Bones)
|
||||
SpineHandles.DrawBoneCircle(b.GetWorldPosition(transform), handleColor, normal, 1f);
|
||||
SpineHandles.DrawBoneCircle(b.GetWorldPosition(transform, skeletonRenderScale), handleColor, normal, 1f * skeletonRenderScale);
|
||||
}
|
||||
}
|
||||
|
||||
static void DrawCrosshairs2D (Vector3 position, float scale) {
|
||||
scale *= SpineHandles.handleScale;
|
||||
static void DrawCrosshairs2D (Vector3 position, float scale, float skeletonRenderScale = 1f) {
|
||||
scale *= SpineHandles.handleScale * skeletonRenderScale;
|
||||
Handles.DrawLine(position + new Vector3(-scale, 0), position + new Vector3(scale, 0));
|
||||
Handles.DrawLine(position + new Vector3(0, -scale), position + new Vector3(0, scale));
|
||||
}
|
||||
|
||||
static void DrawCrosshairs (Vector3 position, float scale, float a, float b, float c, float d, Transform transform) {
|
||||
scale *= SpineHandles.handleScale;
|
||||
static void DrawCrosshairs (Vector3 position, float scale, float a, float b, float c, float d, Transform transform, float skeletonRenderScale = 1f) {
|
||||
scale *= SpineHandles.handleScale * skeletonRenderScale;
|
||||
|
||||
var xOffset = (Vector3)(new Vector2(a, c).normalized * scale);
|
||||
var yOffset = (Vector3)(new Vector2(b, d).normalized * scale);
|
||||
@ -1941,7 +1941,7 @@ namespace Spine.Unity.Editor {
|
||||
float firstScale = 0.08f * scale;
|
||||
Handles.DrawSolidDisc(pos, normal, firstScale);
|
||||
const float Thickness = 0.03f;
|
||||
float secondScale = firstScale - (Thickness * SpineHandles.handleScale);
|
||||
float secondScale = firstScale - (Thickness * SpineHandles.handleScale * scale);
|
||||
|
||||
if (secondScale > 0f) {
|
||||
Handles.color = new Color(0.3f, 0.3f, 0.3f, 0.5f);
|
||||
|
||||
@ -0,0 +1,133 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity {
|
||||
[ExecuteInEditMode]
|
||||
[DisallowMultipleComponent]
|
||||
[AddComponentMenu("Spine/UI/BoneFollowerGraphic")]
|
||||
public class BoneFollowerGraphic : MonoBehaviour {
|
||||
public SkeletonGraphic skeletonGraphic;
|
||||
public SkeletonGraphic SkeletonGraphic {
|
||||
get { return skeletonGraphic; }
|
||||
set {
|
||||
skeletonGraphic = value;
|
||||
Initialize();
|
||||
}
|
||||
}
|
||||
|
||||
public bool initializeOnAwake = true;
|
||||
|
||||
/// <summary>If a bone isn't set in code, boneName is used to find the bone at the beginning. For runtime switching by name, use SetBoneByName. You can also set the BoneFollower.bone field directly.</summary>
|
||||
[SpineBone(dataField: "skeletonGraphic")]
|
||||
[SerializeField] public string boneName;
|
||||
|
||||
public bool followBoneRotation = true;
|
||||
[Tooltip("Follows the skeleton's flip state by controlling this Transform's local scale.")]
|
||||
public bool followSkeletonFlip = true;
|
||||
[Tooltip("Follows the target bone's local scale. BoneFollower cannot inherit world/skewed scale because of UnityEngine.Transform property limitations.")]
|
||||
public bool followLocalScale = false;
|
||||
public bool followZPosition = true;
|
||||
|
||||
[System.NonSerialized] public Bone bone;
|
||||
|
||||
Transform skeletonTransform;
|
||||
bool skeletonTransformIsParent;
|
||||
|
||||
[System.NonSerialized] public bool valid;
|
||||
|
||||
/// <summary>
|
||||
/// Sets the target bone by its bone name. Returns false if no bone was found.</summary>
|
||||
public bool SetBone (string name) {
|
||||
bone = skeletonGraphic.Skeleton.FindBone(name);
|
||||
if (bone == null) {
|
||||
Debug.LogError("Bone not found: " + name, this);
|
||||
return false;
|
||||
}
|
||||
boneName = name;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Awake () {
|
||||
if (initializeOnAwake) Initialize();
|
||||
}
|
||||
|
||||
public void Initialize () {
|
||||
bone = null;
|
||||
valid = skeletonGraphic != null && skeletonGraphic.IsValid;
|
||||
if (!valid) return;
|
||||
|
||||
skeletonTransform = skeletonGraphic.transform;
|
||||
// skeletonGraphic.OnRebuild -= HandleRebuildRenderer;
|
||||
// skeletonGraphic.OnRebuild += HandleRebuildRenderer;
|
||||
skeletonTransformIsParent = Transform.ReferenceEquals(skeletonTransform, transform.parent);
|
||||
|
||||
if (!string.IsNullOrEmpty(boneName))
|
||||
bone = skeletonGraphic.Skeleton.FindBone(boneName);
|
||||
|
||||
#if UNITY_EDITOR
|
||||
if (Application.isEditor)
|
||||
LateUpdate();
|
||||
#endif
|
||||
}
|
||||
|
||||
public void LateUpdate () {
|
||||
if (!valid) {
|
||||
Initialize();
|
||||
return;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
if (!Application.isPlaying)
|
||||
skeletonTransformIsParent = Transform.ReferenceEquals(skeletonTransform, transform.parent);
|
||||
#endif
|
||||
|
||||
if (bone == null) {
|
||||
if (string.IsNullOrEmpty(boneName)) return;
|
||||
bone = skeletonGraphic.Skeleton.FindBone(boneName);
|
||||
if (!SetBone(boneName)) return;
|
||||
}
|
||||
|
||||
var thisTransform = this.transform as RectTransform;
|
||||
if (thisTransform == null) return;
|
||||
|
||||
float scale = skeletonGraphic.canvas.referencePixelsPerUnit;
|
||||
|
||||
if (skeletonTransformIsParent) {
|
||||
// Recommended setup: Use local transform properties if Spine GameObject is the immediate parent
|
||||
thisTransform.localPosition = new Vector3(bone.worldX * scale, bone.worldY * scale, followZPosition ? 0f : thisTransform.localPosition.z);
|
||||
if (followBoneRotation) thisTransform.localRotation = bone.GetQuaternion();
|
||||
} else {
|
||||
// For special cases: Use transform world properties if transform relationship is complicated
|
||||
Vector3 targetWorldPosition = skeletonTransform.TransformPoint(new Vector3(bone.worldX * scale, bone.worldY * scale, 0f));
|
||||
if (!followZPosition) targetWorldPosition.z = thisTransform.position.z;
|
||||
|
||||
float boneWorldRotation = bone.WorldRotationX;
|
||||
|
||||
Transform transformParent = thisTransform.parent;
|
||||
if (transformParent != null) {
|
||||
Matrix4x4 m = transformParent.localToWorldMatrix;
|
||||
if (m.m00 * m.m11 - m.m01 * m.m10 < 0) // Determinant2D is negative
|
||||
boneWorldRotation = -boneWorldRotation;
|
||||
}
|
||||
|
||||
if (followBoneRotation) {
|
||||
Vector3 worldRotation = skeletonTransform.rotation.eulerAngles;
|
||||
#if UNITY_5_6_OR_NEWER
|
||||
thisTransform.SetPositionAndRotation(targetWorldPosition, Quaternion.Euler(worldRotation.x, worldRotation.y, skeletonTransform.rotation.eulerAngles.z + boneWorldRotation));
|
||||
#else
|
||||
thisTransform.position = targetWorldPosition;
|
||||
thisTransform.rotation = Quaternion.Euler(worldRotation.x, worldRotation.y, skeletonTransform.rotation.eulerAngles.z + bone.WorldRotationX);
|
||||
#endif
|
||||
} else {
|
||||
thisTransform.position = targetWorldPosition;
|
||||
}
|
||||
}
|
||||
|
||||
Vector3 localScale = followLocalScale ? new Vector3(bone.scaleX, bone.scaleY, 1f) : new Vector3(1f, 1f, 1f);
|
||||
if (followSkeletonFlip) localScale.y *= bone.skeleton.flipX ^ bone.skeleton.flipY ? -1f : 1f;
|
||||
thisTransform.localScale = localScale;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b42a195b47491d34b9bcbc40898bcb29
|
||||
timeCreated: 1499211965
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,172 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
using Spine.Unity;
|
||||
|
||||
namespace Spine.Unity.Editor {
|
||||
|
||||
using Editor = UnityEditor.Editor;
|
||||
using Event = UnityEngine.Event;
|
||||
|
||||
[CustomEditor(typeof(BoneFollowerGraphic)), CanEditMultipleObjects]
|
||||
public class BoneFollowerGraphicInspector : Editor {
|
||||
|
||||
SerializedProperty boneName, skeletonGraphic, followZPosition, followBoneRotation, followLocalScale, followSkeletonFlip;
|
||||
BoneFollowerGraphic targetBoneFollower;
|
||||
bool needsReset;
|
||||
|
||||
#region Context Menu Item
|
||||
[MenuItem ("CONTEXT/SkeletonGraphic/Add BoneFollower GameObject")]
|
||||
static void AddBoneFollowerGameObject (MenuCommand cmd) {
|
||||
var skeletonGraphic = cmd.context as SkeletonGraphic;
|
||||
var go = new GameObject("BoneFollower", typeof(RectTransform));
|
||||
var t = go.transform;
|
||||
t.SetParent(skeletonGraphic.transform);
|
||||
t.localPosition = Vector3.zero;
|
||||
|
||||
var f = go.AddComponent<BoneFollowerGraphic>();
|
||||
f.skeletonGraphic = skeletonGraphic;
|
||||
f.SetBone(skeletonGraphic.Skeleton.RootBone.Data.Name);
|
||||
|
||||
EditorGUIUtility.PingObject(t);
|
||||
|
||||
Undo.RegisterCreatedObjectUndo(go, "Add BoneFollowerGraphic");
|
||||
}
|
||||
|
||||
// Validate
|
||||
[MenuItem ("CONTEXT/SkeletonGraphic/Add BoneFollower GameObject", true)]
|
||||
static bool ValidateAddBoneFollowerGameObject (MenuCommand cmd) {
|
||||
var skeletonGraphic = cmd.context as SkeletonGraphic;
|
||||
return skeletonGraphic.IsValid;
|
||||
}
|
||||
#endregion
|
||||
|
||||
void OnEnable () {
|
||||
skeletonGraphic = serializedObject.FindProperty("skeletonGraphic");
|
||||
boneName = serializedObject.FindProperty("boneName");
|
||||
followBoneRotation = serializedObject.FindProperty("followBoneRotation");
|
||||
followZPosition = serializedObject.FindProperty("followZPosition");
|
||||
followLocalScale = serializedObject.FindProperty("followLocalScale");
|
||||
followSkeletonFlip = serializedObject.FindProperty("followSkeletonFlip");
|
||||
|
||||
targetBoneFollower = (BoneFollowerGraphic)target;
|
||||
if (targetBoneFollower.SkeletonGraphic != null)
|
||||
targetBoneFollower.SkeletonGraphic.Initialize(false);
|
||||
|
||||
if (!targetBoneFollower.valid || needsReset) {
|
||||
targetBoneFollower.Initialize();
|
||||
targetBoneFollower.LateUpdate();
|
||||
needsReset = false;
|
||||
SceneView.RepaintAll();
|
||||
}
|
||||
}
|
||||
|
||||
public void OnSceneGUI () {
|
||||
var tbf = target as BoneFollowerGraphic;
|
||||
var skeletonGraphicComponent = tbf.SkeletonGraphic;
|
||||
if (skeletonGraphicComponent == null) return;
|
||||
|
||||
var transform = skeletonGraphicComponent.transform;
|
||||
var skeleton = skeletonGraphicComponent.Skeleton;
|
||||
var canvas = skeletonGraphicComponent.canvas;
|
||||
float positionScale = canvas == null ? 1f : skeletonGraphicComponent.canvas.referencePixelsPerUnit;
|
||||
|
||||
if (string.IsNullOrEmpty(boneName.stringValue)) {
|
||||
SpineHandles.DrawBones(transform, skeleton, positionScale);
|
||||
SpineHandles.DrawBoneNames(transform, skeleton, positionScale);
|
||||
Handles.Label(tbf.transform.position, "No bone selected", EditorStyles.helpBox);
|
||||
} else {
|
||||
var targetBone = tbf.bone;
|
||||
if (targetBone == null) return;
|
||||
|
||||
SpineHandles.DrawBoneWireframe(transform, targetBone, SpineHandles.TransformContraintColor, positionScale);
|
||||
Handles.Label(targetBone.GetWorldPosition(transform, positionScale), targetBone.Data.Name, SpineHandles.BoneNameStyle);
|
||||
}
|
||||
}
|
||||
|
||||
override public void OnInspectorGUI () {
|
||||
if (serializedObject.isEditingMultipleObjects) {
|
||||
if (needsReset) {
|
||||
needsReset = false;
|
||||
foreach (var o in targets) {
|
||||
var bf = (BoneFollower)o;
|
||||
bf.Initialize();
|
||||
bf.LateUpdate();
|
||||
}
|
||||
SceneView.RepaintAll();
|
||||
}
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
DrawDefaultInspector();
|
||||
needsReset |= EditorGUI.EndChangeCheck();
|
||||
return;
|
||||
}
|
||||
|
||||
if (needsReset && Event.current.type == EventType.Layout) {
|
||||
targetBoneFollower.Initialize();
|
||||
targetBoneFollower.LateUpdate();
|
||||
needsReset = false;
|
||||
SceneView.RepaintAll();
|
||||
}
|
||||
serializedObject.Update();
|
||||
|
||||
// Find Renderer
|
||||
if (skeletonGraphic.objectReferenceValue == null) {
|
||||
SkeletonGraphic parentRenderer = targetBoneFollower.GetComponentInParent<SkeletonGraphic>();
|
||||
if (parentRenderer != null && parentRenderer.gameObject != targetBoneFollower.gameObject) {
|
||||
skeletonGraphic.objectReferenceValue = parentRenderer;
|
||||
Debug.Log("Inspector automatically assigned BoneFollowerGraphic.SkeletonGraphic");
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUILayout.PropertyField(skeletonGraphic);
|
||||
var skeletonGraphicComponent = skeletonGraphic.objectReferenceValue as SkeletonGraphic;
|
||||
if (skeletonGraphicComponent != null) {
|
||||
if (skeletonGraphicComponent.gameObject == targetBoneFollower.gameObject) {
|
||||
skeletonGraphic.objectReferenceValue = null;
|
||||
EditorUtility.DisplayDialog("Invalid assignment.", "BoneFollowerGraphic can only follow a skeleton on a separate GameObject.\n\nCreate a new GameObject for your BoneFollower, or choose a SkeletonGraphic from a different GameObject.", "Ok");
|
||||
}
|
||||
}
|
||||
|
||||
if (!targetBoneFollower.valid) {
|
||||
needsReset = true;
|
||||
}
|
||||
|
||||
if (targetBoneFollower.valid) {
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUILayout.PropertyField(boneName);
|
||||
needsReset |= EditorGUI.EndChangeCheck();
|
||||
|
||||
EditorGUILayout.PropertyField(followBoneRotation);
|
||||
EditorGUILayout.PropertyField(followZPosition);
|
||||
EditorGUILayout.PropertyField(followLocalScale);
|
||||
EditorGUILayout.PropertyField(followSkeletonFlip);
|
||||
|
||||
//BoneFollowerInspector.RecommendRigidbodyButton(targetBoneFollower);
|
||||
} else {
|
||||
var boneFollowerSkeletonGraphic = targetBoneFollower.skeletonGraphic;
|
||||
if (boneFollowerSkeletonGraphic == null) {
|
||||
EditorGUILayout.HelpBox("SkeletonGraphic is unassigned. Please assign a SkeletonRenderer (SkeletonAnimation or SkeletonAnimator).", MessageType.Warning);
|
||||
} else {
|
||||
boneFollowerSkeletonGraphic.Initialize(false);
|
||||
|
||||
if (boneFollowerSkeletonGraphic.skeletonDataAsset == null)
|
||||
EditorGUILayout.HelpBox("Assigned SkeletonGraphic does not have SkeletonData assigned to it.", MessageType.Warning);
|
||||
|
||||
if (!boneFollowerSkeletonGraphic.IsValid)
|
||||
EditorGUILayout.HelpBox("Assigned SkeletonGraphic is invalid. Check target SkeletonGraphic, its SkeletonDataAsset or the console for other errors.", MessageType.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
var current = Event.current;
|
||||
bool wasUndo = (current.type == EventType.ValidateCommand && current.commandName == "UndoRedoPerformed");
|
||||
if (wasUndo)
|
||||
targetBoneFollower.Initialize();
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: da44a8561fd243c43a1f77bda36de0eb
|
||||
timeCreated: 1499279157
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -134,6 +134,10 @@ namespace Spine.Unity {
|
||||
return spineGameObjectTransform.TransformPoint(new Vector3(bone.worldX, bone.worldY));
|
||||
}
|
||||
|
||||
public static Vector3 GetWorldPosition (this Bone bone, UnityEngine.Transform spineGameObjectTransform, float positionScale) {
|
||||
return spineGameObjectTransform.TransformPoint(new Vector3(bone.worldX * positionScale, bone.worldY * positionScale));
|
||||
}
|
||||
|
||||
/// <summary>Gets a skeleton space UnityEngine.Quaternion representation of bone.WorldRotationX.</summary>
|
||||
public static Quaternion GetQuaternion (this Bone bone) {
|
||||
var halfRotation = Mathf.Atan2(bone.c, bone.a) * 0.5f;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user