Merge remote-tracking branch 'origin/master'

This commit is contained in:
NathanSweet 2016-02-16 20:49:17 +01:00
commit b139932dc2
11 changed files with 280 additions and 31 deletions

View File

@ -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);
}
}

View File

@ -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();
}

View File

@ -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);

View File

@ -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;
}

View File

@ -6,5 +6,6 @@
public interface ISimpleMeshGenerator {
float Scale { set; }
UnityEngine.Mesh GenerateMesh (Spine.Skeleton skeleton);
UnityEngine.Mesh LastGeneratedMesh { get; }
}
}

View File

@ -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;
}

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 78bba472871bc624f8930d51dea6dd3d
folderAsset: yes
timeCreated: 1455570938
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 0d81cc76b52fcdf499b2db252a317726
timeCreated: 1455570945
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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();
}

View File

@ -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: