mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-04 14:24:53 +08:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
230542fb7f
@ -35,33 +35,47 @@ using Spine;
|
||||
|
||||
public class CustomSkin : MonoBehaviour {
|
||||
|
||||
|
||||
[System.Serializable]
|
||||
public class SkinPair {
|
||||
/// <summary>SpineAttachment attachment path to help find the attachment.</summary>
|
||||
/// <remarks>This use of SpineAttachment generates an attachment path string that can only be used by SpineAttachment.GetAttachment.</remarks>
|
||||
[SpineAttachment(currentSkinOnly: false, returnAttachmentPath: true, dataField: "skinSource")]
|
||||
public string sourceAttachment;
|
||||
[UnityEngine.Serialization.FormerlySerializedAs("sourceAttachment")]
|
||||
public string sourceAttachmentPath;
|
||||
|
||||
[SpineSlot]
|
||||
public string targetSlot;
|
||||
|
||||
/// <summary>The name of the skin placeholder/skin dictionary entry this attachment should be associated with.</summary>
|
||||
/// <remarks>This name is used by the skin dictionary, used in the method Skin.AddAttachment as well as setting a slot attachment</remarks>
|
||||
[SpineAttachment(currentSkinOnly: true, placeholdersOnly: true)]
|
||||
public string targetAttachment;
|
||||
}
|
||||
|
||||
#region Inspector
|
||||
public SkeletonDataAsset skinSource;
|
||||
public SkinPair[] skinning;
|
||||
|
||||
[UnityEngine.Serialization.FormerlySerializedAs("skinning")]
|
||||
public SkinPair[] skinItems;
|
||||
|
||||
public Skin customSkin;
|
||||
#endregion
|
||||
|
||||
SkeletonRenderer skeletonRenderer;
|
||||
|
||||
void Start () {
|
||||
skeletonRenderer = GetComponent<SkeletonRenderer>();
|
||||
Skeleton skeleton = skeletonRenderer.skeleton;
|
||||
|
||||
customSkin = new Skin("CustomSkin");
|
||||
|
||||
foreach (var pair in skinning) {
|
||||
var attachment = SpineAttachment.GetAttachment(pair.sourceAttachment, skinSource);
|
||||
foreach (var pair in skinItems) {
|
||||
var attachment = SpineAttachment.GetAttachment(pair.sourceAttachmentPath, skinSource);
|
||||
customSkin.AddAttachment(skeleton.FindSlotIndex(pair.targetSlot), pair.targetAttachment, attachment);
|
||||
}
|
||||
|
||||
// The custom skin does not need to be added to the skeleton data for it to work.
|
||||
// But it's useful for your script to keep a reference to it.
|
||||
skeleton.SetSkin(customSkin);
|
||||
}
|
||||
}
|
||||
|
||||
@ -38,7 +38,7 @@ using Spine;
|
||||
public class SkeletonAnimationInspector : SkeletonRendererInspector {
|
||||
protected SerializedProperty animationName, loop, timeScale, autoReset;
|
||||
protected bool m_isPrefab;
|
||||
protected GUIContent autoResetLabel;
|
||||
protected bool wasAnimationNameChanged;
|
||||
|
||||
protected override void OnEnable () {
|
||||
base.OnEnable();
|
||||
@ -56,43 +56,45 @@ public class SkeletonAnimationInspector : SkeletonRendererInspector {
|
||||
SkeletonAnimation component = (SkeletonAnimation)target;
|
||||
if (!component.valid)
|
||||
return;
|
||||
|
||||
if (wasAnimationNameChanged) {
|
||||
if (!Application.isPlaying) {
|
||||
component.state.ClearTrack(0);
|
||||
component.skeleton.SetToSetupPose();
|
||||
}
|
||||
|
||||
//catch case where SetAnimation was used to set track 0 without using AnimationName
|
||||
Spine.Animation animationToUse = component.skeleton.Data.FindAnimation(animationName.stringValue);
|
||||
|
||||
if (!Application.isPlaying) {
|
||||
if (animationToUse != null) animationToUse.Apply(component.skeleton, 0f, 0f, false, null);
|
||||
component.Update();
|
||||
component.LateUpdate();
|
||||
SceneView.RepaintAll();
|
||||
} else {
|
||||
if (animationToUse != null)
|
||||
component.state.SetAnimation(0, animationToUse, loop.boolValue);
|
||||
else
|
||||
component.state.ClearTrack(0);
|
||||
}
|
||||
|
||||
wasAnimationNameChanged = false;
|
||||
}
|
||||
|
||||
// Reflect animationName serialized property in the inspector even if SetAnimation API was used.
|
||||
if (Application.isPlaying) {
|
||||
TrackEntry currentState = component.state.GetCurrent(0);
|
||||
if (currentState != null) {
|
||||
TrackEntry current = component.state.GetCurrent(0);
|
||||
if (current != null) {
|
||||
if (component.AnimationName != animationName.stringValue) {
|
||||
animationName.stringValue = currentState.Animation.Name;
|
||||
animationName.stringValue = current.Animation.Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
//TODO: Refactor this to use GenericMenu and callbacks to avoid interfering with control by other behaviours.
|
||||
// Animation name.
|
||||
{
|
||||
String[] animations = new String[component.skeleton.Data.Animations.Count + 1];
|
||||
animations[0] = "<None>";
|
||||
int animationIndex = 0;
|
||||
for (int i = 0; i < animations.Length - 1; i++) {
|
||||
String name = component.skeleton.Data.Animations.Items[i].Name;
|
||||
animations[i + 1] = name;
|
||||
if (name == animationName.stringValue)
|
||||
animationIndex = i + 1;
|
||||
}
|
||||
|
||||
animationIndex = EditorGUILayout.Popup("Animation", animationIndex, animations);
|
||||
|
||||
String selectedAnimationName = animationIndex == 0 ? null : animations[animationIndex];
|
||||
if (component.AnimationName != selectedAnimationName) {
|
||||
component.AnimationName = selectedAnimationName;
|
||||
animationName.stringValue = selectedAnimationName;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUILayout.PropertyField(animationName);
|
||||
wasAnimationNameChanged |= EditorGUI.EndChangeCheck();
|
||||
|
||||
EditorGUILayout.PropertyField(loop);
|
||||
EditorGUILayout.PropertyField(timeScale);
|
||||
component.timeScale = Math.Max(component.timeScale, 0);
|
||||
|
||||
@ -5,17 +5,19 @@
|
||||
*****************************************************************************/
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using Spine;
|
||||
|
||||
|
||||
|
||||
public struct SpineDrawerValuePair {
|
||||
public string str;
|
||||
public SerializedProperty property;
|
||||
|
||||
public SpineDrawerValuePair(string val, SerializedProperty property) {
|
||||
public SpineDrawerValuePair (string val, SerializedProperty property) {
|
||||
this.str = val;
|
||||
this.property = property;
|
||||
}
|
||||
@ -23,6 +25,7 @@ public struct SpineDrawerValuePair {
|
||||
|
||||
public abstract class SpineTreeItemDrawerBase<T> : PropertyDrawer where T:SpineAttributeBase {
|
||||
protected SkeletonDataAsset skeletonDataAsset;
|
||||
|
||||
protected T TargetAttribute { get { return (T)attribute; } }
|
||||
|
||||
public override void OnGUI (Rect position, SerializedProperty property, GUIContent label) {
|
||||
@ -72,7 +75,7 @@ public abstract class SpineTreeItemDrawerBase<T> : PropertyDrawer where T:SpineA
|
||||
return;
|
||||
|
||||
GenericMenu menu = new GenericMenu();
|
||||
PopulateMenu (menu, property, this.TargetAttribute, data);
|
||||
PopulateMenu(menu, property, this.TargetAttribute, data);
|
||||
menu.ShowAsContext();
|
||||
}
|
||||
|
||||
@ -84,7 +87,7 @@ public abstract class SpineTreeItemDrawerBase<T> : PropertyDrawer where T:SpineA
|
||||
pair.property.serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
public override float GetPropertyHeight(SerializedProperty property, GUIContent label) {
|
||||
public override float GetPropertyHeight (SerializedProperty property, GUIContent label) {
|
||||
return 18;
|
||||
}
|
||||
|
||||
@ -96,7 +99,7 @@ public class SpineSlotDrawer : SpineTreeItemDrawerBase<SpineSlot> {
|
||||
protected override void PopulateMenu (GenericMenu menu, SerializedProperty property, SpineSlot targetAttribute, SkeletonData data) {
|
||||
for (int i = 0; i < data.Slots.Count; i++) {
|
||||
string name = data.Slots.Items[i].Name;
|
||||
if (name.StartsWith(targetAttribute.startsWith)) {
|
||||
if (name.StartsWith(targetAttribute.startsWith, StringComparison.Ordinal)) {
|
||||
if (targetAttribute.containsBoundingBoxes) {
|
||||
|
||||
int slotIndex = i;
|
||||
@ -139,7 +142,7 @@ public class SpineSkinDrawer : SpineTreeItemDrawerBase<SpineSkin> {
|
||||
|
||||
for (int i = 0; i < data.Skins.Count; i++) {
|
||||
string name = data.Skins.Items[i].Name;
|
||||
if (name.StartsWith(targetAttribute.startsWith))
|
||||
if (name.StartsWith(targetAttribute.startsWith, StringComparison.Ordinal))
|
||||
menu.AddItem(new GUIContent(name), name == property.stringValue, HandleSelect, new SpineDrawerValuePair(name, property));
|
||||
}
|
||||
}
|
||||
@ -150,9 +153,13 @@ public class SpineSkinDrawer : SpineTreeItemDrawerBase<SpineSkin> {
|
||||
public class SpineAnimationDrawer : SpineTreeItemDrawerBase<SpineAnimation> {
|
||||
protected override void PopulateMenu (GenericMenu menu, SerializedProperty property, SpineAnimation targetAttribute, SkeletonData data) {
|
||||
var animations = skeletonDataAsset.GetAnimationStateData().SkeletonData.Animations;
|
||||
|
||||
// <None> item
|
||||
menu.AddItem(new GUIContent("<None>"), property.stringValue == "", HandleSelect, new SpineDrawerValuePair("", property));
|
||||
|
||||
for (int i = 0; i < animations.Count; i++) {
|
||||
string name = animations.Items[i].Name;
|
||||
if (name.StartsWith(targetAttribute.startsWith))
|
||||
if (name.StartsWith(targetAttribute.startsWith, StringComparison.Ordinal))
|
||||
menu.AddItem(new GUIContent(name), name == property.stringValue, HandleSelect, new SpineDrawerValuePair(name, property));
|
||||
}
|
||||
}
|
||||
@ -165,7 +172,7 @@ public class SpineEventNameDrawer : SpineTreeItemDrawerBase<SpineEvent> {
|
||||
var events = skeletonDataAsset.GetSkeletonData(false).Events;
|
||||
for (int i = 0; i < events.Count; i++) {
|
||||
string name = events.Items[i].Name;
|
||||
if (name.StartsWith(targetAttribute.startsWith))
|
||||
if (name.StartsWith(targetAttribute.startsWith, StringComparison.Ordinal))
|
||||
menu.AddItem(new GUIContent(name), name == property.stringValue, HandleSelect, new SpineDrawerValuePair(name, property));
|
||||
}
|
||||
}
|
||||
@ -289,8 +296,8 @@ public class SpineBoneDrawer : SpineTreeItemDrawerBase<SpineBone> {
|
||||
public class SpineAtlasRegionDrawer : PropertyDrawer {
|
||||
Component component;
|
||||
SerializedProperty atlasProp;
|
||||
|
||||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) {
|
||||
|
||||
public override void OnGUI (Rect position, SerializedProperty property, GUIContent label) {
|
||||
if (property.propertyType != SerializedPropertyType.String) {
|
||||
EditorGUI.LabelField(position, "ERROR:", "May only apply to type string");
|
||||
return;
|
||||
@ -321,7 +328,7 @@ public class SpineAtlasRegionDrawer : PropertyDrawer {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void Selector (SerializedProperty property) {
|
||||
GenericMenu menu = new GenericMenu();
|
||||
AtlasAsset atlasAsset = (AtlasAsset)atlasProp.objectReferenceValue;
|
||||
@ -337,7 +344,7 @@ public class SpineAtlasRegionDrawer : PropertyDrawer {
|
||||
|
||||
menu.ShowAsContext();
|
||||
}
|
||||
|
||||
|
||||
static void HandleSelect (object val) {
|
||||
var pair = (SpineDrawerValuePair)val;
|
||||
pair.property.stringValue = pair.str;
|
||||
|
||||
@ -68,6 +68,7 @@ public class SkeletonAnimation : SkeletonRenderer, ISkeletonAnimation {
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
[SpineAnimation]
|
||||
private String _animationName;
|
||||
|
||||
public String AnimationName {
|
||||
@ -104,39 +105,25 @@ public class SkeletonAnimation : SkeletonRenderer, ISkeletonAnimation {
|
||||
public bool loop;
|
||||
|
||||
/// <summary>
|
||||
/// The rate at which animations progress over time. 1 means 100%. 0.5 means 50%.
|
||||
/// AnimationState and TrackEntry also have their own timeScale. These are combined multiplicatively.</summary>
|
||||
/// The rate at which animations progress over time. 1 means 100%. 0.5 means 50%.</summary>
|
||||
/// <remarks>AnimationState and TrackEntry also have their own timeScale. These are combined multiplicatively.</remarks>
|
||||
#if UNITY_5
|
||||
[Tooltip("The rate at which animations progress over time. 1 means 100%. 0.5 means 50%.")]
|
||||
#endif
|
||||
public float timeScale = 1;
|
||||
|
||||
#region AutoReset
|
||||
/**
|
||||
[Tooltip("Setting this to true makes the SkeletonAnimation behave similar to Spine editor. New animations will not inherit the pose from a previous animation. If you need to intermittently and programmatically pose your skeleton, leave this false.")]
|
||||
[SerializeField]
|
||||
protected bool autoReset = false;
|
||||
|
||||
/// <summary>
|
||||
/// Setting this to true makes the SkeletonAnimation behave similar to Spine editor.
|
||||
/// New animations will not inherit the pose from a previous animation.
|
||||
/// If you need to intermittently and programmatically pose your skeleton, leave this false.</summary>
|
||||
public bool AutoReset {
|
||||
get { return this.autoReset; }
|
||||
set {
|
||||
if (!autoReset && value) {
|
||||
state.Start -= HandleNewAnimationAutoreset; // make sure there isn't a double-subscription.
|
||||
state.Start += HandleNewAnimationAutoreset;
|
||||
}
|
||||
autoReset = value;
|
||||
}
|
||||
#region Runtime Instantiation
|
||||
/// <summary>Adds and prepares a SkeletonAnimation component to a GameObject at runtime.</summary>
|
||||
/// <returns>The newly instantiated SkeletonAnimation</returns>
|
||||
public static SkeletonAnimation AddToGameObject (GameObject gameObject, SkeletonDataAsset skeletonDataAsset) {
|
||||
return SkeletonRenderer.AddSpineComponent<SkeletonAnimation>(gameObject, skeletonDataAsset);
|
||||
}
|
||||
|
||||
protected virtual void HandleNewAnimationAutoreset (Spine.AnimationState state, int trackIndex) {
|
||||
if (!autoReset) return;
|
||||
if (skeleton != null) skeleton.SetToSetupPose();
|
||||
/// <summary>Instantiates a new UnityEngine.GameObject and adds a prepared SkeletonAnimation component to it.</summary>
|
||||
/// <returns>The newly instantiated SkeletonAnimation component.</returns>
|
||||
public static SkeletonAnimation NewSkeletonAnimationGameObject (SkeletonDataAsset skeletonDataAsset) {
|
||||
return SkeletonRenderer.NewSpineGameObject<SkeletonAnimation>(skeletonDataAsset);
|
||||
}
|
||||
*/
|
||||
#endregion
|
||||
|
||||
public override void Reset () {
|
||||
@ -146,16 +133,24 @@ public class SkeletonAnimation : SkeletonRenderer, ISkeletonAnimation {
|
||||
|
||||
state = new Spine.AnimationState(skeletonDataAsset.GetAnimationStateData());
|
||||
|
||||
/*
|
||||
if (autoReset) {
|
||||
state.Start += HandleNewAnimationAutoreset;
|
||||
#if UNITY_EDITOR
|
||||
if (!string.IsNullOrEmpty(_animationName)) {
|
||||
if (Application.isPlaying) {
|
||||
state.SetAnimation(0, _animationName, loop);
|
||||
} else {
|
||||
// Assume SkeletonAnimation is valid for skeletonData and skeleton. Checked above.
|
||||
var animationObject = skeletonDataAsset.GetSkeletonData(false).FindAnimation(_animationName);
|
||||
if (animationObject != null)
|
||||
animationObject.Apply(skeleton, 0f, 0f, false, null);
|
||||
}
|
||||
Update(0);
|
||||
}
|
||||
*/
|
||||
|
||||
if (_animationName != null && _animationName.Length > 0) {
|
||||
#else
|
||||
if (!string.IsNullOrEmpty(_animationName)) {
|
||||
state.SetAnimation(0, _animationName, loop);
|
||||
Update(0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public virtual void Update () {
|
||||
@ -185,4 +180,5 @@ public class SkeletonAnimation : SkeletonRenderer, ISkeletonAnimation {
|
||||
_UpdateComplete(this);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* Spine Extensions created by Mitch Thompson
|
||||
* Spine Extensions by Mitch Thompson and John Dy
|
||||
* Full irrevocable rights and permissions granted to Esoteric Software
|
||||
*****************************************************************************/
|
||||
|
||||
@ -11,6 +11,14 @@ using Spine;
|
||||
|
||||
public static class SkeletonExtensions {
|
||||
|
||||
const float ByteToFloat = 1f / 255f;
|
||||
|
||||
#region Colors
|
||||
public static Color GetColor (this Skeleton s) { return new Color(s.r, s.g, s.b, s.a); }
|
||||
public static Color GetColor (this RegionAttachment a) { return new Color(a.r, a.g, a.b, a.a); }
|
||||
public static Color GetColor (this MeshAttachment a) { return new Color(a.r, a.g, a.b, a.a); }
|
||||
public static Color GetColor (this SkinnedMeshAttachment a) { return new Color(a.r, a.g, a.b, a.a); }
|
||||
|
||||
public static void SetColor (this Skeleton skeleton, Color color) {
|
||||
skeleton.A = color.a;
|
||||
skeleton.R = color.r;
|
||||
@ -19,10 +27,10 @@ public static class SkeletonExtensions {
|
||||
}
|
||||
|
||||
public static void SetColor (this Skeleton skeleton, Color32 color) {
|
||||
skeleton.A = color.a / 255f;
|
||||
skeleton.R = color.r / 255f;
|
||||
skeleton.G = color.g / 255f;
|
||||
skeleton.B = color.b / 255f;
|
||||
skeleton.A = color.a * ByteToFloat;
|
||||
skeleton.R = color.r * ByteToFloat;
|
||||
skeleton.G = color.g * ByteToFloat;
|
||||
skeleton.B = color.b * ByteToFloat;
|
||||
}
|
||||
|
||||
public static void SetColor (this Slot slot, Color color) {
|
||||
@ -33,10 +41,10 @@ public static class SkeletonExtensions {
|
||||
}
|
||||
|
||||
public static void SetColor (this Slot slot, Color32 color) {
|
||||
slot.A = color.a / 255f;
|
||||
slot.R = color.r / 255f;
|
||||
slot.G = color.g / 255f;
|
||||
slot.B = color.b / 255f;
|
||||
slot.A = color.a * ByteToFloat;
|
||||
slot.R = color.r * ByteToFloat;
|
||||
slot.G = color.g * ByteToFloat;
|
||||
slot.B = color.b * ByteToFloat;
|
||||
}
|
||||
|
||||
public static void SetColor (this RegionAttachment attachment, Color color) {
|
||||
@ -47,10 +55,10 @@ public static class SkeletonExtensions {
|
||||
}
|
||||
|
||||
public static void SetColor (this RegionAttachment attachment, Color32 color) {
|
||||
attachment.A = color.a / 255f;
|
||||
attachment.R = color.r / 255f;
|
||||
attachment.G = color.g / 255f;
|
||||
attachment.B = color.b / 255f;
|
||||
attachment.A = color.a * ByteToFloat;
|
||||
attachment.R = color.r * ByteToFloat;
|
||||
attachment.G = color.g * ByteToFloat;
|
||||
attachment.B = color.b * ByteToFloat;
|
||||
}
|
||||
|
||||
public static void SetColor (this MeshAttachment attachment, Color color) {
|
||||
@ -61,10 +69,10 @@ public static class SkeletonExtensions {
|
||||
}
|
||||
|
||||
public static void SetColor (this MeshAttachment attachment, Color32 color) {
|
||||
attachment.A = color.a / 255f;
|
||||
attachment.R = color.r / 255f;
|
||||
attachment.G = color.g / 255f;
|
||||
attachment.B = color.b / 255f;
|
||||
attachment.A = color.a * ByteToFloat;
|
||||
attachment.R = color.r * ByteToFloat;
|
||||
attachment.G = color.g * ByteToFloat;
|
||||
attachment.B = color.b * ByteToFloat;
|
||||
}
|
||||
|
||||
public static void SetColor (this SkinnedMeshAttachment attachment, Color color) {
|
||||
@ -75,12 +83,14 @@ public static class SkeletonExtensions {
|
||||
}
|
||||
|
||||
public static void SetColor (this SkinnedMeshAttachment attachment, Color32 color) {
|
||||
attachment.A = color.a / 255f;
|
||||
attachment.R = color.r / 255f;
|
||||
attachment.G = color.g / 255f;
|
||||
attachment.B = color.b / 255f;
|
||||
attachment.A = color.a * ByteToFloat;
|
||||
attachment.R = color.r * ByteToFloat;
|
||||
attachment.G = color.g * ByteToFloat;
|
||||
attachment.B = color.b * ByteToFloat;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Bone Position
|
||||
public static void SetPosition (this Bone bone, Vector2 position) {
|
||||
bone.X = position.x;
|
||||
bone.Y = position.y;
|
||||
@ -91,10 +101,36 @@ public static class SkeletonExtensions {
|
||||
bone.Y = position.y;
|
||||
}
|
||||
|
||||
public static Vector2 GetSkeletonSpacePosition (this Bone bone) {
|
||||
// TODO: This changes in v3.0
|
||||
return new Vector2(bone.worldX, bone.worldY);
|
||||
}
|
||||
|
||||
public static Vector3 GetWorldPosition (this Bone bone, UnityEngine.Transform parentTransform) {
|
||||
return parentTransform.TransformPoint(new Vector3(bone.worldX, bone.worldY));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Posing
|
||||
/// <summary>
|
||||
/// Shortcut for posing a skeleton at a specific time. Time is in seconds. (frameNumber / 30f) will give you seconds.
|
||||
/// If you need to do this often, you should get the Animation object yourself using skeleton.data.FindAnimation. and call Apply on that.</summary>
|
||||
/// <param name = "skeleton">The skeleton to pose.</param>
|
||||
/// <param name="animationName">The name of the animation to use.</param>
|
||||
/// <param name = "time">The time of the pose within the animation.</param>
|
||||
/// <param name = "loop">Wraps the time around if it is longer than the duration of the animation.</param>
|
||||
public static void PoseWithAnimation (this Skeleton skeleton, string animationName, float time, bool loop) {
|
||||
// Fail loud when skeleton.data is null.
|
||||
Spine.Animation animation = skeleton.data.FindAnimation(animationName);
|
||||
if (animation == null) return;
|
||||
animation.Apply(skeleton, 0, time, loop, null);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Unity Sprite To Attachments
|
||||
public static Attachment AttachUnitySprite (this Skeleton skeleton, string slotName, Sprite sprite, string shaderName = "Spine/Skeleton") {
|
||||
var att = sprite.ToRegionAttachment(shaderName);
|
||||
skeleton.FindSlot(slotName).Attachment = att;
|
||||
|
||||
return att;
|
||||
}
|
||||
|
||||
@ -117,4 +153,6 @@ public static class SkeletonExtensions {
|
||||
loader = null;
|
||||
return att;
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
@ -76,6 +76,26 @@ public class SkeletonRenderer : MonoBehaviour {
|
||||
private readonly ExposedList<Submesh> submeshes = new ExposedList<Submesh>();
|
||||
private SkeletonUtilitySubmeshRenderer[] submeshRenderers;
|
||||
|
||||
#region Runtime Instantiation
|
||||
/// <summary>Add and prepare a Spine component that derives from SkeletonRenderer to a GameObject at runtime.</summary>
|
||||
/// <typeparam name="T">T should be SkeletonRenderer or any of its derived classes.</typeparam>
|
||||
public static T AddSpineComponent<T> (GameObject gameObject, SkeletonDataAsset skeletonDataAsset) where T : SkeletonRenderer {
|
||||
|
||||
var c = gameObject.AddComponent<T>();
|
||||
|
||||
if (skeletonDataAsset != null) {
|
||||
c.skeletonDataAsset = skeletonDataAsset;
|
||||
c.Reset(); // TODO: Method name will change.
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
public static T NewSpineGameObject<T> (SkeletonDataAsset skeletonDataAsset) where T : SkeletonRenderer {
|
||||
return SkeletonRenderer.AddSpineComponent<T>(new GameObject("New Spine GameObject"), skeletonDataAsset);
|
||||
}
|
||||
#endregion
|
||||
|
||||
public virtual void Awake () {
|
||||
Reset();
|
||||
}
|
||||
|
||||
@ -85,14 +85,14 @@ public class SpineAttachment : SpineAttributeBase {
|
||||
/// Smart popup menu for Spine Attachments
|
||||
/// </summary>
|
||||
/// <param name="currentSkinOnly">Filters popup results to only include the current Skin. Only valid when a SkeletonRenderer is the data source.</param>
|
||||
/// <param name="returnAttachmentPath">Returns a fully qualified path for an Attachment in the format "Skin/Slot/AttachmentName"</param>
|
||||
/// <param name="returnAttachmentPath">Returns a fully qualified path for an Attachment in the format "Skin/Slot/AttachmentName". This path format is only used by the SpineAttachment helper methods like SpineAttachment.GetAttachment and .GetHierarchy. Do not use full path anywhere else in Spine's system.</param>
|
||||
/// <param name="placeholdersOnly">Filters popup results to exclude attachments that are not children of Skin Placeholders</param>
|
||||
/// <param name="slotField">If specified, a locally scoped field with the name supplied by in slotField will be used to limit the popup results to children of a named slot</param>
|
||||
/// <param name="dataField">If specified, a locally scoped field with the name supplied by in dataField will be used to fill the popup results.
|
||||
/// Valid types are SkeletonDataAsset and SkeletonRenderer (and derivatives)
|
||||
/// If left empty and the script the attribute is applied to is derived from Component, GetComponent<SkeletonRenderer>() will be called as a fallback.
|
||||
/// </param>
|
||||
public SpineAttachment(bool currentSkinOnly = true, bool returnAttachmentPath = false, bool placeholdersOnly = false, string slotField = "", string dataField = "") {
|
||||
public SpineAttachment (bool currentSkinOnly = true, bool returnAttachmentPath = false, bool placeholdersOnly = false, string slotField = "", string dataField = "") {
|
||||
this.currentSkinOnly = currentSkinOnly;
|
||||
this.returnAttachmentPath = returnAttachmentPath;
|
||||
this.placeholdersOnly = placeholdersOnly;
|
||||
@ -100,11 +100,11 @@ public class SpineAttachment : SpineAttributeBase {
|
||||
this.dataField = dataField;
|
||||
}
|
||||
|
||||
public static Hierarchy GetHierarchy(string fullPath) {
|
||||
return new Hierarchy(fullPath);
|
||||
public static SpineAttachment.Hierarchy GetHierarchy (string fullPath) {
|
||||
return new SpineAttachment.Hierarchy(fullPath);
|
||||
}
|
||||
|
||||
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);
|
||||
if (hierarchy.name == "")
|
||||
return null;
|
||||
@ -112,16 +112,18 @@ public class SpineAttachment : SpineAttributeBase {
|
||||
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) {
|
||||
return GetAttachment(attachmentPath, skeletonDataAsset.GetSkeletonData(true));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A struct that represents 3 strings that help identify and locate an attachment in a skeleton.</summary>
|
||||
public struct Hierarchy {
|
||||
public string skin;
|
||||
public string slot;
|
||||
public string name;
|
||||
|
||||
public Hierarchy(string fullPath) {
|
||||
public Hierarchy (string fullPath) {
|
||||
string[] chunks = fullPath.Split(new char[]{'/'}, System.StringSplitOptions.RemoveEmptyEntries);
|
||||
if (chunks.Length == 0) {
|
||||
skin = "";
|
||||
@ -157,15 +159,11 @@ public class SpineBone : SpineAttributeBase {
|
||||
}
|
||||
|
||||
public static Spine.Bone GetBone(string boneName, SkeletonRenderer renderer) {
|
||||
if (renderer.skeleton == null)
|
||||
return null;
|
||||
|
||||
return renderer.skeleton.FindBone(boneName);
|
||||
return renderer.skeleton == null ? null : renderer.skeleton.FindBone(boneName);
|
||||
}
|
||||
|
||||
public static Spine.BoneData GetBoneData(string boneName, SkeletonDataAsset skeletonDataAsset) {
|
||||
var data = skeletonDataAsset.GetSkeletonData(true);
|
||||
|
||||
return data.FindBone(boneName);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user