mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2025-12-20 17:26:01 +08:00
[unity] Updates to examples and editor fixes + new SpineAttributes
This commit is contained in:
parent
812b78ddd4
commit
f18a3cadb2
@ -75,13 +75,14 @@
|
||||
* **Two color tinting** is currently supported via extra UV2 and UV3 mesh vertex streams. To use Two color tinting, you need to:
|
||||
* switch on "Tint Black" under "Advanced...",
|
||||
* use the new `Spine/Skeleton Tint Black` shader, or your own shader that treats the UV2 and UV3 streams similarly.
|
||||
* **Clipping** is now supported. The SkeletonRenderers switches to slightly slower mesh generation code when clipping so limit your use of `ClippingAttachment`s when using on large numbers of skeletons.
|
||||
* **Clipping** is now supported. The SkeletonAnimation switches to slightly slower mesh generation code when clipping so limit your use of `ClippingAttachment`s when using on large numbers of skeletons.
|
||||
* **[SpineAttribute] Improvements**
|
||||
* **Icons have been added to SpineAttributeDrawers**. This should make your default inspectors easier to understand at a glance.
|
||||
* **Added Constraint Attributes** You can now use `[SpineIkConstraint]` `[SpineTransformConstraint]` `[SpinePathConstraint]`
|
||||
* **SpineAttribute dataField** parameter can also now detect sibling fields within arrays and serializable structs/classes.
|
||||
* **[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.
|
||||
* **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 SkeletonAnimation and SkeletonUtility component inspectors into its own utility window. You can access "Skeleton Debug" under the `Advanced...` foldout in the SkeletonAnimation inspector, or in SkeletonAnimation'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 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.
|
||||
|
||||
@ -0,0 +1,82 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes Software License v2.5
|
||||
*
|
||||
* Copyright (c) 2013-2016, Esoteric Software
|
||||
* All rights reserved.
|
||||
*
|
||||
* You are granted a perpetual, non-exclusive, non-sublicensable, and
|
||||
* non-transferable license to use, install, execute, and perform the Spine
|
||||
* Runtimes software and derivative works solely for personal or internal
|
||||
* use. Without the written permission of Esoteric Software (see Section 2 of
|
||||
* the Spine Software License Agreement), you may not (a) modify, translate,
|
||||
* adapt, or develop new applications using the Spine Runtimes or otherwise
|
||||
* create derivative works or improvements of the Spine Runtimes or (b) remove,
|
||||
* delete, alter, or obscure any trademarks or any copyright, trademark, patent,
|
||||
* or other intellectual property or proprietary rights notices on or in the
|
||||
* Software, including any copy thereof. Redistributions in binary or source
|
||||
* form must include this license and terms.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF
|
||||
* USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
namespace Spine.Unity.Modules {
|
||||
|
||||
public class SpineEventUnityHandler : MonoBehaviour {
|
||||
|
||||
[System.Serializable]
|
||||
public class EventPair {
|
||||
[SpineEvent] public string spineEvent;
|
||||
public UnityEvent unityHandler;
|
||||
public AnimationState.TrackEntryEventDelegate eventDelegate;
|
||||
}
|
||||
|
||||
public List<EventPair> events = new List<EventPair>();
|
||||
|
||||
ISkeletonComponent skeletonComponent;
|
||||
IAnimationStateComponent animationStateComponent;
|
||||
|
||||
void Start () {
|
||||
skeletonComponent = skeletonComponent ?? GetComponent<ISkeletonComponent>();
|
||||
if (skeletonComponent == null) return;
|
||||
animationStateComponent = animationStateComponent ?? skeletonComponent as IAnimationStateComponent;
|
||||
if (animationStateComponent == null) return;
|
||||
var skeleton = skeletonComponent.Skeleton;
|
||||
if (skeleton == null) return;
|
||||
|
||||
|
||||
var skeletonData = skeleton.Data;
|
||||
var state = animationStateComponent.AnimationState;
|
||||
foreach (var ep in events) {
|
||||
var eventData = skeletonData.FindEvent(ep.spineEvent);
|
||||
ep.eventDelegate = ep.eventDelegate ?? delegate(TrackEntry trackEntry, Event e) { if (e.Data == eventData) ep.unityHandler.Invoke(); };
|
||||
state.Event += ep.eventDelegate;
|
||||
}
|
||||
}
|
||||
|
||||
void OnDestroy () {
|
||||
animationStateComponent = animationStateComponent ?? GetComponent<IAnimationStateComponent>();
|
||||
if (animationStateComponent == null) return;
|
||||
|
||||
var state = animationStateComponent.AnimationState;
|
||||
foreach (var ep in events) {
|
||||
if (ep.eventDelegate != null) state.Event -= ep.eventDelegate;
|
||||
ep.eventDelegate = null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 90293750f472d3340b452cec6fea2606
|
||||
timeCreated: 1495263964
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -52,7 +52,7 @@ namespace Spine.Unity.Editor {
|
||||
if (spriteSlicesLabel == null) {
|
||||
spriteSlicesLabel = new GUIContent(
|
||||
"Apply Regions as Texture Sprite Slices",
|
||||
SpineInspectorUtility.UnityIcon(typeof(SceneAsset)),
|
||||
SpineEditorUtilities.Icons.unity,
|
||||
"Adds Sprite slices to atlas texture(s). " +
|
||||
"Updates existing slices if ones with matching names exist. \n\n" +
|
||||
"If your atlas was exported with Premultiply Alpha, " +
|
||||
|
||||
@ -259,10 +259,10 @@ namespace Spine.Unity.Editor {
|
||||
void DrawUnityTools () {
|
||||
#if SPINE_SKELETON_ANIMATOR
|
||||
using (new SpineInspectorUtility.BoxScope()) {
|
||||
isMecanimExpanded = EditorGUILayout.Foldout(isMecanimExpanded, SpineInspectorUtility.TempContent("SkeletonAnimator", SpineInspectorUtility.UnityIcon(typeof(SceneAsset))));
|
||||
isMecanimExpanded = EditorGUILayout.Foldout(isMecanimExpanded, SpineInspectorUtility.TempContent("SkeletonAnimator", SpineInspectorUtility.UnityIcon<SceneAsset>()));
|
||||
if (isMecanimExpanded) {
|
||||
EditorGUI.indentLevel++;
|
||||
EditorGUILayout.PropertyField(controller, SpineInspectorUtility.TempContent("Controller", SpineInspectorUtility.UnityIcon(typeof(Animator))));
|
||||
EditorGUILayout.PropertyField(controller, SpineInspectorUtility.TempContent("Controller", SpineInspectorUtility.UnityIcon<Animator>()));
|
||||
if (controller.objectReferenceValue == null) {
|
||||
|
||||
// Generate Mecanim Controller Button
|
||||
|
||||
@ -60,6 +60,7 @@ namespace Spine.Unity.Editor {
|
||||
static AnimBool showConstraintsTree = new AnimBool(false);
|
||||
static AnimBool showDrawOrderTree = new AnimBool(false);
|
||||
static AnimBool showEventDataTree = new AnimBool(false);
|
||||
static AnimBool showDataTree = new AnimBool(false);
|
||||
static AnimBool showInspectBoneTree = new AnimBool(false);
|
||||
|
||||
Vector2 scrollPos;
|
||||
@ -488,9 +489,25 @@ namespace Spine.Unity.Editor {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Data counts. bones, slots, constraints, skins, etc...
|
||||
showDataTree.target = EditorGUILayout.Foldout(showDataTree.target, SpineInspectorUtility.TempContent("Data Counts", Icons.spine), BoldFoldoutStyle);
|
||||
if (showDataTree.faded > 0) {
|
||||
using (new SpineInspectorUtility.IndentScope()) {
|
||||
using (new EditorGUILayout.FadeGroupScope(showDataTree.faded)) {
|
||||
using (new SpineInspectorUtility.LabelWidthScope()) {
|
||||
var skeletonData = skeleton.Data;
|
||||
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Bones", Icons.bone, "Skeleton.Data.Bones"), new GUIContent(skeletonData.Bones.Count.ToString()));
|
||||
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Slots", Icons.slotRoot, "Skeleton.Data.Slots"), new GUIContent(skeletonData.Slots.Count.ToString()));
|
||||
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Skins", Icons.skinsRoot, "Skeleton.Data.Skins"), new GUIContent(skeletonData.Skins.Count.ToString()));
|
||||
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Events", Icons.userEvent, "Skeleton.Data.Events"), new GUIContent(skeletonData.Events.Count.ToString()));
|
||||
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("IK Constraints", Icons.constraintIK, "Skeleton.Data.IkConstraints"), new GUIContent(skeletonData.IkConstraints.Count.ToString()));
|
||||
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Transform Constraints", Icons.constraintTransform, "Skeleton.Data.TransformConstraints"), new GUIContent(skeletonData.TransformConstraints.Count.ToString()));
|
||||
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Path Constraints", Icons.constraintPath, "Skeleton.Data.PathConstraints"), new GUIContent(skeletonData.PathConstraints.Count.ToString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (IsAnimating(showSlotsTree, showSkeleton, showConstraintsTree, showDrawOrderTree, showEventDataTree, showInspectBoneTree))
|
||||
if (IsAnimating(showSlotsTree, showSkeleton, showConstraintsTree, showDrawOrderTree, showEventDataTree, showInspectBoneTree, showDataTree))
|
||||
Repaint();
|
||||
}
|
||||
|
||||
|
||||
@ -294,7 +294,7 @@ namespace Spine.Unity.Editor {
|
||||
EditorGUILayout.Space();
|
||||
|
||||
using (new SpineInspectorUtility.LabelWidthScope()) {
|
||||
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Vertex Data", SpineInspectorUtility.UnityIcon(typeof(MeshFilter))), EditorStyles.boldLabel);
|
||||
EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Vertex Data", SpineInspectorUtility.UnityIcon<MeshFilter>()), EditorStyles.boldLabel);
|
||||
if (pmaVertexColors != null) EditorGUILayout.PropertyField(pmaVertexColors, PMAVertexColorsLabel);
|
||||
EditorGUILayout.PropertyField(tintBlack, TintBlackLabel);
|
||||
|
||||
|
||||
@ -245,6 +245,64 @@ namespace Spine.Unity.Editor {
|
||||
|
||||
}
|
||||
|
||||
[CustomPropertyDrawer(typeof(SpineIkConstraint))]
|
||||
public class SpineIkConstraintDrawer : SpineTreeItemDrawerBase<SpineIkConstraint> {
|
||||
|
||||
protected override Texture2D Icon { get { return SpineEditorUtilities.Icons.constraintIK; } }
|
||||
|
||||
protected override void PopulateMenu (GenericMenu menu, SerializedProperty property, SpineIkConstraint targetAttribute, SkeletonData data) {
|
||||
var constraints = skeletonDataAsset.GetSkeletonData(false).IkConstraints;
|
||||
|
||||
if (TargetAttribute.includeNone)
|
||||
menu.AddItem(new GUIContent(NoneString), string.IsNullOrEmpty(property.stringValue), HandleSelect, new SpineDrawerValuePair(string.Empty, property));
|
||||
|
||||
for (int i = 0; i < constraints.Count; i++) {
|
||||
string name = constraints.Items[i].Name;
|
||||
if (name.StartsWith(targetAttribute.startsWith, StringComparison.Ordinal))
|
||||
menu.AddItem(new GUIContent(name), name == property.stringValue, HandleSelect, new SpineDrawerValuePair(name, property));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[CustomPropertyDrawer(typeof(SpineTransformConstraint))]
|
||||
public class SpineTransformConstraintDrawer : SpineTreeItemDrawerBase<SpineTransformConstraint> {
|
||||
|
||||
protected override Texture2D Icon { get { return SpineEditorUtilities.Icons.constraintTransform; } }
|
||||
|
||||
protected override void PopulateMenu (GenericMenu menu, SerializedProperty property, SpineTransformConstraint targetAttribute, SkeletonData data) {
|
||||
var constraints = skeletonDataAsset.GetSkeletonData(false).TransformConstraints;
|
||||
|
||||
if (TargetAttribute.includeNone)
|
||||
menu.AddItem(new GUIContent(NoneString), string.IsNullOrEmpty(property.stringValue), HandleSelect, new SpineDrawerValuePair(string.Empty, property));
|
||||
|
||||
for (int i = 0; i < constraints.Count; i++) {
|
||||
string name = constraints.Items[i].Name;
|
||||
if (name.StartsWith(targetAttribute.startsWith, StringComparison.Ordinal))
|
||||
menu.AddItem(new GUIContent(name), name == property.stringValue, HandleSelect, new SpineDrawerValuePair(name, property));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[CustomPropertyDrawer(typeof(SpinePathConstraint))]
|
||||
public class SpinePathConstraintDrawer : SpineTreeItemDrawerBase<SpinePathConstraint> {
|
||||
|
||||
protected override Texture2D Icon { get { return SpineEditorUtilities.Icons.constraintPath; } }
|
||||
|
||||
protected override void PopulateMenu (GenericMenu menu, SerializedProperty property, SpinePathConstraint targetAttribute, SkeletonData data) {
|
||||
var constraints = skeletonDataAsset.GetSkeletonData(false).PathConstraints;
|
||||
|
||||
if (TargetAttribute.includeNone)
|
||||
menu.AddItem(new GUIContent(NoneString), string.IsNullOrEmpty(property.stringValue), HandleSelect, new SpineDrawerValuePair(string.Empty, property));
|
||||
|
||||
for (int i = 0; i < constraints.Count; i++) {
|
||||
string name = constraints.Items[i].Name;
|
||||
if (name.StartsWith(targetAttribute.startsWith, StringComparison.Ordinal))
|
||||
menu.AddItem(new GUIContent(name), name == property.stringValue, HandleSelect, new SpineDrawerValuePair(name, property));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[CustomPropertyDrawer(typeof(SpineAttachment))]
|
||||
public class SpineAttachmentDrawer : SpineTreeItemDrawerBase<SpineAttachment> {
|
||||
|
||||
|
||||
@ -82,7 +82,7 @@ namespace Spine.Unity.Editor {
|
||||
|
||||
public static Texture2D info;
|
||||
|
||||
// public static Texture2D unityIcon;
|
||||
public static Texture2D unity;
|
||||
// public static Texture2D controllerIcon;
|
||||
|
||||
public static void Initialize () {
|
||||
@ -120,7 +120,7 @@ namespace Spine.Unity.Editor {
|
||||
path = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-path.png");
|
||||
|
||||
info = EditorGUIUtility.FindTexture("console.infoicon.sml");
|
||||
// unityIcon = EditorGUIUtility.FindTexture("SceneAsset Icon");
|
||||
unity = EditorGUIUtility.FindTexture("SceneAsset Icon");
|
||||
// controllerIcon = EditorGUIUtility.FindTexture("AnimatorController Icon");
|
||||
}
|
||||
|
||||
|
||||
@ -75,7 +75,11 @@ namespace Spine.Unity.Editor {
|
||||
return current.type == EventType.ValidateCommand && current.commandName == "UndoRedoPerformed";
|
||||
}
|
||||
|
||||
public static Texture2D UnityIcon (System.Type type) {
|
||||
public static Texture2D UnityIcon<T>() {
|
||||
return EditorGUIUtility.ObjectContent(null, typeof(T)).image as Texture2D;
|
||||
}
|
||||
|
||||
public static Texture2D UnityIcon(System.Type type) {
|
||||
return EditorGUIUtility.ObjectContent(null, type).image as Texture2D;
|
||||
}
|
||||
|
||||
|
||||
@ -34,6 +34,10 @@ namespace Spine.Unity {
|
||||
readonly T b = new T();
|
||||
bool usingA;
|
||||
|
||||
public T GetCurrent () {
|
||||
return usingA ? a : b;
|
||||
}
|
||||
|
||||
public T GetNext () {
|
||||
usingA = !usingA;
|
||||
return usingA ? a : b;
|
||||
|
||||
@ -113,7 +113,17 @@ namespace Spine.Unity.Editor {
|
||||
[MenuItem("CONTEXT/SkeletonGraphic/Match RectTransform with Mesh Bounds")]
|
||||
static void MatchRectTransformWithBounds (MenuCommand command) {
|
||||
var skeletonGraphic = (SkeletonGraphic)command.context;
|
||||
var mesh = skeletonGraphic.GetComponent<MeshFilter>().sharedMesh;
|
||||
Mesh mesh = skeletonGraphic.GetLastMesh();
|
||||
if (mesh == null) {
|
||||
Debug.Log("Mesh was not previously generated.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (mesh.vertexCount == 0) {
|
||||
skeletonGraphic.rectTransform.sizeDelta = new Vector2(50f, 50f);
|
||||
skeletonGraphic.rectTransform.pivot = new Vector2(0.5f, 0.5f);
|
||||
return;
|
||||
}
|
||||
|
||||
mesh.RecalculateBounds();
|
||||
var bounds = mesh.bounds;
|
||||
@ -143,33 +153,6 @@ namespace Spine.Unity.Editor {
|
||||
EditorGUIUtility.PingObject(Selection.activeObject);
|
||||
}
|
||||
|
||||
// [MenuItem("Assets/Spine/Instantiate (UnityUI)", false, 20)]
|
||||
// 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, 20)]
|
||||
// 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;
|
||||
// }
|
||||
|
||||
// SpineEditorUtilities.InstantiateDelegate. Used by drag and drop.
|
||||
public static Component SpawnSkeletonGraphicFromDrop (SkeletonDataAsset data) {
|
||||
return InstantiateSkeletonGraphic(data);
|
||||
|
||||
@ -67,6 +67,18 @@ namespace Spine.Unity {
|
||||
Debug.LogError("Unity UI does not support multiple textures per Renderer. Your skeleton will not be rendered correctly. Recommend using SkeletonAnimation instead. This requires the use of a Screen space camera canvas.");
|
||||
} else {
|
||||
if (freeze) return;
|
||||
|
||||
if (!string.IsNullOrEmpty(initialSkinName)) {
|
||||
var skin = skeleton.data.FindSkin(initialSkinName);
|
||||
if (skin != null) {
|
||||
if (skin == skeleton.data.defaultSkin)
|
||||
skeleton.SetSkin((Skin)null);
|
||||
else
|
||||
skeleton.SetSkin(skin);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
skeleton.SetToSetupPose();
|
||||
if (!string.IsNullOrEmpty(startingAnimation))
|
||||
skeleton.PoseWithAnimation(startingAnimation, 0f, false);
|
||||
@ -171,6 +183,10 @@ namespace Spine.Unity {
|
||||
DoubleBuffered<Spine.Unity.MeshRendererBuffers.SmartMesh> meshBuffers;
|
||||
SkeletonRendererInstruction currentInstructions = new SkeletonRendererInstruction();
|
||||
|
||||
public Mesh GetLastMesh () {
|
||||
return meshBuffers.GetCurrent().mesh;
|
||||
}
|
||||
|
||||
public event UpdateBonesDelegate UpdateLocal;
|
||||
public event UpdateBonesDelegate UpdateWorld;
|
||||
public event UpdateBonesDelegate UpdateComplete;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user