mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-04 22:34:53 +08:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
b139932dc2
@ -61,17 +61,24 @@ public class Menus {
|
||||
Selection.activeObject = asset;
|
||||
}
|
||||
|
||||
[MenuItem("GameObject/Create Other/Spine SkeletonRenderer")]
|
||||
[MenuItem("GameObject/Spine/SkeletonRenderer", false, 10)]
|
||||
static public void CreateSkeletonRendererGameObject () {
|
||||
GameObject gameObject = new GameObject("New SkeletonRenderer", typeof(SkeletonRenderer));
|
||||
EditorUtility.FocusProjectWindow();
|
||||
Selection.activeObject = gameObject;
|
||||
CreateSpineGameObject<SkeletonRenderer>("New SkeletonRenderer");
|
||||
}
|
||||
|
||||
[MenuItem("GameObject/Create Other/Spine SkeletonAnimation")]
|
||||
[MenuItem("GameObject/Spine/SkeletonAnimation", false, 10)]
|
||||
static public void CreateSkeletonAnimationGameObject () {
|
||||
GameObject gameObject = new GameObject("New SkeletonAnimation", typeof(SkeletonAnimation));
|
||||
CreateSpineGameObject<SkeletonAnimation>("New SkeletonAnimation");
|
||||
}
|
||||
|
||||
static public void CreateSpineGameObject<T> (string name) where T : MonoBehaviour {
|
||||
var parentGameObject = Selection.activeObject as GameObject;
|
||||
var parentTransform = parentGameObject == null ? null : parentGameObject.transform;
|
||||
|
||||
var gameObject = new GameObject("New SkeletonRenderer", typeof(T));
|
||||
gameObject.transform.SetParent(parentTransform, false);
|
||||
EditorUtility.FocusProjectWindow();
|
||||
Selection.activeObject = gameObject;
|
||||
EditorGUIUtility.PingObject(Selection.activeObject);
|
||||
}
|
||||
}
|
||||
|
||||
@ -59,7 +59,7 @@ public class SkeletonAnimationInspector : SkeletonRendererInspector {
|
||||
|
||||
if (wasAnimationNameChanged) {
|
||||
if (!Application.isPlaying) {
|
||||
component.state.ClearTrack(0);
|
||||
if (component.state != null) component.state.ClearTrack(0);
|
||||
component.skeleton.SetToSetupPose();
|
||||
}
|
||||
|
||||
|
||||
@ -138,7 +138,11 @@ public class SkeletonRendererInspector : Editor {
|
||||
EditorGUILayout.PropertyField(immutableTriangles,
|
||||
new GUIContent("Immutable Triangles", "Enable to optimize rendering for skeletons that never change attachment visbility"));
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.PropertyField(zSpacing);
|
||||
|
||||
const float MinZSpacing = 0f;
|
||||
const float MaxZSpacing = 0.1f;
|
||||
EditorGUILayout.Slider(zSpacing, MinZSpacing, MaxZSpacing);
|
||||
|
||||
EditorGUILayout.PropertyField(normals);
|
||||
EditorGUILayout.PropertyField(tangents);
|
||||
EditorGUILayout.PropertyField(front);
|
||||
|
||||
@ -35,7 +35,7 @@ using System.Collections;
|
||||
namespace Spine.Unity {
|
||||
public class ArraysSimpleMeshGenerator : ISimpleMeshGenerator {
|
||||
#region Settings
|
||||
protected float scale;
|
||||
protected float scale = 1f;
|
||||
public float Scale {
|
||||
get { return scale; }
|
||||
set { scale = value; }
|
||||
@ -53,6 +53,9 @@ namespace Spine.Unity {
|
||||
private int[] triangles;
|
||||
#endregion
|
||||
|
||||
private Mesh lastGeneratedMesh;
|
||||
public Mesh LastGeneratedMesh { get { return lastGeneratedMesh; } }
|
||||
|
||||
public Mesh GenerateMesh (Skeleton skeleton) {
|
||||
int totalVertexCount = 0; // size of vertex arrays
|
||||
int totalTriangleCount = 0; // size of index array
|
||||
@ -309,10 +312,12 @@ namespace Spine.Unity {
|
||||
mesh.uv = uvs;
|
||||
|
||||
Vector3 meshBoundsExtents = (meshBoundsMax - meshBoundsMin) * scale;
|
||||
mesh.bounds = new Bounds(meshBoundsMin + meshBoundsExtents * 0.5f, meshBoundsExtents);
|
||||
Vector3 meshCenter = (meshBoundsMin * scale) + meshBoundsExtents * 0.5f;
|
||||
mesh.bounds = new Bounds(meshCenter, meshBoundsExtents);
|
||||
|
||||
mesh.SetTriangles(triangles, 0);
|
||||
|
||||
lastGeneratedMesh = mesh;
|
||||
return mesh;
|
||||
}
|
||||
|
||||
|
||||
@ -6,5 +6,6 @@
|
||||
public interface ISimpleMeshGenerator {
|
||||
float Scale { set; }
|
||||
UnityEngine.Mesh GenerateMesh (Spine.Skeleton skeleton);
|
||||
UnityEngine.Mesh LastGeneratedMesh { get; }
|
||||
}
|
||||
}
|
||||
|
||||
@ -45,6 +45,9 @@ namespace Spine.Unity {
|
||||
|
||||
public int CurrentVertexCount { get { return this.positions.Count; } }
|
||||
|
||||
private Mesh lastGeneratedMesh;
|
||||
public Mesh LastGeneratedMesh { get { return lastGeneratedMesh; } }
|
||||
|
||||
public Mesh GenerateMesh (Skeleton skeleton) {
|
||||
skeletonColor.r = skeleton.r;
|
||||
skeletonColor.g = skeleton.g;
|
||||
@ -59,6 +62,7 @@ namespace Spine.Unity {
|
||||
|
||||
Mesh currentMesh = doubleBufferedMesh.GetNextMesh();
|
||||
FillMesh(currentMesh);
|
||||
lastGeneratedMesh = currentMesh;
|
||||
return currentMesh;
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 78bba472871bc624f8930d51dea6dd3d
|
||||
folderAsset: yes
|
||||
timeCreated: 1455570938
|
||||
licenseType: Free
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,204 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
using UnityEditor;
|
||||
using Spine;
|
||||
|
||||
[CustomEditor(typeof(SkeletonGraphic))]
|
||||
public class SkeletonGraphicInspector : Editor {
|
||||
SerializedProperty material_, color_;
|
||||
SerializedProperty skeletonDataAsset_, initialSkinName_;
|
||||
SerializedProperty startingAnimation_, startingLoop_, timeScale_, freeze_;
|
||||
SerializedProperty raycastTarget_;
|
||||
|
||||
SkeletonGraphic thisSkeletonGraphic;
|
||||
|
||||
void OnEnable () {
|
||||
var so = this.serializedObject;
|
||||
thisSkeletonGraphic = target as SkeletonGraphic;
|
||||
|
||||
// MaskableGraphic
|
||||
material_ = so.FindProperty("m_Material");
|
||||
color_ = so.FindProperty("m_Color");
|
||||
raycastTarget_ = so.FindProperty("m_RaycastTarget");
|
||||
|
||||
// SkeletonRenderer
|
||||
skeletonDataAsset_ = so.FindProperty("skeletonDataAsset");
|
||||
initialSkinName_ = so.FindProperty("initialSkinName");
|
||||
|
||||
// SkeletonAnimation
|
||||
startingAnimation_ = so.FindProperty("startingAnimation");
|
||||
startingLoop_ = so.FindProperty("startingLoop");
|
||||
timeScale_ = so.FindProperty("timeScale");
|
||||
freeze_ = so.FindProperty("freeze");
|
||||
}
|
||||
|
||||
|
||||
public override void OnInspectorGUI () {
|
||||
|
||||
var s = thisSkeletonGraphic;
|
||||
s.skeletonDataAsset = SkeletonGraphicInspector.ObjectField<SkeletonDataAsset>(skeletonDataAsset_);
|
||||
s.material = SkeletonGraphicInspector.ObjectField<Material>(material_);
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
thisSkeletonGraphic.color = EditorGUILayout.ColorField(color_.displayName, color_.colorValue);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
SkeletonGraphicInspector.ForceUpdateHack(thisSkeletonGraphic.transform);
|
||||
|
||||
if (thisSkeletonGraphic.skeletonDataAsset == null) {
|
||||
EditorGUILayout.HelpBox("You need to assign a SkeletonDataAsset first.", MessageType.Info);
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
serializedObject.Update();
|
||||
return;
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.PropertyField(initialSkinName_);
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.LabelField("Animation", EditorStyles.boldLabel);
|
||||
EditorGUILayout.PropertyField(startingAnimation_);
|
||||
s.startingLoop = SkeletonGraphicInspector.BoolField(startingLoop_);
|
||||
s.timeScale = EditorGUILayout.FloatField(timeScale_.displayName, timeScale_.floatValue);
|
||||
EditorGUILayout.Space();
|
||||
s.freeze = SkeletonGraphicInspector.BoolField(freeze_);
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.LabelField("UI", EditorStyles.boldLabel);
|
||||
s.raycastTarget = SkeletonGraphicInspector.BoolField(raycastTarget_);
|
||||
|
||||
}
|
||||
|
||||
#region HAX - Thanks, Unity
|
||||
// colors weren't updating in realtime in the custom inspector.
|
||||
// Why the hell do I have to do this??
|
||||
/// <summary>Use this when scene repaint and proper explicit update methods don't work.</summary>
|
||||
public static void ForceUpdateHack (Transform t) {
|
||||
var origValue = t.localScale;
|
||||
t.localScale = new Vector3(11f, 22f, 33f);
|
||||
t.localScale = origValue;
|
||||
}
|
||||
|
||||
// Hack for Unity 5.3 problem with PropertyField
|
||||
public static T ObjectField<T> (SerializedProperty property) where T : UnityEngine.Object {
|
||||
return (T)EditorGUILayout.ObjectField(property.displayName, property.objectReferenceValue, typeof(T), false);
|
||||
}
|
||||
|
||||
public static bool BoolField (SerializedProperty property) {
|
||||
return EditorGUILayout.Toggle(property.displayName, property.boolValue);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Menus
|
||||
// Add a menu item called "Double Mass" to a Rigidbody's context menu.
|
||||
[MenuItem ("CONTEXT/SkeletonGraphic/Match RectTransform with Mesh Bounds")]
|
||||
static void MatchRectTransformWithBounds (MenuCommand command) {
|
||||
var skeletonGraphic = (SkeletonGraphic)command.context;
|
||||
var mesh = skeletonGraphic.SpineMeshGenerator.LastGeneratedMesh;
|
||||
|
||||
var bounds = mesh.bounds;
|
||||
var size = bounds.size;
|
||||
var center = bounds.center;
|
||||
var p = new Vector2(
|
||||
0.5f - (center.x / size.x),
|
||||
0.5f - (center.y / size.y)
|
||||
);
|
||||
|
||||
skeletonGraphic.rectTransform.sizeDelta = size;
|
||||
skeletonGraphic.rectTransform.pivot = p;
|
||||
}
|
||||
|
||||
public static Material DefaultSkeletonGraphicMaterial {
|
||||
get {
|
||||
var guids = AssetDatabase.FindAssets("SkeletonGraphicDefault t:material"); if (guids.Length <= 0) return null;
|
||||
var firstAssetPath = AssetDatabase.GUIDToAssetPath(guids[0]); if (string.IsNullOrEmpty(firstAssetPath)) return null;
|
||||
var firstMaterial = AssetDatabase.LoadAssetAtPath<Material>(firstAssetPath);
|
||||
return firstMaterial;
|
||||
}
|
||||
}
|
||||
|
||||
[MenuItem("GameObject/Spine/SkeletonGraphic (UnityUI)", false, 10)]
|
||||
static public void SkeletonGraphicCreateMenuItem () {
|
||||
var parentGameObject = Selection.activeObject as GameObject;
|
||||
var parentTransform = parentGameObject == null ? null : parentGameObject.GetComponent<RectTransform>();
|
||||
|
||||
if (parentTransform == null) {
|
||||
Debug.LogWarning("Your new SkeletonGraphic will not be visible until it is placed under a Canvas");
|
||||
}
|
||||
|
||||
var gameObject = NewSkeletonGraphicGameObject("New SkeletonGraphic");
|
||||
gameObject.transform.SetParent(parentTransform, false);
|
||||
EditorUtility.FocusProjectWindow();
|
||||
Selection.activeObject = gameObject;
|
||||
EditorGUIUtility.PingObject(Selection.activeObject);
|
||||
}
|
||||
|
||||
[MenuItem("Assets/Spine/Instantiate (UnityUI)", false, 0)]
|
||||
static void InstantiateSkeletonGraphic () {
|
||||
Object[] arr = Selection.objects;
|
||||
foreach (Object o in arr) {
|
||||
string guid = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(o));
|
||||
string skinName = EditorPrefs.GetString(guid + "_lastSkin", "");
|
||||
|
||||
InstantiateSkeletonGraphic((SkeletonDataAsset)o, skinName);
|
||||
SceneView.RepaintAll();
|
||||
}
|
||||
}
|
||||
|
||||
[MenuItem("Assets/Spine/Instantiate (UnityUI)", true, 0)]
|
||||
static bool ValidateInstantiateSkeletonGraphic () {
|
||||
Object[] arr = Selection.objects;
|
||||
|
||||
if (arr.Length == 0)
|
||||
return false;
|
||||
|
||||
foreach (var selected in arr) {
|
||||
if (selected.GetType() != typeof(SkeletonDataAsset))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static SkeletonGraphic InstantiateSkeletonGraphic (SkeletonDataAsset skeletonDataAsset, string skinName) {
|
||||
return InstantiateSkeletonGraphic(skeletonDataAsset, skeletonDataAsset.GetSkeletonData(true).FindSkin(skinName));
|
||||
}
|
||||
|
||||
public static SkeletonGraphic InstantiateSkeletonGraphic (SkeletonDataAsset skeletonDataAsset, Skin skin = null) {
|
||||
string spineGameObjectName = string.Format("SkeletonGraphic ({0})", skeletonDataAsset.name.Replace("_SkeletonData", ""));
|
||||
var go = NewSkeletonGraphicGameObject(spineGameObjectName);
|
||||
var graphic = go.GetComponent<SkeletonGraphic>();
|
||||
graphic.skeletonDataAsset = skeletonDataAsset;
|
||||
|
||||
SkeletonData data = skeletonDataAsset.GetSkeletonData(true);
|
||||
|
||||
if (data == null) {
|
||||
for (int i = 0; i < skeletonDataAsset.atlasAssets.Length; i++) {
|
||||
string reloadAtlasPath = AssetDatabase.GetAssetPath(skeletonDataAsset.atlasAssets[i]);
|
||||
skeletonDataAsset.atlasAssets[i] = (AtlasAsset)AssetDatabase.LoadAssetAtPath(reloadAtlasPath, typeof(AtlasAsset));
|
||||
}
|
||||
|
||||
data = skeletonDataAsset.GetSkeletonData(true);
|
||||
}
|
||||
|
||||
if (skin == null)
|
||||
skin = data.DefaultSkin;
|
||||
|
||||
if (skin == null)
|
||||
skin = data.Skins.Items[0];
|
||||
|
||||
graphic.Initialize(false);
|
||||
graphic.Skeleton.SetSkin(skin);
|
||||
graphic.initialSkinName = skin.Name;
|
||||
graphic.Skeleton.UpdateWorldTransform();
|
||||
graphic.UpdateMesh();
|
||||
|
||||
return graphic;
|
||||
}
|
||||
|
||||
static GameObject NewSkeletonGraphicGameObject (string gameObjectName) {
|
||||
var go = new GameObject(gameObjectName, typeof(RectTransform), typeof(CanvasRenderer), typeof(SkeletonGraphic));
|
||||
var graphic = go.GetComponent<SkeletonGraphic>();
|
||||
graphic.material = SkeletonGraphicInspector.DefaultSkeletonGraphicMaterial;
|
||||
return go;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0d81cc76b52fcdf499b2db252a317726
|
||||
timeCreated: 1455570945
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -34,20 +34,16 @@ using System.Collections;
|
||||
using UnityEngine.UI;
|
||||
using Spine;
|
||||
|
||||
public delegate void SkeletonGraphicDelegate (SkeletonGraphic skeletonGraphic);
|
||||
|
||||
[ExecuteInEditMode, RequireComponent(typeof(CanvasRenderer), typeof(RectTransform)), DisallowMultipleComponent]
|
||||
[AddComponentMenu("Spine/SkeletonGraphic (Unity UI Canvas)")]
|
||||
public class SkeletonGraphic : MaskableGraphic {
|
||||
|
||||
#region Inspector
|
||||
[Header("Skeleton Renderer")]
|
||||
public SkeletonDataAsset skeletonDataAsset;
|
||||
|
||||
[SpineSkin(dataField:"skeletonDataAsset")]
|
||||
public string initialSkinName = "default";
|
||||
|
||||
[Header("Skeleton Animation")]
|
||||
[SpineAnimation(dataField:"skeletonDataAsset")]
|
||||
public string startingAnimation;
|
||||
public bool startingLoop;
|
||||
@ -74,11 +70,13 @@ public class SkeletonGraphic : MaskableGraphic {
|
||||
} else {
|
||||
if (freeze) return;
|
||||
skeleton.SetToSetupPose();
|
||||
skeleton.PoseWithAnimation(startingAnimation, 0f, false);
|
||||
if (!string.IsNullOrEmpty(startingAnimation)) {
|
||||
skeleton.PoseWithAnimation(startingAnimation, 0f, false);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (skeletonDataAsset != null)
|
||||
Initialize(false);
|
||||
Initialize(true);
|
||||
}
|
||||
|
||||
}
|
||||
@ -93,16 +91,11 @@ public class SkeletonGraphic : MaskableGraphic {
|
||||
#endregion
|
||||
|
||||
#region Internals
|
||||
protected Spine.Unity.ISimpleMeshGenerator spineMeshGenerator; // This is any object that can give you a mesh when you give it a skeleton to render.
|
||||
protected Skeleton skeleton;
|
||||
protected Spine.AnimationState state;
|
||||
|
||||
// This is used by the UI system to determine what to put in the MaterialPropertyBlock.
|
||||
public override Texture mainTexture {
|
||||
get {
|
||||
if (skeletonDataAsset == null) return null;
|
||||
// Fail loudly when incorrectly set up.
|
||||
return skeletonDataAsset.atlasAssets[0].materials[0].mainTexture;
|
||||
return skeletonDataAsset == null ? null : skeletonDataAsset.atlasAssets[0].materials[0].mainTexture;
|
||||
}
|
||||
}
|
||||
|
||||
@ -153,14 +146,22 @@ public class SkeletonGraphic : MaskableGraphic {
|
||||
#endregion
|
||||
|
||||
#region API
|
||||
protected Skeleton skeleton;
|
||||
public Skeleton Skeleton { get { return skeleton; } }
|
||||
public Spine.AnimationState AnimationState { get { return state; } }
|
||||
public SkeletonData SkeletonData { get { return skeleton == null ? null : skeleton.data; } }
|
||||
public bool IsValid { get { return skeleton != null; } }
|
||||
|
||||
public event SkeletonGraphicDelegate UpdateLocal;
|
||||
public event SkeletonGraphicDelegate UpdateWorld;
|
||||
public event SkeletonGraphicDelegate UpdateComplete;
|
||||
protected Spine.AnimationState state;
|
||||
public Spine.AnimationState AnimationState { get { return state; } }
|
||||
|
||||
// This is any object that can give you a mesh when you give it a skeleton to render.
|
||||
protected Spine.Unity.ISimpleMeshGenerator spineMeshGenerator;
|
||||
public Spine.Unity.ISimpleMeshGenerator SpineMeshGenerator { get { return this.spineMeshGenerator; } }
|
||||
|
||||
public delegate void UpdateDelegate (SkeletonGraphic skeletonGraphic);
|
||||
public event UpdateDelegate UpdateLocal;
|
||||
public event UpdateDelegate UpdateWorld;
|
||||
public event UpdateDelegate UpdateComplete;
|
||||
|
||||
public void Clear () {
|
||||
skeleton = null;
|
||||
@ -194,12 +195,12 @@ public class SkeletonGraphic : MaskableGraphic {
|
||||
state.SetAnimation(0, startingAnimation, startingLoop);
|
||||
}
|
||||
|
||||
|
||||
public void UpdateMesh () {
|
||||
//Debug.Log("update mesh");
|
||||
if (this.IsValid) {
|
||||
skeleton.SetColor(this.color);
|
||||
spineMeshGenerator.Scale = canvas.referencePixelsPerUnit; // TODO: move this to a listener to of the canvas?
|
||||
if (canvas != null)
|
||||
spineMeshGenerator.Scale = canvas.referencePixelsPerUnit; // TODO: move this to a listener to of the canvas?
|
||||
|
||||
canvasRenderer.SetMesh(spineMeshGenerator.GenerateMesh(skeleton));
|
||||
this.UpdateMaterial();
|
||||
}
|
||||
|
||||
@ -1,10 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d85b887af7e6c3f45a2e2d2920d641bc
|
||||
timeCreated: 1455074790
|
||||
timeCreated: 1455576193
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
defaultReferences:
|
||||
- m_Material: {fileID: 2100000, guid: b66cf7a186d13054989b33a5c90044e4, type: 2}
|
||||
- skeletonDataAsset: {instanceID: 0}
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user