mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-03-26 22:49:01 +08:00
[unity] SkeletonBakingWindow and various editor fixes.
This commit is contained in:
parent
7570c69aa2
commit
439c8e8e22
@ -82,6 +82,7 @@
|
|||||||
* **[SpineAttribute(includeNone:false)]** SpineAttributes now have an `includeNone` optional parameter to specify if you want to include or exclude a none ("") value option in the dropdown menu. Default is `includeNone:true`.
|
* **[SpineAttribute(includeNone:false)]** SpineAttributes now have an `includeNone` optional parameter to specify if you want to include or exclude a none ("") value option in the dropdown menu. Default is `includeNone:true`.
|
||||||
* **[SpineAttachment(skinField:"mySkin")]** The SpineAttachment attribute now has a skinField optional parameter to limit the dropdown items to attachments in a specific skin instead of the just default skin or all the skins in SkeletonData.
|
* **[SpineAttachment(skinField:"mySkin")]** The SpineAttachment attribute now has a skinField optional parameter to limit the dropdown items to attachments in a specific skin instead of the just default skin or all the skins in SkeletonData.
|
||||||
* **SkeletonDebugWindow**. Debugging tools have been moved from the SkeletonRenderer and SkeletonUtility component inspectors into its own utility window. You can access "Skeleton Debug" under the `Advanced...` foldout in the SkeletonRenderer inspector, or in SkeletonRenderer's right-click/context menu.
|
* **SkeletonDebugWindow**. Debugging tools have been moved from the SkeletonRenderer and SkeletonUtility component inspectors into its own utility window. You can access "Skeleton Debug" under the `Advanced...` foldout in the SkeletonRenderer inspector, or in SkeletonRenderer's right-click/context menu.
|
||||||
|
* **Skeleton Baking Window** The old Skeleton Baking feature is also now accessible through the SkeletonDataAsset's right-click/context menu.
|
||||||
* **AttachmentTools source material**. `AttachmentTools` methods can now accept a `sourceMaterial` argument to copy material properties from.
|
* **AttachmentTools source material**. `AttachmentTools` methods can now accept a `sourceMaterial` argument to copy material properties from.
|
||||||
* **AttachmentTools Skin Extensions**. Using AttachmentTools, you can now add entries by slot name by also providing a skeleton argument. Also `Append(Skin)`, `RemoveAttachment` and `Clear` have been added.
|
* **AttachmentTools Skin Extensions**. Using AttachmentTools, you can now add entries by slot name by also providing a skeleton argument. Also `Append(Skin)`, `RemoveAttachment` and `Clear` have been added.
|
||||||
* **BoneFollower and SkeletonUtilityBone Add RigidBody Button**. The BoneFollower and SkeletonUtilityBone component inspectors will now offer to add a `Rigidbody` or `Rigidbody2D` if it detects a collider of the appropriate type. Having a rigidbody on a moving transform with a collider fits better with the Unity physics systems and prevents excess calculations. It will not detect colliders on child objects so you have to add Rigidbody components manually accordingly.
|
* **BoneFollower and SkeletonUtilityBone Add RigidBody Button**. The BoneFollower and SkeletonUtilityBone component inspectors will now offer to add a `Rigidbody` or `Rigidbody2D` if it detects a collider of the appropriate type. Having a rigidbody on a moving transform with a collider fits better with the Unity physics systems and prevents excess calculations. It will not detect colliders on child objects so you have to add Rigidbody components manually accordingly.
|
||||||
|
|||||||
@ -287,73 +287,6 @@ namespace Spine.Unity.Editor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if SPINE_BAKING
|
|
||||||
bool pre = isBakingExpanded;
|
|
||||||
isBakingExpanded = EditorGUILayout.Foldout(isBakingExpanded, new GUIContent("Baking", Icons.unityIcon));
|
|
||||||
if (pre != isBakingExpanded)
|
|
||||||
EditorPrefs.SetBool(ShowBakingPrefsKey, isBakingExpanded);
|
|
||||||
|
|
||||||
if (isBakingExpanded) {
|
|
||||||
EditorGUI.indentLevel++;
|
|
||||||
const string BakingWarningMessage =
|
|
||||||
// "WARNING!" +
|
|
||||||
// "\nBaking is NOT the same as SkeletonAnimator!" +
|
|
||||||
// "\n\n" +
|
|
||||||
"The main use of Baking is to export Spine projects to be used without the Spine Runtime (ie: for sale on the Asset Store, or background objects that are animated only with a wind noise generator)" +
|
|
||||||
|
|
||||||
"\n\nBaking does not support the following:" +
|
|
||||||
"\n\tDisabled transform inheritance" +
|
|
||||||
"\n\tShear" +
|
|
||||||
"\n\tColor Keys" +
|
|
||||||
"\n\tDraw Order Keys" +
|
|
||||||
"\n\tAll Constraint types" +
|
|
||||||
|
|
||||||
"\n\nCurves are sampled at 60fps and are not realtime." +
|
|
||||||
"\nPlease read SkeletonBaker.cs comments for full details.";
|
|
||||||
EditorGUILayout.HelpBox(BakingWarningMessage, MessageType.Info, true);
|
|
||||||
|
|
||||||
EditorGUI.indentLevel++;
|
|
||||||
bakeAnimations = EditorGUILayout.Toggle("Bake Animations", bakeAnimations);
|
|
||||||
using (new EditorGUI.DisabledGroupScope(!bakeAnimations)) {
|
|
||||||
EditorGUI.indentLevel++;
|
|
||||||
bakeIK = EditorGUILayout.Toggle("Bake IK", bakeIK);
|
|
||||||
bakeEventOptions = (SendMessageOptions)EditorGUILayout.EnumPopup("Event Options", bakeEventOptions);
|
|
||||||
EditorGUI.indentLevel--;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bake Skin buttons.
|
|
||||||
using (new GUILayout.HorizontalScope()) {
|
|
||||||
if (GUILayout.Button(new GUIContent("Bake All Skins", Icons.unityIcon), GUILayout.Height(32), GUILayout.Width(150)))
|
|
||||||
SkeletonBaker.BakeToPrefab(m_skeletonDataAsset, m_skeletonData.Skins, "", bakeAnimations, bakeIK, bakeEventOptions);
|
|
||||||
|
|
||||||
if (m_skeletonAnimation != null && m_skeletonAnimation.skeleton != null) {
|
|
||||||
Skin bakeSkin = m_skeletonAnimation.skeleton.Skin;
|
|
||||||
|
|
||||||
string skinName = "<No Skin>";
|
|
||||||
if (bakeSkin == null) {
|
|
||||||
skinName = "Default";
|
|
||||||
bakeSkin = m_skeletonData.Skins.Items[0];
|
|
||||||
} else
|
|
||||||
skinName = m_skeletonAnimation.skeleton.Skin.Name;
|
|
||||||
|
|
||||||
using (new GUILayout.VerticalScope()) {
|
|
||||||
if (GUILayout.Button(new GUIContent("Bake \"" + skinName + "\"", Icons.unityIcon), GUILayout.Height(32), GUILayout.Width(250)))
|
|
||||||
SkeletonBaker.BakeToPrefab(m_skeletonDataAsset, new ExposedList<Skin>(new [] { bakeSkin }), "", bakeAnimations, bakeIK, bakeEventOptions);
|
|
||||||
using (new GUILayout.HorizontalScope()) {
|
|
||||||
GUILayout.Label(new GUIContent("Skins", Icons.skinsRoot), GUILayout.Width(50));
|
|
||||||
if (GUILayout.Button(skinName, EditorStyles.popup, GUILayout.Width(196))) {
|
|
||||||
DrawSkinDropdown();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
EditorGUI.indentLevel--;
|
|
||||||
EditorGUI.indentLevel--;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DoReimport () {
|
void DoReimport () {
|
||||||
|
|||||||
@ -42,36 +42,35 @@ using System.Reflection;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using Spine;
|
using Spine;
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// [SUPPORTS]
|
|
||||||
/// Linear, Constant, and Bezier Curves*
|
|
||||||
/// Inverse Kinematics*
|
|
||||||
/// Inherit Rotation
|
|
||||||
/// Translate Timeline
|
|
||||||
/// Rotate Timeline
|
|
||||||
/// Scale Timeline**
|
|
||||||
/// Event Timeline***
|
|
||||||
/// Attachment Timeline
|
|
||||||
///
|
|
||||||
/// RegionAttachment
|
|
||||||
/// MeshAttachment
|
|
||||||
/// SkinnedMeshAttachment
|
|
||||||
///
|
|
||||||
/// [LIMITATIONS]
|
|
||||||
/// *Inverse Kinematics & Bezier Curves are baked into the animation at 60fps and are not realtime. Use bakeIncrement constant to adjust key density if desired.
|
|
||||||
/// **Non-uniform Scale Keys (ie: if ScaleX and ScaleY are not equal to eachother, it will not be accurate to Spine source)
|
|
||||||
/// ***Events may only fire 1 type of data per event in Unity safely so priority to String data if present in Spine key, otherwise a Float is sent whether the Spine key was Int or Float with priority given to Int.
|
|
||||||
///
|
|
||||||
/// [DOES NOT SUPPORT]
|
|
||||||
/// FlipX or FlipY (Maybe one day)
|
|
||||||
/// FFD (Unity does not provide access to BlendShapes with code)
|
|
||||||
/// Color Keys (Maybe one day when Unity supports full FBX standard and provides access with code)
|
|
||||||
/// InheritScale (Never. Unity and Spine do scaling very differently)
|
|
||||||
/// Draw Order Keyframes
|
|
||||||
/// </summary>
|
|
||||||
///
|
|
||||||
namespace Spine.Unity.Editor {
|
namespace Spine.Unity.Editor {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// [SUPPORTS]
|
||||||
|
/// Linear, Constant, and Bezier Curves*
|
||||||
|
/// Inverse Kinematics*
|
||||||
|
/// Inherit Rotation
|
||||||
|
/// Translate Timeline
|
||||||
|
/// Rotate Timeline
|
||||||
|
/// Scale Timeline**
|
||||||
|
/// Event Timeline***
|
||||||
|
/// Attachment Timeline
|
||||||
|
///
|
||||||
|
/// RegionAttachment
|
||||||
|
/// MeshAttachment
|
||||||
|
/// SkinnedMeshAttachment
|
||||||
|
///
|
||||||
|
/// [LIMITATIONS]
|
||||||
|
/// *Inverse Kinematics & Bezier Curves are baked into the animation at 60fps and are not realtime. Use bakeIncrement constant to adjust key density if desired.
|
||||||
|
/// **Non-uniform Scale Keys (ie: if ScaleX and ScaleY are not equal to eachother, it will not be accurate to Spine source)
|
||||||
|
/// ***Events may only fire 1 type of data per event in Unity safely so priority to String data if present in Spine key, otherwise a Float is sent whether the Spine key was Int or Float with priority given to Int.
|
||||||
|
///
|
||||||
|
/// [DOES NOT SUPPORT]
|
||||||
|
/// FlipX or FlipY (Maybe one day)
|
||||||
|
/// FFD (Unity does not provide access to BlendShapes with code)
|
||||||
|
/// Color Keys (Maybe one day when Unity supports full FBX standard and provides access with code)
|
||||||
|
/// InheritScale (Never. Unity and Spine do scaling very differently)
|
||||||
|
/// Draw Order Keyframes
|
||||||
|
/// </summary>
|
||||||
public static class SkeletonBaker {
|
public static class SkeletonBaker {
|
||||||
|
|
||||||
#region SkeletonAnimator's Mecanim Clips
|
#region SkeletonAnimator's Mecanim Clips
|
||||||
|
|||||||
121
spine-unity/Assets/spine-unity/Editor/SkeletonBakingWindow.cs
Normal file
121
spine-unity/Assets/spine-unity/Editor/SkeletonBakingWindow.cs
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEditor;
|
||||||
|
|
||||||
|
namespace Spine.Unity.Editor {
|
||||||
|
|
||||||
|
using Editor = UnityEditor.Editor;
|
||||||
|
using Icons = SpineEditorUtilities.Icons;
|
||||||
|
|
||||||
|
public class SkeletonBakingWindow : EditorWindow {
|
||||||
|
const bool IsUtilityWindow = true;
|
||||||
|
|
||||||
|
[MenuItem("CONTEXT/SkeletonDataAsset/Skeleton Baking", false, 5000)]
|
||||||
|
public static void Init (MenuCommand command) {
|
||||||
|
var window = EditorWindow.GetWindow<SkeletonBakingWindow>(IsUtilityWindow);
|
||||||
|
window.minSize = new Vector2(330f, 530f);
|
||||||
|
window.maxSize = new Vector2(600f, 1000f);
|
||||||
|
window.titleContent = new GUIContent("Skeleton Baking", Icons.spine);
|
||||||
|
window.skeletonDataAsset = command.context as SkeletonDataAsset;
|
||||||
|
window.Show();
|
||||||
|
}
|
||||||
|
|
||||||
|
public SkeletonDataAsset skeletonDataAsset;
|
||||||
|
[SpineSkin(dataField:"skeletonDataAsset")]
|
||||||
|
public string skinToBake = "default";
|
||||||
|
|
||||||
|
// Settings
|
||||||
|
bool bakeAnimations = false;
|
||||||
|
bool bakeIK = true;
|
||||||
|
SendMessageOptions bakeEventOptions;
|
||||||
|
|
||||||
|
SerializedObject so;
|
||||||
|
Skin bakeSkin;
|
||||||
|
|
||||||
|
|
||||||
|
void DataAssetChanged () {
|
||||||
|
bakeSkin = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnGUI () {
|
||||||
|
so = so ?? new SerializedObject(this);
|
||||||
|
|
||||||
|
EditorGUIUtility.wideMode = true;
|
||||||
|
EditorGUILayout.LabelField("Spine Skeleton Prefab Baking", EditorStyles.boldLabel);
|
||||||
|
|
||||||
|
const string BakingWarningMessage = "\nThe main use of Baking is to export Spine projects to be used without the Spine Runtime (ie: for sale on the Asset Store, or background objects that are animated only with a wind noise generator)" +
|
||||||
|
|
||||||
|
"\n\nBaking does not support the following:" +
|
||||||
|
"\n\tDisabled transform inheritance" +
|
||||||
|
"\n\tShear" +
|
||||||
|
"\n\tColor Keys" +
|
||||||
|
"\n\tDraw Order Keys" +
|
||||||
|
"\n\tAll Constraint types" +
|
||||||
|
|
||||||
|
"\n\nCurves are sampled at 60fps and are not realtime." +
|
||||||
|
"\nPlease read SkeletonBaker.cs comments for full details.\n";
|
||||||
|
EditorGUILayout.HelpBox(BakingWarningMessage, MessageType.Info, true);
|
||||||
|
|
||||||
|
EditorGUI.BeginChangeCheck();
|
||||||
|
var skeletonDataAssetProperty = so.FindProperty("skeletonDataAsset");
|
||||||
|
EditorGUILayout.PropertyField(skeletonDataAssetProperty, SpineInspectorUtility.TempContent("SkeletonDataAsset", Icons.spine));
|
||||||
|
if (EditorGUI.EndChangeCheck()) {
|
||||||
|
so.ApplyModifiedProperties();
|
||||||
|
DataAssetChanged();
|
||||||
|
}
|
||||||
|
EditorGUILayout.Space();
|
||||||
|
|
||||||
|
if (skeletonDataAsset == null) return;
|
||||||
|
var skeletonData = skeletonDataAsset.GetSkeletonData(false);
|
||||||
|
if (skeletonData == null) return;
|
||||||
|
|
||||||
|
using (new SpineInspectorUtility.BoxScope(false)) {
|
||||||
|
EditorGUILayout.LabelField(skeletonDataAsset.name, EditorStyles.boldLabel);
|
||||||
|
using (new SpineInspectorUtility.IndentScope()) {
|
||||||
|
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Bones: " + skeletonData.Bones.Count, Icons.bone));
|
||||||
|
|
||||||
|
int totalAttachments = 0;
|
||||||
|
foreach (var s in skeletonData.Skins) totalAttachments += s.Attachments.Count;
|
||||||
|
|
||||||
|
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Total Attachments: " + totalAttachments, Icons.genericAttachment));
|
||||||
|
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Current skin attachments: " + (bakeSkin == null ? 0 : bakeSkin.Attachments.Count), Icons.skinPlaceholder));
|
||||||
|
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Animations: " + skeletonData.Animations.Count, Icons.animation));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
using (new SpineInspectorUtility.BoxScope(false)) {
|
||||||
|
EditorGUILayout.LabelField("Settings", EditorStyles.boldLabel);
|
||||||
|
using (new SpineInspectorUtility.IndentScope()) {
|
||||||
|
bakeAnimations = EditorGUILayout.Toggle(SpineInspectorUtility.TempContent("Bake Animations", Icons.animationRoot), bakeAnimations);
|
||||||
|
bakeIK = EditorGUILayout.Toggle(SpineInspectorUtility.TempContent("Bake IK", Icons.constraintIK), bakeIK);
|
||||||
|
bakeEventOptions = (SendMessageOptions)EditorGUILayout.EnumPopup(SpineInspectorUtility.TempContent("Event Options", Icons.userEvent), bakeEventOptions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EditorGUILayout.Space();
|
||||||
|
|
||||||
|
EditorGUI.BeginChangeCheck();
|
||||||
|
EditorGUILayout.PropertyField(so.FindProperty("skinToBake"));
|
||||||
|
if (EditorGUI.EndChangeCheck()) {
|
||||||
|
so.ApplyModifiedProperties();
|
||||||
|
Repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(skinToBake) && UnityEngine.Event.current.type == EventType.Repaint)
|
||||||
|
bakeSkin = skeletonData.FindSkin(skinToBake) ?? skeletonData.DefaultSkin;
|
||||||
|
|
||||||
|
var prefabIcon = EditorGUIUtility.FindTexture("PrefabModel Icon");
|
||||||
|
|
||||||
|
if (SpineInspectorUtility.LargeCenteredButton(SpineInspectorUtility.TempContent(string.Format("Bake Skin ({0})", (bakeSkin == null ? "default" : bakeSkin.Name)), prefabIcon))) {
|
||||||
|
SkeletonBaker.BakeToPrefab(skeletonDataAsset, new ExposedList<Skin>(new [] { bakeSkin }), "", bakeAnimations, bakeIK, bakeEventOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (skeletonData.Skins.Count > 1) {
|
||||||
|
if (SpineInspectorUtility.LargeCenteredButton(SpineInspectorUtility.TempContent(string.Format("Bake All ({0} skins)", skeletonData.Skins.Count), prefabIcon))) {
|
||||||
|
SkeletonBaker.BakeToPrefab(skeletonDataAsset, skeletonData.Skins, "", bakeAnimations, bakeIK, bakeEventOptions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 868b0caae5b3e65408ece1ab400c4a99
|
||||||
|
timeCreated: 1495203966
|
||||||
|
licenseType: Free
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@ -305,7 +305,7 @@ namespace Spine.Unity.Editor {
|
|||||||
prefix = skinPrefix;
|
prefix = skinPrefix;
|
||||||
|
|
||||||
for (int i = 0; i < data.Slots.Count; i++) {
|
for (int i = 0; i < data.Slots.Count; i++) {
|
||||||
if (slotMatch.Length > 0 && !(data.Slots.Items[i].Name.ToLower().Contains(slotMatch)))
|
if (slotMatch.Length > 0 && !(data.Slots.Items[i].Name.Equals(slotMatch, StringComparison.OrdinalIgnoreCase)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
attachmentNames.Clear();
|
attachmentNames.Clear();
|
||||||
|
|||||||
@ -200,7 +200,7 @@ namespace Spine.Unity.Editor {
|
|||||||
string buttonLabel = box.IsWeighted() ? box.Name + " (!)" : box.Name;
|
string buttonLabel = box.IsWeighted() ? box.Name + " (!)" : box.Name;
|
||||||
if (GUILayout.Button(buttonLabel, GUILayout.Width(200))) {
|
if (GUILayout.Button(buttonLabel, GUILayout.Width(200))) {
|
||||||
utilityBone.bone.Skeleton.UpdateWorldTransform();
|
utilityBone.bone.Skeleton.UpdateWorldTransform();
|
||||||
var bbTransform = utilityBone.transform.FindChild("[BoundingBox]" + box.Name);
|
var bbTransform = utilityBone.transform.Find("[BoundingBox]" + box.Name); // Use FindChild in older versions of Unity.
|
||||||
if (bbTransform != null) {
|
if (bbTransform != null) {
|
||||||
var originalCollider = bbTransform.GetComponent<PolygonCollider2D>();
|
var originalCollider = bbTransform.GetComponent<PolygonCollider2D>();
|
||||||
if (originalCollider != null)
|
if (originalCollider != null)
|
||||||
|
|||||||
@ -166,7 +166,6 @@ namespace Spine.Unity {
|
|||||||
bone.y = Mathf.Lerp(bone.y, pos.y, overrideAlpha);
|
bone.y = Mathf.Lerp(bone.y, pos.y, overrideAlpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
// MITCH
|
|
||||||
if (rotation) {
|
if (rotation) {
|
||||||
float angle = Mathf.LerpAngle(bone.Rotation, Quaternion.LookRotation(Vector3.forward, parentReference.InverseTransformDirection(cachedTransform.up)).eulerAngles.z, overrideAlpha);
|
float angle = Mathf.LerpAngle(bone.Rotation, Quaternion.LookRotation(Vector3.forward, parentReference.InverseTransformDirection(cachedTransform.up)).eulerAngles.z, overrideAlpha);
|
||||||
bone.Rotation = angle;
|
bone.Rotation = angle;
|
||||||
|
|||||||
@ -144,10 +144,7 @@ namespace Spine.Unity {
|
|||||||
|
|
||||||
public static Spine.Attachment GetAttachment (string attachmentPath, Spine.SkeletonData skeletonData) {
|
public static Spine.Attachment GetAttachment (string attachmentPath, Spine.SkeletonData skeletonData) {
|
||||||
var hierarchy = SpineAttachment.GetHierarchy(attachmentPath);
|
var hierarchy = SpineAttachment.GetHierarchy(attachmentPath);
|
||||||
if (hierarchy.name == "")
|
return string.IsNullOrEmpty(hierarchy.name) ? null : skeletonData.FindSkin(hierarchy.skin).GetAttachment(skeletonData.FindSlotIndex(hierarchy.slot), hierarchy.name);
|
||||||
return null;
|
|
||||||
|
|
||||||
return skeletonData.FindSkin(hierarchy.skin).GetAttachment(skeletonData.FindSlotIndex(hierarchy.slot), hierarchy.name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Spine.Attachment GetAttachment (string attachmentPath, SkeletonDataAsset skeletonDataAsset) {
|
public static Spine.Attachment GetAttachment (string attachmentPath, SkeletonDataAsset skeletonDataAsset) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user